2009-07-01 27 views
3

CUDAカーネルでは、次のようなコードがあります。私はスレッドごとに1つの分子を計算しようとしており、分母を計算して比を返すようにブロックに分子を累積しています。しかし、CUDAは、denomの値を、ブロック内のすべてのスレッドで計算されたnumer値の合計ではなく、最大のthreadIdx.xを持つブロック内のスレッドによって計算された値に設定しています。誰が何が起こっているか知っていますか?CUDA共有メモリ配列 - 奇妙な動作

extern __shared__ float s_shared[]; 

float numer = //calculate numerator 

s_shared[threadIdx.x] = numer; 
s_shared[blockDim.x] += numer; 
__syncthreads(); 

float denom = s_shared[blockDim.x]; 
float result = numer/denom; 

「結果」は常に0と1の間であるべきであり、ブロックを横切っ1に合計する必要があり、その代わりにそれはthreadIdx.xが最大であるすべてのスレッドの1.0に等しく、他のいくつかの値は限定されませんブロック内の他のスレッドの範囲に設定します。

答えて

4

合計がblockDim.xの場所に正しく同期されていません。どのスレッドも、合計を追加する前に他のスレッドが何を書き留めているかを見るのを待っていません。ソートの

  • 誰もがゼロを読み込み、
  • 家に行くように、ゼロ+のNUMERを計算します。
  • 高いスレッドIDは、B/Cそれが最後の演技の高い可能性を持って勝ちEveroneは、メモリ位置

にゼロ+のNUMERを書き込み、私は考えます。あなたの代わりに何をしたいのか

は、迅速な合計を行うために、バイナリ合計を行うことです s_shared[threadIdx.x]

  • に誰もが自分のNUMER
  • 半分のスレッドがペアと書き込みの合計を計算する書き込み新しい場所
  • スレッドの四分の一に、それらは、ペアのペアの和をcaluclate、およびyまで
  • など
  • 新しい場所にそれらを書き込みます1つのスレッドと1つの合計があります。

これはO(n)作業とO(log n)時間がかかります。

+4

これをメモするだけで、ここでのロジックは削減と呼ばれます。このサンプルはcuda sdkにいくつかあります。参照:cuda-sdk/C/src/reduction/reduction_kernel.cu –