强制AVX内在函数使用SSE指令

Tho*_*mas 6 c++ sse avx visual-studio visual-c++

不幸的是我有一个AMD打桩机cpu,它似乎与AVX指令有问题:

使用256位AVX寄存器进行的内存写入非常慢.测量的吞吐量比之前的型号(Bulldozer)慢5到6倍,比两个128位写入慢8到9倍.

根据我自己的经验,我发现mm256内在函数比mm128要慢得多,而且我假设它是因为上述原因.

我真的想编写最新的指令集AVX,同时仍然能够以合理的速度在我的机器上测试构建.有没有办法迫使mm256内在函数使用SSE指令?我正在使用VS 2015.

如果没有简单的方法,那么艰难的方式呢.替换<immintrin.h>为包含我自己的内在函数定义的自定义标题,可以编码为使用SSE?不确定这是多么合理,在我完成这项工作之前,如果可能的话,更喜欢更简单的方法.

Z b*_*son 6

使用Agner Fog的Vector类库并将其添加到Visual Studio中的命令行:-D__SSE4_2__ -D__XOP__.

然后使用AVX大小的矢量,例如Vec8f八个浮点数.在没有AVX启用的情况下编译时,它将使用vectorf256e.h模拟具有两个SSE寄存器的AVX 的文件.例如,Vec8f继承从Vec256fe这样开始:

class Vec256fe {
protected:
    __m128 y0;                         // low half
    __m128 y1;                         // high half
Run Code Online (Sandbox Code Playgroud)

如果使用/arch:AVX -D__XOP__VCL进行编译,则将使用该文件vectorf256.h和一个AVX寄存器.然后您的代码适用于AVX和SSE,只需更改编译器开关.

如果你不想使用XOP不要使用-D__XOP__.


正如Peter Cordes在他的回答中指出的那样,如果你的目标只是为了避免256位加载/存储,那么你可能仍然需要VEX编码指令(虽然不清楚这会产生差异,除非在某些特殊情况下).你可以使用这样的矢量类来做到这一点

Vec8f a;
Vec4f lo = a.get_low();  // a is a Vec8f type
Vec4f hi = a.get_high();
lo.store(&b[0]);         // b is a float array
hi.store(&b[4]);
Run Code Online (Sandbox Code Playgroud)

然后编译/arch:AVX -D__XOP__.

另一种选择是使用Vecnf然后执行的一个源文件

//foo.cpp
#include "vectorclass.h"
#if SIMDWIDTH == 4
typedef Vec4f Vecnf;
#else
typedef Vec8f Vecnf;
#endif  
Run Code Online (Sandbox Code Playgroud)

并像这样编译

cl /O2 /DSIMDWIDTH=4                     foo.cpp /Fofoo_sse
cl /O2 /DSIMDWIDTH=4 /arch:AVX /D__XOP__ foo.cpp /Fofoo_avx128
cl /O2 /DSIMDWIDTH=8 /arch:AVX           foo.cpp /Fofoo_avx256
Run Code Online (Sandbox Code Playgroud)

这将创建三个带有一个源文件的可执行文件.您可以只使用/c它们编译它们而不是链接它们,而是创建一个CPU调度程序.我使用XOPavx128是因为我认为除了AMD之外没有充分的理由使用avx128.