Я пытаюсь понять, выгодно ли использовать 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? Что ошибочно в моей гипотезе?
a
,b
иc
, то сборка дляtest_2
станет просто вызовомjmp fma
, аtest_1
станет 3 инструкциями. (Пример в проводнике компилятора) - person Human-Compiler   schedule 09.06.2020-O3
ничего не знает о вашем наборе инструкций. Я только что добавил-march=native
с обоими компиляторами, и ваши две функции стали эквивалентны (и используйте инструкциюvfmadd213sd
). Между прочим, инструкцииmulsd
иaddsd
содержат операцию перемещения (т.е. извлечения данных из памяти). - person prog-fh   schedule 09.06.2020a*b + c
в инструкцию FMA с настройкой по умолчанию-ffp-contract=fast
, если она доступна. - person Peter Cordes   schedule 09.06.2020