c++ - episodes - fullmetal alchemist brotherhood wikipedia
Generar automáticamente instrucciones de FMA en MSVC (2)
MSVC 2015 genera una instrucción fma para operaciones escalares pero no para operaciones vectoriales (a menos que uses explícitamente un fma intrínseco).
Recopilé el siguiente código
//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);
}
con
cl /c /O2 /arch:AVX2 /fp:fast /FA foo.cpp
en MSVC2015 y produjo el siguiente ensamblaje
;mul_add
vmovaps xmm3, xmm1
vfmadd213ss xmm3, xmm0, xmm2
vmovaps xmm0, xmm3
y
;mul_addv
vmovups ymm0, YMMWORD PTR [rcx]
vmulps ymm1, ymm0, YMMWORD PTR [rdx]
vaddps ymm0, ymm1, YMMWORD PTR [r8]
MSVC admite las instrucciones AVX / AVX2 desde hace años y de acuerdo con esta publicación de blog msdn , puede generar automáticamente instrucciones fusionadas-multiplicar-añadir (FMA) .
Sin embargo, ninguna de las siguientes funciones compila a la instrucción 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);
}
Peor aún, std :: fma no se implementa como una única instrucción FMA, funciona terriblemente, mucho más lento que un simple x * y + z
(se espera un rendimiento deficiente de std :: fma si la implementación no se basa en FMA instrucción).
/arch:AVX2 /O2 /Qvec
banderas /arch:AVX2 /O2 /Qvec
. También lo intenté con /fp:fast
, sin éxito.
Entonces, la pregunta es ¿cómo puede MSVC obligarse a emitir instrucciones de FMA automáticamente?
ACTUALIZAR
Hay un #pragma fp_contract (on|off)
, que (parece) no hace nada.
Resolví este problema de larga data.
Como resultado, flags /fp:fast
, /arch:AVX2
y /O1
(o superior /O1
) no son suficientes para que el modo Visual Studio 2015 emita instrucciones FMA en modo de 32 bits. También necesita activar la "optimización de todo el programa" con flag /GL
.
Entonces Visual Studio 2015 generará una instrucción FMA vfmadd213ss
para
float func1(float x, float y, float z)
{
return x * y + z;
}
En cuanto a std::fma
, abrí un error en Microsoft Connect . Confirmaron el comportamiento que std::fma
no compila en las instrucciones de FMA, porque el compilador no lo trata como un elemento intrínseco. De acuerdo con su respuesta, se solucionará en una actualización futura para obtener el mejor codegen posible.