如何将多个fma操作链接在一起以获得性能?

use*_*710 4 c c++ floating-point fma

假设在一些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 )
Run Code Online (Sandbox Code Playgroud)

101*_*010 7

最近,在Build 2014中,Eric Brumer就这一主题发表了非常好的演讲(见这里).谈话的底线是

使用Fused Multiply Accumulate(aka FMA)无处不在会损害性能.

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

在此输入图像描述

然而,FMA似乎不是指令的冬青.正如您在下面的图片中看到的那样,FMA可以在某些引用中损害性能.

在此输入图像描述

以同样的方式,您的案例fma(triplet1) + fma(triplet2) + fma(triplet 3)成本为21个周期,而如果您使用FMA进行相同的操作则需要30个周期.这是性能提升30%.

在代码中使用FMA需要使用编译器内在函数.尽管如此,除非你是C++编译器程序员,否则FMA等并不是你应该担心的事情.如果不是,请让编译器优化处理这些技术问题.一般来说,在这种关注下,所有邪恶的根源(即,过早的优化),都可以解释其中一个伟大的(即Donald Knuth).

  • 这是一个相当幼稚和误导性的例子.它有点震惊,它来自编译工程师.在性能关键代码中,*latency*很少是主要的瓶颈.虽然a*b + c*d具有比fma(a,b,c*d)更低的延迟,但它需要3μs而不是2μs,这将其限制为在更常见的吞吐量主导的上下文中的性能的2/3.这种转变有一个合理的反对意见,但它涉及*数字*细节,而不是表现. (3认同)