opencl内核线程中的竞争条件

时间:2013-01-21 07:58:43

标签: opencl gpu gpgpu gpu-programming

如果多个线程同时写入单个内存位置,则会出现竞争条件,对吧? 在我的情况下,情况正在发生..

考虑来自'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个线程..

有没有办法让它平行,比如使用锁定或信号量?因为这个求和在我的算法中是一个非常重要的部分......

1 个答案:

答案 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