グローバルカウンタをゼロに設定し、いくつかの計算を行い、共有カウンタをインクリメントしてから、グローバルカウンタに異なるブロックの共有カウンタを追加するCUDAカーネルがあります。今私は、グローバルカウンタのインクリメントの前に初期化が行われることを確認したい。ここに私のカーネルの簡単な例です:グローバルメモリ変数を初期化した後のグローバル__syncthreads()
__global__ void counter_function(int32_t* global_count, int32_t* other_data)
{
__shared__ int32_t block_count;
bool condition = false;
// first thread of first block initializes global counter
if (thread.Idx == 0 && block.Idx == 0) {
*global_count = 0;
}
// do some calculation on other_data and possibliy set
// condition = true;
// increment counter if condition is true
if (condition) {
atomicAdd(&block_count, 1);
}
__synchthreads();
// first thread of each block adds its count to the global count
if (thread.Idx == 0) {
atomicAdd(&global_count, block_count);
}
}
私はCUDA Cプログラミング・ガイドのMemory Fence FunctionsとSynchronization Functionsを読んでいるが、__syncthreads()
が唯一のブロックごとにスレッドを同期して__threadfence()
だけの世話をするので、解決策を見つけることができませんでした私が理解している限り、スレッド内のグローバル読み書き操作の順序。また、グローバルカウントを初期化するスレッドを除くすべてのスレッドは、グローバル書き込み操作を1つしか持たないため、私の場合でも使用できません。私は__threadfence()
の機能を正しく理解していますか?
1つの方法は、カーネルを2つのカーネルに分割することです。そのため、基本的にカウンタをゼロに設定するだけの別個のカーネルが必要です。しかし、より良い方法がありますか?
これを解決する方法を教えてください。または私は何かを逃していますか?
"//最初のブロックの最初のスレッドはグローバルカウンタを初期化します"最初のブロックの最初のスレッドが最初に実行されるという保証は(CUDAでは)ありません。大きなグリッドでは、最初のブロックが他のブロック*が完了するまで実行を開始しない可能性があります*。また、カーネルの立ち上げ以外には、CUDAにはグローバル同期メカニズムはありません。したがって、カーネルを起動する前に、ホスト上で 'global_count'を初期化してください。カーネルの前に、 'cudaMemset(global_count、0、sizeof(int32_t));で簡単に行うことができます。それはあなたの質問の範囲ですか? –
はい、それは私の質問の範囲です。ありがとう。私の場合は、http://stackoverflow.com/questions/6404992/cuda-block-synchronization \ suggestsの回答として余分なカーネルを呼び出すほうが良いようです。 – denisalevi