2017-03-26 9 views
1

OpenCL 1.2で問題があります。 私は__globalという配列をカーネルに持っており、グループサイズは1000です。 問題は、atomic_add()関数が正しく機能しないということです。OpenCL atomic_add()関数が間違った値を返します

私のカーネルのコードは次のとおりです。

__kernel void kernelfunction(__global uint32_t* buffer){ 

buffer[3] = 100; 

atomic_add(&buffer[3], 1); 

... 

} 

私は1000個のスレッドを作成した場合、私は右だ、buffer[3]の値は1100になります期待して? ですが、プログラムの動作は未定義です。 いつかそれは1100年、時には1064、時には1093と...私が試してみました何

次のようになります。

私はまた、以下のようなOpenCLの拡張機能を有効にします。

#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable

が、問題まだ存在する。 別のプロジェクトでは単純なopenclプロジェクトを作成し、atomic_addは正しく動作しています。ほとんどのプロジェクト構成を確認しましたが、どこに問題があるか分かりません。

お手伝いできますか? ありがとう

+0

いいえ、あなたは正しくありません。また、コードを適切にフォーマットする方法も検討する必要があります。私はあなたの最初の行が「楽しい時を過す」という理由を知りません。 –

答えて

3

アトミックでないと、単純なアクセスで同じ要素に競合が発生し、さらに悪いことに、すべてのデータが計算単位ごとにキャッシュされ、カーネルが終了するまで更新されない可能性があります。

buffer[3] = 100; 

これは未定義の動作です。結果は101であってもよい。

同じローカルグループ内の偶数スレッドは、同期コマンドがないと真のデータを持つことはできません。

gpuがスレッドを同時に実行するため、ホストによる初期化が必要です。逐次ではなく、アトミックを除く。または、他のグループからは見えない独自のグループを初期化し、その後同じグループ内の他のスレッドが正しく認識できるように、barrier(CLK_GLOBAL_MEM_FENCE)を追加します。

+0

ええ、あなたは正直でありがとうですが、時々私はOpenCLカーネルのバッファの要素3を変更(初期化)し、これと同じように振る舞いました:if(id == 0)buffer [ 3] = 100;問題は依然として残っています。私は今、親愛なるフセインに何をしますか?その後文章の場合は –

+0

、バリアを追加してください。これはそのワークグループに対してのみ機能します。グローバルスレッドの場合は、cpuホストプログラムで初期化する必要があります –

関連する問題