次のコードでワープ発散のペナルティが何であるかを理解しようとしています。原則として、ワープ発散がどのように処理されるかを理解しています (小さなブランチの述語命令、大きなブランチのワープ投票と分岐 - すべてのワープが一致する場合、それ以外の場合は述語命令と分岐なし、小さなブランチと同じ)。ただし、詳細はわかりません-中断/継続を伴うwhileループがどのように処理されるか。
以下の例では、scrapeEverythingCondition() がレーン X で true と評価されると、次のいずれかが発生します。
- 評価は n == N_N になるまで内側のループで進行し、レーン X は常に nops を評価し、i がインクリメントされ、すべてのレーンが連携するようになります。
- レーン X を除くすべての人が someMoreWork() を実行し、レーン X は nops を評価し、レーン X は someCostlyInitialization() を実行し、その後 n=0 を実行しますが、他のすべての人は nops を評価します。
- 私が考えていなかった他の何か。
コード:
__global__ void chainKernel() {
int i = threadIdx.x + blockIdx.x * blockDim.x;
while (i < N_I) {
someCostlyInitialization();
for(int n = 0; n < N_N; ++n) {
someStatisticsComputations(n);
if (scrapEverythingCondition(n)) {
// Everything we did for current i is no good. Scrap and begin again
i -= BLOCKS*THREADS;
break;
}
someMoreWork();
}
i += BLOCKS*THREADS;
}
}
PTX にコンパイルして結果のコードを調べてみましたが、複雑すぎました :(
編集:答えてくれたMakuに感謝します。また、コードの周りに散りばめられた昔ながらの printf() を使用して、答えを確認することもできました。どのスレッドがどこで、どのような順序で取得されたかを確認できました。実際、オプション 1 が正しいものです (レーン X は、内側の for ループが使い果たされるまで中断されます)。