我是opencl的新手,似乎有一些关于屏障功能的东西我不明白。这是我的内核的代码。这是用* w输出的标准矩阵向量计算。有1个工作组有64个工作单位,与矢量的维数相同opencl同步
#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);
此外,内核仅在每次程序运行时调用一次。随机行为是由多次运行程序产生的。
该评论让我看到我做错了什么。我将工作组和项目配置为
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);
感谢您的帮助。这对我来说很好,但可能对其他人不太感兴趣。
采取远离这一切最重要的是,在OpenCL内核的'barrier'功能只会充当工作组,而不是整个设备的屏障。 GPU上的设备范围同步是一个积极研究的话题。 – KLee1 2012-04-15 07:56:44