所以我应该在 FMA 和 MUL 之间受到惩罚
是的,从 Agner Fog 的表格中,您应该查看指令在哪些执行端口上运行。 这通常是您计算一系列不同指令的吞吐量所需的全部内容。(在像 Broadwell 这样的现代主流 x86 CPU 上,除 div/sqrt 之外的所有执行单元都是完全流水线的(可以在每个时钟周期启动一个新的 uop),因此只有一些奇怪的微编码指令loop
的吞吐量低于您从查看它们时所期望的微指令/端口。)
Agner 表中的实际“吞吐量”数字主要用作总结或指示任何奇怪之处,通常不直接有用,特别是对于有效的单微指令,如vmulps
or vfma...ps
。请参阅在预测现代超标量处理器上的操作延迟时需要考虑哪些注意事项以及如何手动计算它们?有关如何在延迟、后端端口瓶颈和前端 uop 吞吐量瓶颈方面预测多条指令块的性能的更多详细信息。
但是我的测量很顺利。我怀疑引擎盖下的处理器通过 FMA 交换 MUL 并添加空值,或者至少使用 FPU 中电路的相同部分,这解释了我的结果。
呵呵,不明白。你刚才说你认为 MUL 和 FMA 应该相互冲突,但现在你说你认为在 FMA 单元上运行 MUL 可以解释什么?
我怀疑最后一个英特尔架构像 FMA 一样执行助记符 MUL,但添加了一个空值(在 broadWell 架构上)。
几乎每个必须对 FP 结果进行归一化的 FP 操作(FP add 除外)都在 Broadwell 的 FMA 单元上运行。 但是 mul 和 add 在 Broadwell 上有 3 个周期延迟,而实际 FMA 有 5 个周期延迟,因此显然 FMA 单元有不同的配置。MUL/FMA 的吞吐量相同,但 Broadwell 的延迟不同。
(与丢弃单独添加单元的 Skylake 不同,mul/add 两者都具有与 FMA 完全相同的 4c 延迟/0.5c 吞吐量)。
在 Broadwell 中具有与 FMA 不同延迟的 MUL 是不寻常的;大多数 CPU 都以相同的性能运行它们,大概只是将 a0.0
输入到 add 输入中,或者等效的东西。
SIMD 整数乘法也使用 FMA 单元中的乘法器,整数移位也是如此。数量惊人的东西使用它,但特别是在 Skylake-X 中,它们会尽可能多地利用这些晶体管,而不是拥有更多 512 位宽的 SIMD 执行单元,这很有意义。
我目前正在按照模式执行二次多项式 (Pi) 的乘积。 P1*P2*P3*P4
你对结果做了什么? 你只做4人一组吗?你如何处理每组的结果?
或者你是在一个巨大的乘法链中将许多二次多项式相乘,创建一个 mulps 依赖链?
这将成为每个多项式 3 个周期的瓶颈,每个多项式 (2x FMA) 的独立计算为并行发生的 mulps 创建输入。在这种情况下,Broadwell 是您理想的 CPU,具有 3 个周期的 mulps 与 5 个周期的 Haswell 和 4 个周期的 Skylake。
但是,如果您可以假装 FP 数学是关联的并且具有不同的临时结果,您可以运行 2、3 或 4 个乘法链(甚至更多)并在最后组合,使用具有多个向量的展开循环。例如(P1*P3*P5*... ) * (P2*P4*P6*...)
,将循环外的最终乘法作为清理的一部分。
请参阅为什么 mulss 在 Haswell 上只需要 3 个周期,与 Agner 的指令表不同?有关使用多个累加器展开以隐藏 FP 延迟的更多信息。