使用 dword 或 qword 参数的 fdiv 更快吗?

Is fdiv faster with a dword or qword argument?

提问人:pts 提问时间:5/16/2023 最后编辑:Peter Cordespts 更新时间:5/16/2023 访问量:96

问:

我可以在以下 80387 指令之间进行选择:

fdiv dword ptr a

fdiv qword ptr b

数字 和 是等价的,它们都是 100% 准确的。ab

我应该选择版本有什么理由吗?我只能把速度看作是一种好处。现代处理器有区别吗?80387 或 80487 有区别吗?qword

程序集 x86 浮点 CPU 架构 x87

评论

1赞 Jester 5/16/2023
除了从内存中加载额外字节的可能成本外,没有区别。 速度通常只取决于控制字选择的结果精度,而不取决于操作数大小。无论如何,dword 版本更小,只能更快,所以我会选择它。请注意,FPU 内部使用 80 位,因此两个版本都需要转换。因为英特尔手册明确指出,“指令在执行除法之前将整数源操作数转换为双倍扩展精度浮点格式。因此,这可能也适用于浮动。fdivFIDIV
1赞 fuz 5/16/2023
@Jester 从技术上讲,FPU 内部可以是 32、64 或 80 位。不确定流行操作系统上的默认值是什么。
0赞 chux - Reinstate Monica 5/16/2023
“我有理由选择qword版本吗?” -->它会提供更准确的答案。
0赞 pts 5/16/2023
@chux-ReinstateMonica:为什么它会给出一个更准确的答案?就我而言,两个输入(st(0) 和 a/b)都是 100% 准确的。为什么 a 和 b 的答案会有所不同?
1赞 chux - Reinstate Monica 5/16/2023
@pts,问题有“数字 a 和 b 是等价的,它们都是 100% 准确的”,而不是“在我的情况下,两个输入(st(0) 和 a/b)都是 100% 准确的。它是什么?你是说商是 100% 准确的——没有四舍五入误差?

答:

6赞 Peter Cordes 5/16/2023 #1

