あなたが何を達成したいのか正確にはわかりません(何ごとに1回実行しますか?)ので、いくつかの代替案を示します。
ブロックごとに 1回ステートメントを実行する場合は、スレッド インデックスをテストするだけで実行できます。
__syncthreads();
if ((threadIdx.x | threadIdx.y | threadIdx.z) == 0) {
// statements that are only executed once per block
}
__syncthreads();
カーネル呼び出しごとにステートメントを 1 回実行する場合は、カーネルのブロックが特定の順序で実行されないため、ステートメントをいつ実行するかをもう少し具体的にする必要があります。
上記の例を単純に拡張すると、ステートメントがカーネル呼び出しごとに 1 回実行されるバージョンが得られますが、時間は指定されていません。
if ((threadIdx.x | threadIdx.y | threadIdx.z
| blockIdx.x | blockIdx.y | blockIdx.z) == 0) {
// statements that are executed once per kernel invocation,
// at an unspecified time
}
追加のグローバル メモリ帯域幅の使用を犠牲にして、グローバル メモリでアトミック操作を使用してステートメントを実行するタイミングを指定することができます。パフォーマンスへの影響を制限するには、通常、これらのアトミック操作をブロックごとに 1 回だけ実行することをお勧めします。
最初のブロックがそれに到達するとすぐにステートメントを実行したい場合は、グローバル フラグの簡単なテストで十分です。
__global__ volatile unsigned int statementHasExecuted;
...
__syncthreads();
if ((threadIdx.x | threadIdx.y | threadIdx.z) == 0) {
unsigned int state = atomicMin((unsigned int*)&statementHasExecuted, 1);
if (state == 0) {
// statements that are executed once per kernel invocation,
// as soon as the first block reaches the statement
// now make the results visible to the other blocks:
__threadfence();
// and signal that we are done:
atomicMin((unsigned int*)&statementHasExecuted, 2);
} else {
while (state < 2) {
// busy wait until execution of statement in other block has finished:
state = statementHasExecuted;
}
}
}
__syncthreads();
statementHasExecuted
カーネルを起動するたびにゼロにリセットする必要があります。
あなたが求めているのは、他のすべてのブロックが終了した後にのみ実行されるコードの一部である、逆のケースかもしれません。プログラミング ガイドの付録 B.5「メモリ フェンス関数」には、このためのサンプル コードが示されています。
(すべてのコードはブラウザーで作成され、テストされていないことに注意してください。エラーが含まれている可能性があります)。