最近、CUDA を使用してリダクションのアルゴリズムをテストしました (たとえば、http: //www.cuvilib.com/Reduction.pdf の 16 ページにあります)。しかし、最終的には原子性を使用しないという問題に遭遇しました。したがって、基本的には各ブロックの合計を計算して共有配列に格納します。次に、グローバル配列 x に戻します (tdx は threadIndex.x で、i はグローバル インデックスです)。
if(i==0){
*sum = 0.; // Initialize to 0
}
__syncthreads();
if (tdx == 0){
x[blockIdx.x] = s_x[tdx]; //get the shared sums in global memory
}
__syncthreads();
次に、最初の x 要素 (ブロックの数だけ) を合計します。アトミック性を使用すると正常に動作しますが (CPU と同じ結果)、以下のコメント行を使用すると動作せず、多くの場合「nan」が生成されます。
if(i == 0){
for(int k = 0; k < gridDim.x; k++){
atomicAdd(sum, x[k]); //Works good
//sum[0] += x[k]; //or *sum += x[k]; //Does not work, often results in nan
}
}
実際、atomicadd を直接使用して共有合計を合計していますが、これが機能しない理由を理解したいと思います。操作を単一のスレッドに制限する場合、アトミックな追加はまったくナンセンスです。そして、単純な合計はうまくいくはずです!