【问题标题】:Fastest way to implement floating-point multiplication by a small integer constant用一个小整数常量实现浮点乘法的最快方法
【发布时间】:2019-01-17 12:58:38
【问题描述】:

假设您试图将一个浮点数 k 乘以一个小的整数常量 n(我的意思是 -20 <= n <= 20)。这样做的天真方法是将n 转换为浮点数(就本问题而言,它不计入运行时)并执行浮点乘法。然而,对于n = 2k + k 似乎是一种更快的计算方式。在n,乘法指令比重复加法更快(如果n < 0,则在末尾加上反转)?

请注意,我在这里并不特别关心准确性;我愿意允许不合理的优化,只要它们得到大致正确的答案(即:最多 1024 ULP 错误可能没问题)。

我正在编写 OpenCL 代码,因此我对这个问题在许多计算环境(x86-64、x86-64 + AVX256、GPU)中的答案很感兴趣。

我可以对此进行基准测试,但由于我没有考虑特定的架构,我更喜欢选择的理论依据。

【问题讨论】:

  • 这真的取决于架构,因为有些可以快速从整数转换为浮点,有些则没有。如果可能,最好将 n 存储为浮点类型
  • 浮点乘法与当今的普通处理器一样快或几乎一样快。处理器的乘法单元可能比加法单元少,因此您可以在单位时间内完成更多的加法运算。否则,优化空间不大。
  • 如果您的值不存在溢出的风险,那么对于与 2、4、8 和 16 的乘法,您只需将指数分别增加 1、2、3 和 4。然后将中间结果相加(即 X*10 与 X*2 + X*8 相同)。但是 1)需要了解 FP 值的内部表示,以及 2)我不确定(还没有尝试过)这是否比简单的 X*10.0 更快。
  • @phuclv 我在问题中说整数到浮点数的转换不计入运行时(因为我在编译时知道所有相关整数)。

标签: performance floating-point opencl


【解决方案1】:

根据AMD's OpenCL optimisation guide for GPUs,第 3.8.1 节“指令带宽”,对于单精度浮点操作数,加法、乘法和“MAD”(乘加)在基于 GCN 的 GPU 上每个周期的吞吐量均为 5 .对于 24 位整数也是如此。只有当你转向 32 位整数时,乘法的成本才会高得多(1/周期)。 Int-to-float 转换和反之亦然也相对较慢(1/cycle),除非您有双精度浮点型模型(主要是 FirePro/Radeon Pro 系列或 nvidia 的 Quadro/Tesla),否则双精度操作非常慢(-(a + b) 在转换为 (-a) + (-b) 后编译为一条指令。

Nvidia GPU 在整数运算方面往往要慢一些,但对于浮点数,这与 AMD 的情况相似:乘法与加法一样快,如果您可以将它们组合成 MAD 运算,则可以使吞吐量翻倍。英特尔的 GPU 在其他方面完全不同,但它们在 FP 乘法和加法方面的速度也非常快。

基本上,在浮点乘法方面击败 GPU 真的很难,因为这基本上是他们优化的一件事。

在 CPU 上它通常更复杂 - Agner Fog's optimisation resources and instruction tables 是详细信息的地方。请注意,尽管在许多 CPU 上,您会因为将浮点数据解释为整数并返回而付出代价,因为 ALU 和 FPU 通常是分开的。 (例如,如果您想通过对其指数执行整数加法来优化浮点数乘以 2 的幂。在 x86 上,您可以通过使用第一个浮点指令,然后是整数指令对 SSE 或 AVX 寄存器进行操作来轻松地做到这一点,但它是通常不利于性能。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-25
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 1970-01-01
    相关资源
    最近更新 更多