GPU上浮点数的划分与CPU上的浮点数划分不同

时间:2012-12-18 16:28:36

标签: cuda gpu

当我在GPU上划分两个浮点数时,结果为0.196405。当我在CPU上划分它们时,结果为0.196404。使用计算器的实际值为0.196404675。如何在GPU和CPU上进行划分?

3 个答案:

答案 0 :(得分:9)

正如对另一个答案的评论所表明的那样,有很多原因导致在CPU和GPU上运行浮点计算的相同结果是不现实的。它比这强得多:当相同的源代码针对不同的目标架构(例如x86或x64)或不同的优化级别进行编译时,你不能假设FP结果是相同的。

实际上,如果您的代码是多线程的,并且FP操作从一次运行到下一次运行以不同的顺序执行,那么在EXACT SAME SYSTEM上运行的EXACT SAME EXECUTABLE可能会产生从一次运行到下一次运行的稍微不同的结果。

其中一些原因包括但不限于:

  • 浮点运算不是关联的,所以看似良性的重新排序(例如上面提到的多线程的竞争条件)可以改变结果;
  • 不同的体系结构支持不同级别的精度和不同条件下的舍入(即编译器标志,控制字与每条指令);
  • 不同的编译器以不同的方式解释语言标准,
  • 某些架构支持FMAD(融合乘法 - 加法),有些则不支持。

请注意,出于本次讨论的目的,CUDA的JIT编译器(使PTX代码能够在未来可用的GPU架构中具有前瞻性的魔力)当然应该会扰乱FP结果。

尽管如此,你还是必须编写健壮的FP代码。

正如我今天写的那样,我相信CUDA GPU的浮点运算架构要比任何现代CPU都要好得多。 GPU包括原生IEEE标准(c.2008)对16位浮点和FMAD的支持,对非正规数有全速支持,并且能够在每个指令的基础上启用舍入控制,而不是控制其设置对所有FP指令有副作用的字并且变化很昂贵。

相比之下,CPU使用每线程状态过多且性能不佳,除非使用SIMD指令,主流编译器在利用性能方面很糟糕(因为使用标量C代码来利用这些指令集要困难得多)而不是为伪标量体系结构(如CUDA)构建编译器。如果要相信维基百科History页面,那么英特尔和AMD似乎已经完全拙劣地添加了FMAD支持,其方式无法描述。

您可以在此处找到关于浮点精度和NVIDIA GPU中IEEE支持的出色讨论:

https://developer.nvidia.com/content/precision-performance-floating-point-and-ieee-754-compliance-nvidia-gpus

答案 1 :(得分:1)

你没有。您永远不应该假设浮点值将完全等于数学运算后的预期值。它们仅被定义为对指定的精度是正确的,并且在处理器与处理器之间略有不同,无论该处理器是CPU还是GPU。例如,x86处理器实际上将默认执行具有80位精度的浮点计算,然后将结果截断为所请求的精度。浮点数的等效性比较应始终使用容差,因为不能保证任何两个处理器(或者甚至相同的处理器通过不同但数学上等效的指令序列)将产生相同的结果。例如。当且仅当|时,浮点数a和b应被视为相等a - b | <为了一些容忍度。

答案 2 :(得分:1)

哪个GPU用于计算?

如果使用单精度浮点运算,通常在尾数部分的第六位会有+ 1 / -1的精度误差。这是因为GPU中的四舍五入错误。

如果您使用双精度,您将获得在CPU中获得的精确精度。但速度几乎是浮点精度的一半,内存使用量将是2倍。 现在从基于FERMI的架构开始,NVIDIA GPU支持双精度点计算支持。