我试图通过查看生成的汇编代码来了解使用带有双参数的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 &b, 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&, 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?我的假设有什么错误?