我想在设备内存中使用具有非整数(浮点和双精度)的原子函数,例如,我在 CUDA C编程指南中看到了实现atomicAdd
的下一个代码双精度浮点数的函数:
代码:
#if __CUDA_ARCH__ < 600
__device__ double atomicAdd(double* address, double val)
{
unsigned long long int* address_as_ull =
(unsigned long long int*)address;
unsigned long long int old = *address_as_ull, assumed;
do {
assumed = old;
old = atomicCAS(address_as_ull, assumed,
__double_as_longlong(val +
__longlong_as_double(assumed)));
// Note: uses integer comparison to avoid hang in case of NaN (since NaN != NaN)
} while (assumed != old);
return __longlong_as_double(old);
}
#endif
是否可以在openCL中做类似的事情?我的设备具有2.1的计算能力
UPD
我设法写了一个与原代码等效的代码:
double atom_add_double(__global double* address, double val) {
__global long* address_as_ull =
(__global long*)address;
long old = *address_as_ull;
long assumed;
do {
assumed = old;
old = atom_cmpxchg(address_as_ull, assumed,
as_long(val + as_double(assumed)));
// Note: uses integer comparison to avoid hang in case of NaN (since NaN != NaN)
} while (assumed != old);
return as_double(old);
}
由于@pmdj,帖子回复中有更多详细信息。
答案 0 :(得分:1)
对于64位数据(double
),您需要测试cl_khr_int64_base_atomics
扩展名。如果您的实现支持此功能,则可以将atom_cmpxchg()
函数与long
/ ulong
(64位整数)值一起使用。
对于32位float
,atomic_cmpxchg
function是核心OpenCL 1.2及更高版本的一部分。如果您的实现仅支持OpenCL 1.0,则需要测试the cl_khr_global_int32_base_atomics
extension并使用其atom_cmpxchg()
函数(如果受支持)。
在OpenCL中,使用as_typen
运算符可以很容易地将浮点值的二进制表示形式处理为整数,反之亦然。 (或者,您可以使用union
类型,尽管在这种情况下这无济于事;有关详细信息,请参见OpenCL规范的6.2.4节。)在您的代码中,等效于__double_as_longlong
的类型为as_long()
,而您将使用__longlong_as_double
代替as_double()
。