如何在AVX或SSE指令中进行间接加载(聚集 - 分散)?

Kim*_*y W 11 c sse vector intel avx

我一直在寻找一段时间,但似乎无法在文档或SO上找到任何有用的东西.这个问题并没有真正帮助我,因为它引用了修改程序集,我用C语言写作.

我有一些代码进行间接访问,我想要进行矢量化.

for (i = 0; i < LENGTH; ++i) {
   foo[bar[i]] *= 2;
}
Run Code Online (Sandbox Code Playgroud)

由于我有索引我想要加倍内部bar,我想知道是否有办法将这些索引加载foo到矢量寄存器然后我可以应用我的数学并将其存储回相同的索引.

像下面这样的东西.该loadstore说明我只是做了,因为我找不到AVX和SSE文档中像他们一样东西.我想我读过AVX2有类似功能的地方,但我正在使用的处理器不支持AVX2.

for (i = 0; i < LENGTH; i += 8) {
   // For simplicity, I'm leaving out any pointer type casting
   __m256 ymm0 = _mm256_load_indirect(bar+i);
   __m256 ymm1 = _mm256_set1_epi32(2); // Set up vector of just 2's
   __m256 ymm2 = _mm256_mul_ps(ymm0, ymm1);
   _mm256_store_indirect(ymm2, bar+i);
}
Run Code Online (Sandbox Code Playgroud)

在AVX或SSE中是否有任何指令允许我从不同的数组加载带有索引数组的向量寄存器?如果没有明确的功能,还是围绕它的任何"hacky"方式?

Pib*_*ben 5

(我为这个老问题写了一个答案,因为我认为它可以帮助其他人。)

简答

否。 SSE 和 AVX 指令集中没有分散/收集指令。

更长的答案

分散/聚集指令的实现成本很高(就复杂性和芯片空间而言),因为分散/聚集机制需要与高速缓存控制器深度交织在一起。我相信这就是 SSE/AVX 缺少此功能的原因。

对于较新的指令集,情况有所不同。在AVX2 中你有

AVX-512 中,我们得到了

然而,对于这样一个简单的操作使用分散/聚集是否真的有回报仍然是一个问题。