【问题标题】:Is it ok to create big array of AVX/SSE values可以创建大量 AVX/SSE 值吗
【发布时间】:2015-07-21 01:21:29
【问题描述】:

我正在使用 AVX2/SSE 指令并行化某个动态编程问题。

在计算的主要迭代中,我计算矩阵中的列,其中每个单元格都是 AVX2 寄存器的结构 (_m256i)。我使用前一个矩阵列中的值作为计算当前列的输入值。列可能很大,所以我要做的是我有一个结构数组(在堆栈上),其中每个结构都有两个 _m256i 元素。

结构:

struct Cell {
  _m256i first;
  _m256i second;
};

然后我有这样的数组:Cell prevColumn [N]N 通常会有几百个。

我知道_m256i 基本上代表一个 avx2 寄存器,所以我想知道我应该如何看待这个数组,它的行为如何,因为 N 远大于 16(这是 avx 寄存器的数量)?创建这样一个数组是一种好习惯,还是在存储大量即将真正重用的_m256i 值时应该使用一些更好的方法?

另外,我应该对这些结构进行调整吗?我读了很多关于对齐的文章,但我仍然不确定如何以及何时准确地做到这一点。

【问题讨论】:

  • 简短回答:是的,您可以创建数组,但编译器可能不会将数组优化到寄存器中。
  • 好的 - 相当小 - 这在桌面或服务器操作系统上应该不是问题。
  • 不用担心加载/存储 - 反正你只有 16 个寄存器 - 现在让编译器和 L1 缓存处理所有事情。
  • 与其考虑拥有一组 AVX/SSE 值,不如将其视为拥有一个对 SIMD 友好的 SoA or AosOA
  • @Martinsos,Cell 在您存储或阅读时是一个SoA(例如typedef union __m256i { int8_t m256_i8[32]; int16_t m256_i16[16]; int32_t m256_i32[8]; } __256i;)。然后在Cell prevColumn [N] 中,数组prevColumn 是一个AoSoA。

标签: intel sse simd avx avx2


【解决方案1】:

在继续之前,最好对代码进行结构化,以尽其所能使用值。适合 L1 缓存的小缓冲区不会对性能造成太大影响,但除非需要,否则不要这样做。

我认为使用int [] 类型的缓冲区而不是__m256i 类型的缓冲区编写代码更为典型,但我不确定。无论哪种方式都有效,并且应该得到编译以生成有效的代码。但int [] 方式意味着 SSE、AVX2 和 AVX512 版本的不同代码必须更少。并且它可能更容易使用调试器检查事物,将您的数据放在一个数组中,该数组的类型可以很好地格式化数据。

据我了解,加载/存储内在函数部分存在于_m256iint [] 之间,因为 AVX 在未对齐时不会出错,只是在缓存线边界上减慢了速度。从_m256i 的数组中分配/分配应该可以正常工作,并在需要时生成加载/存储指令,否则生成带有内存源操作数的向量指令。 (以获得更紧凑的代码和更少的融合域微指令。)

【讨论】:

  • Peter,当您说“AVX 在未对齐时不会出错”时,您的意思是对齐加载指令 (vmovdqa) 也可以处理未对齐地址吗?英特尔软件开发人员手册说:“当源或目标操作数是内存操作数时,操作数必须在 32 字节边界上对齐,否则将生成通用保护异常 (#GP)。要将整数数据移动到和从未对齐的内存位置,使用 VMOVDQU 指令。”然而,我在我的代码中观察到了这种效果(对齐的加载指令处理未对齐的地址很好),但不敢利用它。有参考吗?
  • 我在一篇关于汇编语言的英特尔文档中找到了关于我的问题的参考资料(Kreitzer 和 Domeika 撰写):“最后,对于大多数指令,英特尔® AVX 解除了向量加载和存储对齐的限制。显式诸如 VMOVDQA 之类的“移动对齐”指令仍然要求地址在向量大小边界上对齐。但其他向量加载和存储可以不对齐。”
  • ... 这会导致以下问题:当 C 编译器从内在函数生成 AVX 指令时,它可能会采用显式对齐的加载内在函数,如 _mm256_load_si256() 并将其转换为机器指令(如加法)直接使用地址。这将带来令人惊讶的行为,即突然可以从未对齐的地址加载数据。有什么方法可以控制这种行为(影响编译器何时生成 vmovdqa 以及何时在后续指令中生成地址参数)?
  • @Ralf: 是的,将mm_load 内在函数折叠到其他insn 的内存操作数中会导致意外,正如您猜对的那样。例如stackoverflow.com/questions/30329235/…。解决方案是始终使用loadu 内在函数,因此如果编译器想要使用独立加载,它将使用movdqu / movups。 (当地址对齐时,它与movdqa 具有相同的性能,在足以支持 AVX 的新 CPU 上。)
猜你喜欢
  • 2015-03-11
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 2017-07-25
  • 1970-01-01
  • 1970-01-01
  • 2021-03-25
  • 2011-12-12
相关资源
最近更新 更多