Автоматически генерировать инструкции FMA в MSVC

MSVC поддерживает инструкции AVX / AVX2 в течение многих лет и в соответствии с это сообщение в блоге msdn, он может автоматически генерировать сплавлено-умножить-добавить (FMA) инструкции.

Но ни одна из следующих функций не компилируется в инструкцию FMA:

float func1(float x, float y, float z)
{
return x * y + z;
}

float func2(float x, float y, float z)
{
return std::fma(x,y,z);
}

Хуже того, std :: fma не реализована как отдельная инструкция FMA, она работает ужасно, намного медленнее, чем обычная x * y + z (низкая производительность std :: fma ожидается, если реализация не полагается на инструкцию FMA).

Я собираю с /arch:AVX2 /O2 /Qvec флаги.
Также попробовал это с /fp:fastнет успеха.

Итак, вопрос в том, как MSVC может принудительно автоматически выдавать инструкции FMA?

ОБНОВИТЬ

Eсть #pragma fp_contract (on|off), который (похоже) ничего не делает.

7

Решение

MSVC 2015 генерирует инструкцию fma для скалярных операций, но не для векторных операций (если вы явно не используете встроенную функцию fma).

Я скомпилировал следующий код

//foo.cpp
float mul_add(float a, float b, float c) {
return a*b + c;
}

//MSVC cannot handle vectors as function parameters so use const references
__m256 mul_addv(__m256 const &a, __m256 const &b, __m256 const &c) {
return _mm256_add_ps(_mm256_mul_ps(a, b), c);
}

с

cl /c /O2 /arch:AVX2 /fp:fast /FA foo.cpp

в MSVC2015 и он произвел следующую сборку

;mul_add
vmovaps xmm3, xmm1
vfmadd213ss xmm3, xmm0, xmm2
vmovaps xmm0, xmm3

а также

;mul_addv
vmovups ymm0, YMMWORD PTR [rcx]
vmulps  ymm1, ymm0, YMMWORD PTR [rdx]
vaddps  ymm0, ymm1, YMMWORD PTR [r8]
3

Другие решения

Я решил эту давнюю проблему.

Как оказалось, флаги /fp:fast, /arch:AVX2 а также /O1 (или выше /O1) недостаточно для режима Visual Studio 2015 для выдачи инструкций FMA в 32-битном режиме. Вам также нужно «Оптимизация всей программы» включен с флагом /GL,

Затем Visual Studio 2015 сгенерирует инструкцию FMA vfmadd213ss за

float func1(float x, float y, float z)
{
return x * y + z;
}

относительно std::fmaЯ открыла ошибка в Microsoft Connect. Они подтвердили, что поведение std::fma не компилируется с инструкциями FMA, потому что компилятор не рассматривает его как встроенный. Согласно их ответу, это будет исправлено в будущем обновлении, чтобы получить наилучший возможный кодоген.

3

По вопросам рекламы [email protected]