我正在使用AVX2 / SSE指令并行化某个动态编程问题。
在我计算的主要迭代中,我计算矩阵中的列,其中每个单元格是AVX2寄存器(_m256i
)的结构。我使用前一个矩阵列中的值作为计算当前列的输入值。列可能很大,所以我做的是我有一个结构数组(在堆栈上),其中每个结构有两个_m256i
元素。
结构:
struct Cell {
_m256i first;
_m256i second;
};
然后我有这样的数组:Cell prevColumn [N]
。 N
只需几百个。
我知道_m256i
基本上代表了一个avx2寄存器,所以我想知道如何考虑这个数组,它是如何表现的,因为N远大于16(这是avx寄存器的数量)?创建这样一个数组是一个好习惯,还是有一些更好的方法,我应该在存储很多将要很快重用的_m256i
值时使用?
此外,我是否应该采用这种结构进行调整?我读了很多关于对齐的内容,但我仍然不确定如何以及何时完成这项工作。
答案 0 :(得分:1)
最好在构建代码之前使用值执行所有操作,然后再继续操作。适合L1缓存的小缓冲区对于性能来说不会太糟糕,但除非你需要,否则不要这样做。
我认为用int []
类型的缓冲区而不是__m256i
类型的缓冲区编写代码更为典型,但我不确定。无论哪种方式都有效,并且应该通过编译来生成有效的代码。但是int []
方式意味着SSE,AVX2和AVX512版本的代码必须更少。并且它可以使用调试器更容易地检查事物,将数据放在一个数组中,其类型可以很好地格式化数据。
据我了解,加载/存储内在函数部分存在于_m256i
和int []
之间,因为AVX在未对齐时没有故障,只会减慢缓存线边界的速度。分配到_m256i
数组或从数组git rebase -i HEAD~6
分配应该可以正常工作,并在需要时生成加载/存储指令,否则生成带有内存源操作数的向量指令。 (对于更紧凑的代码和更少的融合域uops。)