我试图通过查看生成的汇编代码来了解使用带有双参数的 std :: fma 是否有利,我正在使用标志“ -O3”,并且正在比较这两个例程的组装:
#include <cmath>
#define FP_FAST_fmaF
float test_1(const double &a,const double &b,const double &c ){
return a*b + c;
}
float test_2(const double &a,const double &c ){
return std::fma(a,b,c);
}
使用Compiler Explorer工具,这是为两个例程生成的程序集:
test_1(double const&,double const&,double const&):
movsd xmm0,QWORD PTR [rdi] #5.12
mulsd xmm0,QWORD PTR [rsi] #5.14
addsd xmm0,QWORD PTR [rdx] #5.18
cvtsd2ss xmm0,xmm0 #5.18
ret #5.18
test_2(double const&,double const&):
push rsi #7.65
movsd xmm0,QWORD PTR [rdi] #8.12
movsd xmm1,QWORD PTR [rsi] #8.12
movsd xmm2,QWORD PTR [rdx] #8.12
call fma #8.12
cvtsd2ss xmm0,xmm0 #8.12
pop rcx #8.12
ret
并且使用icc或gcc可用的最新版本也不会更改程序集。关于这两个例程的性能,令我感到困惑的是,对于test_1来说,只有一个内存操作( movsd ),而对于test_2来说只有三个内存操作,并且考虑到内存操作的延迟介于比浮点操作的等待时间大一个数量级和两个数量级,test_1的性能应更高。因此,在哪种情况下建议使用std :: fma?我的假设中有什么错误?