2016-10-05 2 views
2

openCL C++で作業しているときにこの非常に奇妙な問題が発生しました。問題は、100個のスレッドのそれぞれが100個のサイズの配列の1つの要素にアクセスしていることです。 0から63まで、問題はなく、各スレッドは配列の要素の値を適切に計算し更新します。ここでOpenCL C++ - スレッド64の後の配列のメモリ管理エラー

私はカーネルを呼び出す方法です。しかし、それは64のスレッド化になったときに、それが台無しにし、他のいくつかの値を使用して値を更新...:

kernelGA(cl::EnqueueArgs(queue[iter], 
         cl::NDRange(200/numberOfDevices)), 
         d_value, 
         d_doubleParameters, 
         buf_half_population, and so on...) 

カーネル側では、私はそれぞれにアクセスしていますが

__kernel void kernelGA (__global double * value, 
         __global double * doubleParameters, 
         __global double * population, 
         __global double * scores, and so on...) 

int idx = get_global_id(0); // This gives me 100 threads for each device. (I have two devices) 
int size_a = 50; 
double tempValue[size_a]; 

// Copying the global "value" into local array so each thread has its own copy. 
for (int i = 0; i < size_a; i++) { 
    tempValue[i] = value[i]; 
} 

この時点で、各スレッドは同じ値を持つ独自のtempValue []配列を持つようになりました。そして、私はこの後

// Applying some computations on tempValue and changing the values for each copy of tempValue for each thread. 
tempValue[i] = some calculations for each thread... 

...各スレッドのtempValue []配列の値のいくつかの計算や数式を適用し、私は、スレッドごとにtempValue []配列の各要素にアクセスし、中に継続的にそれらを元に戻しますより大きなサイズの配列(スレッドの数* size_a)。念頭に置いておくと、配列のためのインデックスは次のように行くこと:0,1、2、3、...のように...

for (int i = 0; i < size_a; i++) { 
    totalArray[(idx * size_a) + i] = tempvalue[i]; 
} 

だから私は、カーネルの外totalArrayの答えを取得し、それらを印刷するとき最初の64個(0〜63)のスレッドはtotalArray []に値を適切に配置しています。しかし、64を超えると、索引付けが乱れてしまいます。私は索引だけを印刷し、索引はすべてのスレッドに対して適切にアクセスしているため、索引付けは正確ではありません。しかし、値が混乱しているようです...

たとえば、スレッド0-63の3番目、4番目、5番目および6番目の要素の値は、それぞれ50,60,70および80です。しかし、スレッド64以降では、第3、第4、第5および第6要素の値は80,90,100,110である。あたかも値が逆方向に少数の要素だけシフトされているかのように。どうして?ここで何が起こっているのですか?

答えて

0

だから、私は問題の解決策が見つかりました:配列の

// Copying the global "value" into local array so each thread has its own copy. 
for (int i = 0; i < size_a; i++) { 
    tempValue[i] = value[i]; 
} 

値:

問題は、各スレッドがtempValue[]配列に格納されvalue[]配列の独自のコピーを持っていたにもかかわらず、ということでしたスレッド64の後で乱されていた。だから、私はホストコード(sizeOf(value) * 100)の外に大きな値の配列を作成し、残りの99の部分に配列の最初の部分をコピーして、それをデバイスに送りました。そして、インデックスを使って各スレッドにvalue []配列の独自の部分にアクセスさせました。

問題を解決しました。

0

同じアレイ上で動作する複数のデバイスが、

あなたは範囲

として

cl::NDRange(200/numberOfDevices) 

を入れたがためのオフセットとして、あなたは

cl::NDRange((200/numberOfDevices)*deviceIndex) 

を入れていない場合は問題があります各デバイス。

近隣のグループの代わりに同じ位置に書き込もうとするすべてのデバイス。

また、カーネルの総スレッド数が配列の長さよりも小さいかどうかをチェックしていないため、一部のスレッドが境界からの書き込みを試みることがあります。

+0

合計スレッド数が配列の長さよりも小さいかどうかを確認するにはどうすればよいですか? –