请使用 Agner Fog 的
向量类库,并将以下内容添加到 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
如果您使用
/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]);
然后使用/arch:AVX -D__XOP__
编译。
另一个选择是使用Vecnf
的一个源文件,然后执行
//foo.cpp
typedef Vec4f Vecnf;
typedef Vec8f Vecnf;
并像这样编译
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
这将使用一个源文件创建三个可执行文件。您可以使用
/c
编译它们,而不是链接它们,然后制作一个CPU分发器。我使用了
XOP
和avx128,因为我认为除了在AMD上使用之外,没有什么好的理由使用avx128。
Vec8f
并使用-D__SSE4_2__ -D__XOP__
进行编译。 - Z boson