【发布时间】:2018-02-02 15:47:55
【问题描述】:
是否有一种内在的或另一种有效的方法将 AVX 寄存器的 64 位组件的高/低 32 位组件重新打包到 SSE 寄存器中?使用 AVX2 的解决方案是可以的。
到目前为止,我正在使用以下代码,但分析器说它在 Ryzen 1800X 上运行缓慢:
// Global constant
const __m256i gHigh32Permute = _mm256_set_epi32(0, 0, 0, 0, 7, 5, 3, 1);
// ...
// function code
__m256i x = /* computed here */;
const __m128i high32 = _mm256_castsi256_si128(_mm256_permutevar8x32_epi32(x),
gHigh32Permute); // This seems to take 3 cycles
【问题讨论】:
-
所以你想提取奇数或偶数的 32 位元素?即像 AVX512
_mm256_cvtepi64_epi32(vpmovqd)?我认为您不会以 3 周期延迟击败 1 条 shuffle 指令,因为在 Intel CPU 上,车道交叉 shuffle 总是有 3c 延迟。您的vpermd解决方案具有单周期吞吐量。 -
如果您需要它更快,您将不得不减少周围的代码使用它,或者不需要车道交叉或其他东西!或者也许以某种方式使用
shufps将两个源打包成256b 结果(除非它不是车道交叉,所以它不能解决您的问题,并且没有vpackqd指令和打包指令也不是车道交叉。) -
@PeterCordes,是的,我想从 256 位寄存器中提取奇数或偶数 32 位元素到 128 位寄存器。感谢您对 AVX512 的参考!我在 Ryzen 1800X 上没有,但期待迁移一次……这些 32 位元素是 64 位双精度的高低部分,所以我没有看到改变周围代码的方法.
-
那么它们必须在
__m128i中,还是您可以使用通道内随机播放将低半部分和高半部分放入__m256i的每个通道的底部2 个元素中?不过,如果您正在为 Ryzen 进行调整,那么将其降低到 128b 可能确实有意义。但也许vextractf128然后使用 2-source shuffle(如shufps)在 Ryzen 上会更好,因为在 Ryzen 上,跨车道的 shuffle 非常慢。
标签: c++ vectorization x86-64 sse avx2