在MSVC中自动生成FMA指令
Automatically generate FMA instructions in 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
慢得多(如果实现不依赖于fma指令,那么std::fma的性能会很差)。
我使用/arch:AVX2 /O2 /Qvec
标志进行编译。用/fp:fast
也试过,没有成功。
那么问题是MSVC如何被迫自动发出FMA指令呢?
更新
有一个#pragma fp_contract (on|off)
,它(看起来)什么都不做。
我解决了这个长期存在的问题。
事实证明,标志/fp:fast
、/arch:AVX2
和/O1
(或高于/O1
)不足以使Visual Studio 2015模式在32位模式下发出FMA指令。您还需要使用标志/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指令的行为,因为编译器不将其视为内在指令。根据他们的回应,它将在未来的更新中得到修复,以获得尽可能好的编解码器。
MSVC 2015确实为标量运算生成了fma指令,但不为向量运算生成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]
相关文章:
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- C++:对不存在的命名空间使用命名空间指令
- 函数名是c中该函数的第一条指令的地址吗
- 错误:无效的预处理指令 #i 的意思是 #if?
- 组装指令中乘法的下部和上部是什么
- OpenMP 与有序和关键指令并行
- C++中的移动分配出现问题.非法指令: 4.
- 嵌套命名空间的"using"指令,但需要命名内部命名空间
- C++CMake编译指令与
- 使用宏扩展的泛型:为什么指令缓存使用不当?
- 如何在 c++ 中确定一条指令(以字节为单位)在哪里结束,另一条指令从哪里开始?
- AVX 指令中寄存器和指针之间的客观差异
- while 循环 c++ 中的非法指令
- 如何在编译时定义C++预处理器指令的值?
- 存储指令是否会阻止缓存未命中的后续指令?
- 保证编译器指令在C++中重新排序
- VS2008中的AVX-512指令库
- 使用FMA(融合乘数)指令进行复杂的乘法
- 在MSVC中自动生成FMA指令