ワープが「分割」されることはありません。それらは、条件付きで発散するコードパスを処理するために「条件付き実行」(つまり、参加していないスレッドをマスクした状態での実行)を必要とするか、または必要としません。
条件が複数の発散ワープを生成する方法については、次の不自然な例を検討してください。
if (threadIdx.x < 128) {
// Only first four warps process here
int modthirtytwo = threadIdx.x % 32;
if (modthirtytwo == 0) {
// Action A only first thread in the warp
} else {
// Action B for the other threads in the warp
}
}
ここで、コードは複数の発散ワープを生成する可能性があり、コンパイラーはコンパイル時に動作をモデル化できる必要があります。カーネルのコンパイラーに起動境界が指定されていれば、さらに良いでしょう。このケースを、ワープを1つだけ使用する共有メモリの削減と比較してください。
if (threadIdx.x < 32) {
if (threadIdx.x < 16) shm[threadIdx.x] += shm[threadIdx.x+16];
if (threadIdx.x < 8) shm[threadIdx.x] += shm[threadIdx.x+8];
if (threadIdx.x < 4) shm[threadIdx.x] += shm[threadIdx.x+4];
if (threadIdx.x < 2) shm[threadIdx.x] += shm[threadIdx.x+2];
if (threadIdx.x == 0) shm[0] += shm[1];
}
ここでは、発散はブロックごとに1つのワープに制限されています。そのテキストのすべては、2つの場合のコンパイラの動作が異なる可能性があるということです。
「新しい」コンパイラー(OpenCLで数年間使用されています)には、ブランチがより経済的になる前に使用する必要のある述語命令の数についてのヒューリスティックがあるようです。また、命令パイプラインの多くのブランチはパフォーマンスに良くないようです。そのため、コンパイラがそのコードがより高い「ブランチ密度」を生成することを理解できる場合、ブランチではなく、より多くの述語命令を優先します。