CUDA - atomicAdd(float)不会添加非常小的值

时间:2013-11-25 10:01:53

标签: cuda

当我使用float atomicAdd(float *address, float val)添加小于约的浮点值时。 1e-390,添加无效,address的值仍为0。

这是最简单的代码:

__device__ float test[6] = {0};
__global__ void testKernel() {
    float addit = sinf(1e-20);
    atomicAdd(&test[0], addit);
    test[1] += addit;
    addit = sinf(1e-37);
    atomicAdd(&test[2], addit);
    test[3] += addit;
    addit = sinf(1e-40);
    atomicAdd(&test[4], addit);
    test[5] += addit;
}

当我将上面的代码作为testKernel<<<1, 1>>>();运行并使用调试器停止时,我看到:

test    0x42697800
    [0] 9.9999997e-21
    [1] 9.9999997e-21
    [2] 9.9999999e-38
    [3] 9.9999999e-38
    [4] 0            
    [5] 9.9999461e-41

注意test [4]和test [5]之间的区别。两者都做了同样的事情,但简单的添加工作,原子一个什么都没做。 我在这里缺少什么?

更新:系统信息:CUDA 5.5.20,NVidia Titan卡,驱动程序331.82,Windows 7x64,Nsight 3.2.1.13309。

1 个答案:

答案 0 :(得分:7)

atomicAdd是一个特殊指令,如果您在其他浮点运算中指定例如-ftz=true-ftz=false,则不一定遵循相同的刷新和舍入行为(例如普通的fp add)

PTX ISA manual中所述:

  

浮点运算.add是单精度,32位运算。 atom.add.f32舍入到最近的偶数并刷新次正常输入,结果为符号保留零。

因此,即使普通浮点数添加不应该将非正规数刷新为零,如果指定-ftz=false(这是默认值,我认为,对于nvcc),浮点原子添加操作全局内存将刷新为零(总是)。