我正在尝试在opencl内核中实现原子函数。我正在创建的多个线程并行尝试编写单个内存位置。我希望他们在该特定代码行上执行串行执行。我之前从未使用过原子功能。
我在许多博客和论坛上发现了类似的问题,我正在尝试一种解决方案。使用两个不同的函数'获取'和'释放'来锁定和解锁信号量。我已经包含了必要的opencl扩展,我的设备(NVIDIA GeForce GTX 630M)肯定支持这些扩展。
我的内核执行配置:
global_item_size = 8;
ret = clEnqueueNDRangeKernel(command_queue2, kernel2, 1, NULL, &global_item_size2, &local_item_size2, 0, NULL, NULL);
这是我的代码:reducer.cl
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
typedef struct data
{
double dattr[10];
int d_id;
int bestCent;
}Data;
typedef struct cent
{
double cattr[5];
int c_id;
}Cent;
__global void acquire(__global int* mutex)
{
int occupied;
do {
occupied = atom_xchg(mutex, 1);
} while (occupied>0);
}
__global void release(__global int* mutex)
{
atom_xchg(mutex, 0); //the previous value, which is returned, is ignored
}
__kernel void reducer(__global int *keyMobj, __global int *valueMobj,__global Data *dataMobj,__global Cent *centMobj,__global int *countMobj,__global double *sumMobj, __global int *mutex)
{
__local double sum[2][2];
__local int cnt[2];
int i = get_global_id(0);
int n,j;
if(i<2)
cnt[i] = countMobj[i];
barrier(CLK_GLOBAL_MEM_FENCE);
n = keyMobj[i];
for(j=0; j<2; j++)
{
barrier(CLK_GLOBAL_MEM_FENCE);
acquire(mutex);
sum[n][j] += dataMobj[i].dattr[j];
release(mutex);
}
if(i<2)
{
for(j=0; j<2; j++)
{
sum[i][j] = sum[i][j]/countMobj[i];
centMobj[i].cattr[j] = sum[i][j];
}
}
}
不幸的是,解决方案似乎对我不起作用。当我使用
将centMobj读回主机内存时ret = clEnqueueReadBuffer(command_queue2, centMobj, CL_TRUE, 0, (sizeof(Cent) * 2), centNode, 0, NULL, NULL);
ret = clEnqueueReadBuffer(command_queue2, sumMobj, CL_TRUE, 0, (sizeof(double) * 2 * 2), sum, 0, NULL, NULL);
对于centMobj和sumMobj,它给出了错误代码= -5(CL_OUT_OF_RESOURCES)的错误。
如果原子功能代码中存在任何问题,或者将数据读回主机内存,则无法获取。如果我错误地使用原子功能,请让我正确。 提前谢谢。
答案 0 :(得分:1)
在OpenCL中,工作项之间的同步只能在工作组中 完成。尝试在不同工作组之间同步工作项的代码可能在某些非常具体(以及依赖于实现/设备)的情况下工作,但在一般情况下将失败。
解决方案是使用atomics序列化对同一内存位置的访问(但不阻止任何工作项),或者以不同方式重新设计代码。