CUDA 5.0和7.5之间的默认CUDA加法舍入模式

CUDA 5.0和7.5之间的默认CUDA加法舍入模式,cuda,double,rounding,Cuda,Double,Rounding,我有一个cuda循环,其中变量cumul以双精度存储累加: double cumulative_value = (double)0; loop(...) { // ... double valueY = computeValueY(); // ... cumulative_value += valueY } 此代码在不同的SDK上编译,并在两台计算机上运行: M1 : TeslaM2075 CUDA 5.0 M2 : TeslaM2075 CUDA 7.5

我有一个cuda循环,其中变量cumul以双精度存储累加:

double cumulative_value = (double)0;
loop(...)
{
    // ...
    double valueY = computeValueY();
    // ...
    cumulative_value += valueY
}
此代码在不同的SDK上编译,并在两台计算机上运行:

 M1 : TeslaM2075 CUDA 5.0
 M2 : TeslaM2075 CUDA 7.5
在步骤10,结果是不同的。此加法的值(十六进制的双精度表示法)为:

正如我在ptx cuda文件(=add.f64)中看到的那样,没有指定舍入模式,但M1似乎使用舍入到无穷大,而M1使用另一种模式

如果我使用此指令的4种舍入模式之一(uu dadd_XX())强制M2,则即使在步骤10之前,累积值也始终不同于M1。
但如果我强制M1和M2使用相同的舍入模式,结果是相同的,但不等于修改前的M1


我的目标是在M2机器(CUDA7.5)上获得M1(CUDA5.0)结果,但我不了解运行时的默认舍入模式行为。我想知道如果没有指定,rouding模式在运行时是否是动态的。你有什么想法吗?

在另一次ptx分析之后,在我的例子中,valueY是从cuda 5.0上的FMA指令计算出来的,而cuda 7.5编译器使用MUL和ADD指令。Cuda文档解释了只有一个舍入步骤使用单个FMA指令,而有两个舍入步骤使用MUL和ADD。非常感谢您对我的帮助:)

只是一个粗略的想法:您可以尝试创建CUBIN文件,并使用。这可能会带来一些关于PTX文件实际编译目的的见解。您确实需要使用cuobjdump来分解二进制代码,以确定指令级别上发生了什么。你能在你的问题中添加一个实际的复制案例吗?我认为这需要可编译的代码来理解这里发生了什么。CUDA 5和7.5的默认体系结构已更改,如果您使用默认编译设置,它可能与您现在为不同的指令集编译一样简单谢谢您的回答。我将尝试在最小的cuda内核上重现这种行为,并查看二进制文件。在另一次ptx分析之后,在我的例子中,valueY是根据cuda 5.0上的FMA指令计算的,而cuda 7.5编译器使用MUL和ADD指令。Cuda文档解释了只有一个舍入步骤使用单个FMA指令,而有两个舍入步骤使用MUL和ADD。非常感谢。@Calex您能将此作为答案发布吗?FMA的自动生成是一种优化,不同的编译器版本(以及不同的优化级别)可能会为给定代码生成不同数量的FMA。如果数字需求要求在某个地方使用FMA,我建议使用
FMA()
fmaf()
对其进行显式编码。要禁用FMA的自动生成,请使用编译器开关
-fmad=false
。这可能会对准确性和性能产生负面影响。为了防止单个加法或乘法收缩到FMA中,可以使用设备内部函数对它们进行编码:
\uu fadd\u rn()、\uu fmul\u rn()、\uu dadd\u rn()、\uu dmul\u rn()
   0x 41 0d d3 17 34 79 27 4d    => cumulative_value
+  0x 40 b6 60 1d 78 6f 09 b0    => valueY
-------------------------------------------------------
=    
  0x 41 0e 86 18 20 3c 9f 9b (for M1)
  0x 41 0e 86 18 20 3c 9f 9a (for M2)