初期状態がさまざまな手法を使用して進化する大きなカーネルがあります。つまり、カーネルにループがあります。このループでは、特定の述語が現在の状態で評価され、この述語の結果で特定のアクションが実行されます。
カーネルは少しの一時データと共有メモリを必要としますが、大きいので 63 個のレジスタを使用し、占有率は非常に低くなります。
カーネルを多くの小さなカーネルに分割したいのですが、すべてのブロックが他のブロックから完全に独立しており、ホスト コードで 1 つのスレッドを使用して複数の小さなカーネルを起動することはできません。
ストリームがこの種の作業に適しているかどうかはわかりませんが、使用したことはありませんが、動的並列処理を使用するオプションがあるため、この種のジョブを実装するための良いオプションであると思います. カーネルからカーネルを起動するのは速いですか? サブカーネルで使用できるようにするために、グローバル メモリにデータをコピーする必要がありますか?
大きなカーネルを多くの小さなカーネルに分割し、必要に応じて必要なカーネルを呼び出すメイン ループを最初のカーネルに残しておくと (すべてのサブカーネルで一時変数を移動できるようになります)、占有率を増やすのに役立ちますか?
少し一般的な質問であることは知っていますが、このテクノロジーについては知りません。自分のケースに合うかどうか、またはストリームの方が優れているかどうかを知りたいです。
編集:他の詳細を提供するために、私のカーネルがこの種の構造を持っていると想像できます:
__global__ void kernel(int *sampleData, int *initialData) {
__shared__ int systemState[N];
__shared__ int someTemp[N * 3];
__shared__ int time;
int tid = ...;
systemState[tid] = initialData[tid];
while (time < TIME_END) {
bool c = calc_something(systemState);
if (c)
break;
someTemp[tid] = do_something(systemState);
c = do_check(someTemp);
if (__syncthreads_or(c))
break;
sample(sampleData, systemState);
if (__syncthreads_and(...)) {
do_something(systemState);
sync();
time += some_increment(systemState);
}
else {
calcNewTemp(someTemp, systemState);
sync();
do_something_else(someTemp, systemState);
time += some_other_increment(someTemp, systemState);
}
}
do_some_stats();
}
これは、メイン ループがあること、どこかで使用され、他のポイントでは使用されない一時データがあること、共有データ、同期ポイントなどがあることを示すためのものです。
スレッドはベクトルデータの計算に使用されますが、理想的には、各ブロックに 1 つのループが存在します (もちろん、それは正しくありませんが、論理的にはそうです)... 各ブロックに 1 つの「大きなフロー」があります。
さて、この場合のストリームの使用方法がわかりません...「大きなループ」はどこにありますか? 私が推測するホストでは...しかし、単一のループからすべてのブロックを調整するにはどうすればよいですか? これが私を最も疑わしくさせるものです。異なるホスト スレッド (ブロックごとに 1 つのスレッド) からのストリームを使用できますか?
大きなループを簡単に実行し続けることができたので、動的並列処理についてはあまり疑いがありませんが、ここで利点があるかどうかはわかりません。