首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >强制AVX本质部分使用SSE指令

强制AVX本质部分使用SSE指令
EN

Stack Overflow用户
提问于 2015-11-01 08:57:21
回答 2查看 1.5K关注 0票数 6

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

256位AVX寄存器的内存写入速度非常慢.测量的吞吐量比以前的模型(Bulldozer)慢5-6倍,比两次128位写入慢8-9倍。

根据我自己的经验,我发现mm256本质比mm128慢得多,我认为这是因为上述原因。

我真的很想为最新的指令集AVX编写代码,同时仍然能够以合理的速度在我的机器上测试构建。是否有一种方法可以强制mm256本质上使用SSE指令?我用的是VS 2015。

如果没有容易的方法,那么困难的方法呢?将<immintrin.h>替换为一个定制的标头,其中包含我自己对本质的定义,可以对其进行编码以使用SSE?不知道这有多可信,如果可能的话,我更喜欢在我完成这份工作之前的更简单的方法。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-01 15:14:12

使用Agner的向量类库并将其添加到Visual:-D__SSE4_2__ -D__XOP__中的命令行。

然后使用AVX大小的矢量,如Vec8f,用于八个浮标。当您在不使用AVX的情况下编译时,它将使用vectorf256e.h文件,该文件使用两个SSE寄存器来模拟AVX。例如,Vec8f继承自Vec256fe,其开头如下:

代码语言:javascript
复制
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编码的指令(虽然不清楚这将产生不同的效果,除非在一些特殊情况下)。您可以使用这样的向量类来完成这个任务。

代码语言:javascript
复制
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然后执行以下操作的源文件

代码语言:javascript
复制
//foo.cpp
#include "vectorclass.h"
#if SIMDWIDTH == 4
typedef Vec4f Vecnf;
#else
typedef Vec8f Vecnf;
#endif  

然后像这样编译

代码语言:javascript
复制
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。

票数 6
EN

Stack Overflow用户

发布于 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存储

代码语言:javascript
复制
// 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)
#endif

gcc为Piledriver (-march=bdver2)定义了推土机版本2(-march=bdver2)。

您可以对(对齐) _mm256_store_ps进行同样的操作,也可以始终使用未对齐的内在特性。

编译器将_mm256_extractf128(data,0)优化为简单的转换。也就是说,它应该编译成

代码语言:javascript
复制
vmovups       [rdi], xmm0         ; if data is in xmm0 and addr is in rdi
vextractf128  [rdi+16], xmm0, 1

然而,对天栓的测试表明gcc和clang都是哑巴。,并提取到一个寄存器,然后存储。ICC正确地生成两个指令序列。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33460592

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档