为什么使用 FP32 而不是 FP64 时性能会提高 32 倍(而不是 2 倍)?

为什么使用 FP32 而不是 FP64 时性能会提高 32 倍(而不是 2 倍)?

考虑一下NVIDIA Quadro RTX 8000(规格如下)。使用它执行单精度(32 位精度)可获得 16.31 TFLOPS 的理论性能。如果我们将精度降低到半精度(16 位),理论性能双打达到 32.62 TFLOPS。但是,如果我们将精度从 32 位减半为 64 位,理论性能就会下降32倍达到 509.8 GFLOPS。为什么从 FP32 到 FP64 的性能损失比从 FP32 到 FP16 的性能提升要大得多?

在此处输入图片描述

我认识到对于每个 GPU 来说情况并非总是如此,但我的印象是,对于许多 GPU 而言,从 FP64 -> FP32 获得的收益比从 FP32 -> FP16 获得的收益大得多。

答案1

可能是因为单位内的默认寄存器大小是 32 位。

32 位寄存器可以保存两个 16 位值,这两个值可以相乘,从而使性能提高一倍。

另一方面,乘以 64 位值需要 4 个寄存器(两个 64 位值,每个分为 32 位部分)或在执行 64 位值的低 32 位和高 32 位之间进行内存加载/存储。处理溢出需要额外的加载/存储和字节,这可能会使用更多寄存器。在 32 位寄存器中执行 64 位浮点数学运算是可行的,但由于宽度是双倍,因此远非简单的减半。涉及大量额外的数学运算,因为您不能简单地“将这两个寄存器加在一起”,而是必须绕远路进行数学运算。

来自 Stack Overflow在 8086 asm 中将 64 位数字乘以 32 位数字

对于最终代码(合并);您最终会得到 8 条 MUL 指令、3 条 ADD 指令和大约 7 条 ADC 指令。

矢量处理器的重点在于它们指令和数据,甚至在具有大量带宽内存访问的 GPU 中,成本也非常高,尤其是当您的数据依赖于计算的先前部分时。出于偏好,矢量处理器只需要“针对这个巨大的数组运行这个简单代码”的流,而对一个数据进行大量重复运行会很快耗尽带宽和处理器核心。

有证据表明FP64 性能由于支持 FP64 的单元很少或根本没有,因此“游戏”卡的性能受到限制。结果,您最终只能在 32 位寄存器中“艰难地”进行 64 位数学运算。

相关内容