1

在STREAM 博客之后的 openCL 中模拟原子的实现非常适用于 32 位、CPU 以及 NVIDIA 和 AMD GPU 上的原子添加。

基于cl_khr_int64_base_atomics扩展的 64 位等效项似乎可以在(pocl 和 intel)CPU 以及 NVIDIA openCL 驱动程序上正常运行。

不过,我无法在 AMD GPU 卡上运行 64 位 - 在 amdgpu-pro 和 rocm (3.5.0) 环境中,分别在 Radeon VII 和 Radeon Instinct MI50 上运行。

实现如下:

inline void atomicAdd(volatile __global double *addr, double val)
{
    union {
        long u64;
        double f64;
    } next, expected, current;
    current.f64 = *addr;
    do {
        expected.f64 = current.f64;
        next.f64 = expected.f64 + val;
        current.u64 = atomic_cmpxchg(
            (volatile __global long *)addr,
            (long) expected.u64,
            (long) next.u64);
    } while( current.u64 != expected.u64 );
}

在不支持双精度类型的原子操作的情况下,想法是利用转换为只要值只需要存储(不需要算术)。然后应该能够按照khronos 手册中long atom_cmpxchg(__global long *p, long cmp, long val)定义的int64 base atomics 使用。

我收到的两种 AMD 环境的错误都指向回退到 32 位版本,编译器似乎无法识别 64 位版本,尽管#pragma


/tmp/comgr-0bdbdc/input/CompileSource:21:17: error: call to 'atomic_cmpxchg' is ambiguous
                current.u64 = atomic_cmpxchg(
                              ^~~~~~~~~~~~~~
[...]/centos_pipeline_job_3.5/rocm-rel-3.5/rocm-3.5-30-20200528/7.5/out/centos-7/7/build/amd_comgr/<stdin>:13468:12: note: candidate function
int __ovld atomic_cmpxchg(volatile __global int *p, int cmp, int val);
           ^
[...]/centos_pipeline_job_3.5/rocm-rel-3.5/rocm-3.5-30-20200528/7.5/out/centos-7/7/build/amd_comgr/<stdin>:13469:21: note: candidate function
unsigned int __ovld atomic_cmpxchg(volatile __global unsigned int *p, unsigned int cmp, unsigned int val);
                    ^
1 error generated.
Error: Failed to compile opencl source (from CL or HIP source to LLVM IR).

不过,我确实在扩展列表上找到了cl_khr_int64_base_atomics对这两种环境的支持。opencl 驱动程序二进制文件中也存在。clinfocl_khr_int64_base

有人知道这里可能出了什么问题吗?对 32 位使用相同的实现(int 和 float 而不是 long 和 double)对我来说完美无缺......

感谢您的任何提示。

4

1 回答 1

1

对于 64 位,调用函数atom_cmpxchg而不是atomic_cmpxchg.

于 2021-04-22T11:41:25.683 回答