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

时间:2016-05-01 20:42:29

标签: c vector intel sse avx

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

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

for (i = 0; i < LENGTH; ++i) {
   foo[bar[i]] *= 2;
}

由于我想要在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);
}

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

1 个答案:

答案 0 :(得分:2)

(我正在写这个老问题的答案,因为我认为这可能会对其他人有所帮助。)

简短答案

不。 SSE和AVX指令集中没有分散/聚集指令。

更长的答案

由于分散/收集机制需要与高速缓存存储器控制器紧密地缠绕在一起,因此执行分散/收集指令的成本很高(就复杂性和芯片面积而言)。我相信这是SSE / AVX缺少此功能的原因。

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

  • 用于浮点收集(intrinsics here)的VGATHERDPD,VGATHERDPS,VGATHERQPD,VGATHERQPS
  • VPGATHERDD,VPGATHERQD,VPGATHERDQ,VPGATHERQQ 用于整数收集(intrinsics here

AVX-512中,我们得到了

  • VSCATTERDPD,VSCATTERDPS,VSCATTERQPD,VSCATTERQPS 用于浮点散布 (intrinsics here
  • VPSCATTERDD,VPSCATTERQD,VPSCATTERDQ,VPSCATTERQQ 用于整数散点(intrinsics here

但是,对于这种简单的操作使用分散/聚集是否真的会奏效还是个问题。