私はopenclが初めてで、バリア機能について理解できないことがあるようです。これは私のカーネルのコードです。これは、出力が *w の標準的な行列ベクトル計算です。ベクトルの次元と同じ 64 個の作業単位を持つ 1 つの作業グループがあります。
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__kernel void fmin_stuff(__global double *h, __global double *g, __global double
*w,int n,__global int * gid) {
// Get the index of the current element
int i = get_global_id(0);
int j;
gid[i]=get_local_id(0);
w[i]=-g[i];
barrier(CLK_GLOBAL_MEM_FENCE | CLK_LOCAL_MEM_FENCE);
for (j=0;j<n;j++)
{
if (j<i)
w[i]-=h[i+j*n]*w[j];
barrier(CLK_GLOBAL_MEM_FENCE | CLK_LOCAL_MEM_FENCE);
}
}
問題は、コードがランダムに失敗することです。出力はしばらくの間正しいです。各実行の w の初期値は次のとおりです。
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.72261 2.80155
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.72261 2.80155
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.72261 2.80155
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.72261 2.80155
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.72261 2.80155
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.72261 2.80155
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.34999 2.51524
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.72261 2.80155
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.72261 2.80155
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.72261 2.10141
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.72261 2.80155
-0.148351 -0.309007 0.133204 -1.39589 2.88335 -2.68636 2.77369
プログラムは、いずれの場合もカーネルが正常に実行されたことを報告します。すべての実行で、ベクトル w の値は最終的に不正確になります。アドバイスをいただければ幸いです。
これが単純な行列の乗算であるかどうかについて、いくつかの混乱がありました。そうではない。これは、w の最初の 5 つの項のみを含めるコードで達成しようとしていることです。
w(1)=-g(1);
w(2)=-g(2);
w(3)=-g(3);
w(4)=-g(4);
w(5)=-g(5);
w(2)-=h(2)*w(1);
w(3)-=h(3)*w(1);
w(4)-=h(4)*w(1);
w(5)-=h(5)*w(1);
w(3)-=h(3+N)*w(2);
w(4)-=h(4+N)*w(2);
w(5)-=h(5+N)*w(2);
w(4)-=h(4+2*N)*w(3);
w(5)-=h(5+2*N)*w(3);
w(5)-=h(5+3*N)*w(4);
また、カーネルは、プログラムの実行ごとに 1 回だけ呼び出されます。ランダムな動作は、プログラムを複数回実行した結果です。
コメントのおかげで、自分が何を間違っていたのかがわかりました。ワークグループとアイテムを次のように構成しました
size_t global_item_size[3] = {N, 1, 1}; // Process the entire lists
size_t local_item_size[3] = {1,1,1}; // Process in groups of 64
ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL,
global_item_size, local_item_size, 0, NULL, NULL);
あるべきだったとき。
size_t global_item_size[3] = {N, 1, 1}; // Process the entire lists
size_t local_item_size[3] = {N,1,1}; // Process in groups of 64
ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL,
global_item_size, local_item_size, 0, NULL, NULL);
助けてくれてありがとう。これは私にとっては素晴らしいことですが、おそらく他の人にとってはあまり興味がありません。