dword大小永远不会变慢。(除非由于一些次要影响,例如此处的内存位置较窄,导致其他一些数据未对齐。

在大多数 CPU 上,我认为除了数据传输时间之外,当它的值相同时,速度会相同。qword

在某些 CPU 上,如果尾数的低位不是全部为零(因此除数的有效位比 dword 浮点数更适合),则速度可能会更慢。除非“整数”早期情况仅适用于有效位少得多的数字。


在 P5 Pentium 之前,传输 qword 比传输 dword 需要更多的周期,因为直到 P5 Pentium 才将数据路径拓宽到 64 位。(除非 486DX 可以在 FPU 及其内部缓存之间传输 64 位?64 位原子性保证是 P5 的新功能。

我认为内存源 FP 数学运算相当于首先将1 位拓宽到 80 位,就 FPU 本身看到的数据而言,因此表示与 dword float32 完全相同的值的 qword float64 一旦完成加载内存操作数,将导致对实际 FPU 工作的相同输入。fld

对于指令,性能不依赖于输入数据或 x87 控制字中的精度设置(它必须为输出生成多少尾数位),至少在 P5 或更高版本上不取决于。faddfsubfmul

但是,确实取决于精度设置。https://agner.org/optimize/ 指令表最早只包括 P5。 P5 上输出尾数精度设置为 24、53 或 64 位的周期为 19/33/39。降低精度会加快 fdiv/fsqrt 的速度,但会损害所有内容的精度: 有趣的事实:默认情况下,Direct3D 会将 FPU 精度降低到最小 24 位,这可能是因为 3D 几何图形对矢量的大小执行大量 sqrt 和除法。fdivfsqrtfdiv

在某些 CPU 上,性能取决于实际数据。在许多 CPU 上,Agner Fog 的指令表都包含有关 fdiv 时序的注释。AMD K7 的第一个注释说:“低值 [时钟周期计数] 适用于整除数,例如 2 的幂。2 的幂是最圆的,尾数为全零,但措辞意味着其他值也可以有点圆,并且需要更少的周期。fdiv

所以我猜不仅仅是 2 的幂速度快。一个 qword float64 也是一个精确的 float32,有点圆:只有 23 个非零尾数位,低 29 位全部为零。但这仍然是许多非零尾数位的潜在数量;对于任何特殊情况来说,可能太多了,IDK。

后来的注释更简洁,只是提到了“圆除数”,但想必他的意思是一样的,而不仅仅是 2 的幂作为唯一的特例。

Pentium-M / Core Solo/Duo 具有 8 到 37 个周期(以及类似的周期),Agner Fog 的注释说“高值是典型的,低值是低精度或整数除数。我认为“低精度”是指 x87 控制字设置。我不知道“圆除数”是否仅表示 2 的幂(全零尾数),或者它是否有多圆,比如重要的尾数位有多少。对于整数 / 在 P-M / Core 1 上,注释的开头相同,但添加了“Core Solo/Duo 是 在具有允许早期算法的舍入值的情况下,比 Pentium M 更有效。fdivdivsddividiv

具有此类注释的 CPU:

  • K7、K8:整除法更快

  • K10 提到速度取决于被红利绝对值中的有效位数,并查看 AMD 的优化手册。但没有注意,K10 上的固定延迟/吞吐量。山猫/美洲虎也一样。idivfdiv

  • 推土机系列:可变的延迟和吞吐量(并且部分流水线的吞吐量优于延迟),但没有说明何时。fdiv

  • Zen 1:可变延迟和吞吐量,无注意事项

  • Zen 2 到 Zen 4:延迟 = 15 个周期,吞吐量 = 每 6 个周期一个。fdiv

  • P5 奔腾:FDIV 需要 19、33 或 39 个时钟周期,精度分别为 24、53 和 64 位。FIDIV 需要 3 个时钟。精度由位 8-9 定义 浮点控制字的

  • P6 奔腾 II / III:FDIV 延迟取决于控制字中指定的精度:64 位精度 提供 38 的延迟,53 位精度提供 32 的延迟,24 位精度的延迟提供 18。除以 2 的幂需要 9 个时钟。倒数吞吐量为 1/(latency-1)。(不依赖于上述数据值)

  • 奔腾 M / Core (1) Duo/Solo:高值为典型值,低值表示低精度或整除数。

  • 核心 2 Merom 和 Wolfdale 以及 Nehalem:圆除数或低精度给出低值。

  • 没有关于 Sandybridge 或更晚的注释:时序为 lat = 10-24c,snB 的往复吞吐量 = 10-24c。 IvB / Haswell 略微流水线化(吞吐量比延迟好几个周期),Broadwell 是吞吐量明显优于延迟。fdiv

  • 奔腾 4: 延迟和倒数吞吐量取决于 F.P 中的精度设置。 控制词。单精度:23、双精度:38、长双精度 (默认值):43。并且在使用 FP-DIV 单元期间,FP-MUL 单元的吞吐量也会降低。 (尽管是单个 uop 问题/调度。fdiv

  • Atom / Silvermont / Goldmont (plus) / Tremont:延迟和吞吐量是固定的,甚至没有提到精度设置有帮助。fdiv

  • 通过 Nano 2000 / 3000:fdiv 延迟和吞吐量为 15-42 (Nano 2000) 或 14-23 个周期 (Nano 3000)。没有音符,所以也许只是精确控制。


脚注 1:拓宽是相当微不足道的:在尾数底部填充零,并调整偏置指数场,使其表示 2 的相同幂。80 位格式还在尾数中使用显式而不是隐式前导(或次正态),以便从指数字段解码该位。10

对于 dword 或 qword 加载,解码过程的工作量应该相同;P5 Pentium 在一个时钟周期内运行。fld m32 / m64