我正在尝试遵循https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html的B.12部分进行原子添加,该部分适用于浮点数。简单地从那里复制和粘贴代码并将类型更改为float无效,因为我无法执行atomicCAS操作所需的从GLOBAL到PRIVATE的强制转换指针转换。为了克服这个问题,我决定使用atomic_xchg(),因为它可用于浮点数,并带有附加的if语句,以实现与atomicCAS相同的功能。但是,每次运行程序时,对大型浮点向量执行加法运算时,都会返回不同的答案。
我试图弄清楚如何克服从GLOBAL到PRIVATE的显式转换,但是老实说,我不知道该怎么做,因此当我执行加法运算时,address参数被更改,而不是某些temp变量。 / p>
kernel void atomicAdd_2(volatile global float* address, float value)
{
float old = *address, assumed;
do {
assumed = old;
if (*address == assumed) {
old = atomic_xchg(address, value + assumed);
}
else{
old = *address;
}
// Note: uses integer comparison to avoid hang in case of NaN (since NaN != NaN)
} while (assumed != old);
}
这是我对floats的atomicAdd实现。
kernel void reduce_add(global const float* input, global float* output) {
float temp = 242.23f;
atomicAdd_floats(&output[0], temp);
printf(" %f ", output[0]);
}
这是我将参数提供给atomicAdd_floats的函数。注意,我的输入参数包含一个浮点数向量,而输出参数只是我要存储结果的位置,特别是在输出向量output [0]的第一个元素中;但是当我printf(“%f”,output [0]);时它显示了我的默认初始化值0。
答案 0 :(得分:0)
首先,我建议删除atomicAdd_2函数上的“ kernel”关键字。 “内核”应仅用于您打算从主机入队的功能。第二,有atomic-add-float on the net.
的OpenCL实现。然后,对于您尝试执行的操作,我有些困惑。您是否正在尝试对向量求和并在一个私有变量中求和?如果是这样,则使用atomicAdd没有任何意义。私有内存始终是原子的,因为它是私有的。仅全局性和局部性记忆才需要原子性,因为它们是共享的。 否则,我不确定为什么您提到将地址或GLOBAL更改为PRIVATE。
无论如何,链接中的代码应该可以工作,尽管它相对较慢。如果要求和的向量较大,则最好使用其他算法(部分和)。尝试使用Google搜索“ opencl并行和”或类似的方法。