1

1-D 配列の最初の k 要素のそれぞれをオフセットで移動する必要があります。ここで、オフセットは単調に増加します。つまり、要素 i のオフセットが offset1 の場合、要素 i+1 は次を満たすオフセット、offset2 を持ちます: offset2 >= オフセット 1。

最初の k 個の要素のそれぞれで実行されるカーネルを作成しました。

if (thread_id < k) {

  // compute offset

  if (offset) {
    int temp = a[thread_id];

    __synchthreads();

    a[thread_id + offset] = temp;
  }
}

ただし、k = 3 についてテストすると、オフセットは実際には 0、1、1 と単調に増加します。要素 0 は、期待どおりにその位置にとどまります。ただし、要素 1 は、(要素 1 のオフセットに従って) 要素 2 だけでなく、要素 3 にもコピーされます。

つまり、スレッド 1 が要素 1 から要素 2 へのコピーを完了した後でのみ、スレッド 2 が要素 2 を読み取り、temp のコピーに格納するように見えます。

何が間違っていて、どうすれば修正できますか?

ありがとうございました!

4

1 に答える 1

3

あなたがしていることは、分散操作に一般化されます。

thread   0  1  2  3  4
in  =  { 1, 4, 3, 2, 5}
idx =  { 1, 2, 3, 4, 0}

out[idx] = in[i]

一般に、スレッドは他のスレッドが書き込む場所から読み取るため、スキャッターは並列でその場で行うことはできません。この例では、スレッド 1 が出力場所を書き込んだ後にスレッド 2 が入力場所を読み取ると、誤った結果が得られます。これは競合状態であり、同期またはアウトオブプレース ストレージが必要です。

この場合の大きな配列の同期はグローバル同期であり、CUDA プログラミング モデルではサポートされていないため、アウトオブプレース スキャッタを使用する必要があります。

つまり、これを行うことはできません。

temp = in[thread_idx]
global-sync
in[thread_idx + offset] = temp

これを行う必要があります:

out[i + offset] = in[thread_idx]

Whereoutは と同じメモリを指していませんin

于 2013-02-19T10:58:23.073 に答える