不幸的是,我有一个AMD堆河cpu,它似乎与AVX指令有问题:
256位AVX寄存器的内存写入速度非常慢.测量的吞吐量比以前的模型(Bulldozer)慢5-6倍,比两次128位写入慢8-9倍。
根据我自己的经验,我发现mm256本质比mm128慢得多,我认为这是因为上述原因。
我真的很想为最新的指令集AVX编写代码,同时仍然能够以合理的速度在我的机器上测试构建。是否有一种方法可以强制mm256本质上使用SSE指令?我用的是VS 2015。
如果没有容易的方法,那么困难的方法呢?将<immintrin.h>替换为一个定制的标头,其中包含我自己对本质的定义,可以对其进行编码以使用SSE?不知道这有多可信,如果可能的话,我更喜欢在我完成这份工作之前的更简单的方法。
发布于 2015-11-01 15:14:12
使用Agner的向量类库并将其添加到Visual:-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在他的回答中指出的那样,如果您的目标只是避免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
#include "vectorclass.h"
#if SIMDWIDTH == 4
typedef Vec4f Vecnf;
#else
typedef Vec8f Vecnf;
#endif 然后像这样编译
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,因为我不认为有一个很好的理由使用avx128除了在AMD。
发布于 2015-11-04 19:26:42
你不想使用SSE指令。您想要的是256 b存储作为两个单独的128 B存储,仍然使用VEX编码的128 B指令。即128 128b vmovups。
gcc有-mavx256-split-unaligned-load和...-store选项(例如,作为-march=sandybridge的一部分启用,大概也适用于Bulldozer家族(-march=bdver2是piledriver) )。但是,当编译器知道内存对齐时,这并不能解决问题。
您可以用宏来覆盖普通256 b存储
// maybe enable this for all BD family CPUs?
#if defined(__bdver2) | defined(PILEDRIVER) | defined(SPLIT_256b_STORES)
#define _mm256_storeu_ps(addr, data) do{ \
_mm_storeu_ps( ((float*)(addr)) + 0, _mm256_extractf128_ps((data),0)); \
_mm_storeu_ps( ((float*)(addr)) + 4, _mm256_extractf128_ps((data),1)); \
}while(0)
#endifgcc为Piledriver (-march=bdver2)定义了推土机版本2(-march=bdver2)。
您可以对(对齐) _mm256_store_ps进行同样的操作,也可以始终使用未对齐的内在特性。
编译器将_mm256_extractf128(data,0)优化为简单的转换。也就是说,它应该编译成
vmovups [rdi], xmm0 ; if data is in xmm0 and addr is in rdi
vextractf128 [rdi+16], xmm0, 1然而,对天栓的测试表明gcc和clang都是哑巴。,并提取到一个寄存器,然后存储。ICC正确地生成两个指令序列。
https://stackoverflow.com/questions/33460592
复制相似问题