9

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

4

3 回答 3

11

正如对另一个答案的评论所暗示的那样,有很多原因导致在 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

于 2012-12-19T08:27:23.383 回答
1

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

于 2012-12-18T19:00:12.050 回答
1

哪个 GPU 用于计算?

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

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

于 2012-12-19T09:13:08.757 回答