1

複数のスレッドが同時に単一のメモリ位置を書き込んでいる場合、競合状態が発生しますよね?? 私の場合、同じことが起こっています。

'reduce.cl'のモジュールについて考えてみます。

int i = get_global_id(0);
int n,j;

n = keyMobj[i];                       // this n is the key..It can be either 0 or 1.
for(j=0; j<2; j++)
      sumMobj[n*2+j] += dataMobj[i].dattr[j];        //summing operation.

ここで、メモリ位置
sumMobj ===> [... 0 ...、.... 1 ...]は4つのスレッドに同時にアクセスされ、sumMobj ===> [.... 3 ...、。 ...4...]は6つのスレッドに同時にアクセスされます。

ロックやセマフォを使用するなど、並列化する方法はありますか?この合計は私のアルゴリズムの非常に大きな部分なので...

4

1 に答える 1

3

私も同様の問題に直面していたので、私はあなたにいくつかのヒントを与えることができます。

同様の目標を達成するための3つの異なる方法を考えることができます。

4(0-3)スレッドを起動したと仮定して、単純なカーネルを考えてみましょう。

_kernel void addition (int *p)
{
int i = get_local_id(0);
     p[4]+= p[i];
}

値p[0]、p [1]、p [2]、p [3]、p [4]を追加し、最終的な合計をp[4]に格納します。右?すなわち:

p[4]= p[0] + p[1] + p[2] + p[3] + p[4] 

方法-1 (並列処理なし)

このジョブを1つのスレッドのみに割り当てます(並列処理なし):

int i = get_local_id(0);
if (i==0)

{

p[4]+= p[i];

} 

方法2(並列処理あり)

次のように問題を表現します。

p[4]= p[0] + p[1] + p[2] + p[3] + p[4] + 0  

これは削減の問題です

したがって、3つのスレッドを起動します:i=0からi=2。最初の反復で

 i=0 finds p[0] + p[1]
 i=1 finds p[2] + p[3]  
 i=2 finds p[4] + 0

これで3つの数値が得られたので、上記と同じロジックを適用し、これらの数値を追加します(2の累乗にするために0の適切なパディングを使用)

方法-3不可分操作

それでもこれをアトミックに実装する必要がある場合は、atomic_add()を使用できます。

  int fsfunc atomic_add (   volatile __global int *p ,int val)

説明

pが指す位置に格納されている32ビット値(古いと呼ばれる)を読み取ります。(old + val)を計算し、pが指す場所に結果を保存します。関数は古いものを返します。

これは、データがint型であることを前提としています。それ以外の場合は、上記のリンクが表示されます。

于 2013-02-06T07:16:26.157 に答える