如果多个线程同时写入单个内存位置,则会出现竞争条件,对吧? 在我的情况下,情况正在发生..
考虑来自'reduce.cl'
的模块int i = get_global_id(0);
int n,j;
n = keyMobj[i]; // this n is the key..It can be either 0 or 1.
for(j=0; j<2; j++)
sumMobj[n*2+j] += dataMobj[i].dattr[j]; //summing operation.
这里,存储位置
sumMobj ===&GT; [... 0 ...,.... 1 ...]同时访问4个线程&amp;
sumMobj ===&GT; [.... 3 ...,.... 4 ...]同时访问6个线程..
有没有办法让它平行,比如使用锁定或信号量?因为这个求和在我的算法中是一个非常重要的部分......
答案 0 :(得分:3)
我可以给你一些提示,因为我也面临类似的问题。
我可以想到实现类似目标的三种不同方法:
考虑一个简单的内核,假设您启动了4(0-3)个线程
_kernel void addition (int *p)
{
int i = get_local_id(0);
p[4]+= p[i];
}
您想要添加值p [0],p [1],p [2],p [3],p [4],并将最终总和存储在p [4]中。对?即:
p[4]= p[0] + p[1] + p[2] + p[3] + p[4]
方法-1 (无并行)
将此作业分配给仅1个线程(无并行):
int i = get_local_id(0);
if (i==0)
{
p[4]+= p[i];
}
方法-2 (并行)
按如下方式表达您的问题:
p[4]= p[0] + p[1] + p[2] + p[3] + p[4] + 0
这是一个减少问题
所以启动3个线程:i = 0到i = 2。在第一次迭代中
i=0 finds p[0] + p[1]
i=1 finds p[2] + p[3]
i=2 finds p[4] + 0
现在你有三个数字,你应用与上面相同的逻辑并添加这些数字(使用合适的填充0来使它具有2的幂)
方法-3 原子操作
如果您仍需要以原子方式实现此功能,则可以使用atomic_add():
int fsfunc atomic_add ( volatile __global int *p ,int val)
描述
读取存储在指向位置的32位值(称为旧值) 通过p。计算(旧+ val)并将结果存储在p指向的位置。 该函数返回旧的。
这假设数据是int类型。否则,您可以按照上面的建议查看link。