我们不能在CUDA中对浮点变量使用原子操作吗?

时间:2013-07-01 07:11:23

标签: cuda nvidia

我使用atomicMax()来查找CUDA内核中的最大值:

__global__ void global_max(float* values, float* gl_max)
{
    int i=threadIdx.x + blockDim.x * blockIdx.x;
    float val=values[i];

    atomicMax(gl_max, val);
}

抛出以下错误:

  

错误:没有重载函数的实例“atomicMax”匹配参数列表

参数类型为:(float *, float)

5 个答案:

答案 0 :(得分:23)

atomicMax不适用于浮动类型。但您可以通过atomicCAS实现它:

__device__ static float atomicMax(float* address, float val)
{
    int* address_as_i = (int*) address;
    int old = *address_as_i, assumed;
    do {
        assumed = old;
        old = ::atomicCAS(address_as_i, assumed,
            __float_as_int(::fmaxf(val, __int_as_float(assumed))));
    } while (assumed != old);
    return __int_as_float(old);
}

答案 1 :(得分:7)

您需要将 float映射到orderedIntFloat 以使用 atomicMax

__device__ __forceinline__ int floatToOrderedInt( float floatVal ) {
 int intVal = __float_as_int( floatVal );
 return (intVal >= 0 ) ? intVal : intVal ^ 0x7FFFFFFF;
}
__device__ __forceinline__ float orderedIntToFloat( int intVal ) {
 return __int_as_float( (intVal >= 0) ? intVal : intVal ^ 0x7FFFFFFF);
}

答案 2 :(得分:3)

简短的回答是否定的。正如您在atomic function documentation中看到的那样,atomicMax仅支持整数参数,并且仅在计算能力3.5设备上支持64位整数参数。

答案 3 :(得分:2)

基于CUDA Toolkit Documentation v9.2.148,没有用于float的原子操作。 但是我们可以通过将atomicMax和atomicMin与有符号和无符号整数转换混合来实现它!

这是一个浮动原子最小值:

__device__ __forceinline__ float atomicMinFloat (float * addr, float value) {
        float old;
        old = (value >= 0) ? __int_as_float(atomicMin((int *)addr, __float_as_int(value))) :
             __uint_as_float(atomicMax((unsigned int *)addr, __float_as_uint(value)));

        return old;
}

这是一个浮动原子最大值:

__device__ __forceinline__ float atomicMaxFloat (float * addr, float value) {
    float old;
    old = (value >= 0) ? __int_as_float(atomicMax((int *)addr, __float_as_int(value))) :
         __uint_as_float(atomicMin((unsigned int *)addr, __float_as_uint(value)));

    return old;
}

答案 4 :(得分:0)

这是Atomic MAX的语法

int atomicMax(int* address,int val);

但是像atomicAdd这样的异常支持浮点数。