4

假设在某些 C 或 C++ 代码中,我有一个名为的函数T fma( T a, T b, T c ),它执行 1 次乘法和 1 次加法,如下所示( a * b ) + c;我应该如何优化多个mul 和添加步骤?

例如,我的算法需要用 3 或 4 个 fma 操作链接并汇总在一起来实现,我如何编写这是一种有效的方法,我应该特别注意语法或语义的哪一部分?

我还想要一些关于关键部分的提示:避免更改 CPU 的舍入模式以避免刷新 cpu 管道。但我很确定,仅使用+多个调用之间的操作fma不应该改变这一点,我说“非常确定”,因为我没有太多 CPU 来测试这个,我只是遵循一些合乎逻辑的步骤.

我的算法类似于多个 fma 调用的总数

fma ( triplet 1 ) + fma ( triplet 2 ) + fma ( triplet 3 )
4

1 回答 1

7

最近,在 Build 2014 中,Eric Brumer 就该主题进行了非常精彩的演讲(请参阅此处)。谈话的底线是

在任何地方使用 Fused Multiply Accumulate(又名 FMA)会损害性能。

在 Intel CPU 中,一条 FMA 指令需要 5 个周期。相反,进行乘法(5 个周期)和加法(3 个周期)需要 8 个周期。使用 FMA,您将获得两项操作的奖励(见下图)。

在此处输入图像描述

然而,FMA 似乎并不是指令的圣杯。正如您在下图中看到的那样,FMA 在某些引用中会损害性能。

在此处输入图像描述

以同样的方式,您的案例fma(triplet1) + fma(triplet2) + fma(triplet 3)需要 21 个周期,而如果您在没有 FMA 的情况下执行相同的操作,则需要 30 个周期。这意味着性能提升了 30%。

在您的代码中使用 FMA 需要使用编译器内在函数。不过,在我看来,FMA 等不是你应该担心的,除非你是 C++ 编译器程序员。如果你不是,让编译器优化来处理这些技术问题。一般来说,在这种担忧之下是万恶之源(即,过早的优化),套用一个伟大的问题(即唐纳德·高德纳)。

于 2014-05-17T12:58:38.450 回答