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

Pro*_*mer 8 cuda gpu

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

Arc*_*are 10

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

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

一些原因包括但不限于:

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

请注意,出于本讨论的目的,CUDA的JIT编译器(使PTX代码能够面向未来的GPU体系结构的魔力)当然应该会扰乱FP结果.

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

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

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

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

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