AVX unpackhipd / unpacklopd模拟整个256位寄存器

时间:2017-09-01 05:38:05

标签: c sse simd avx

假设我有两个256位寄存器,包含四个双值xy_mm256_unpacklo_pd(x, y)VUNPCKLPD)的输出为:[x0, y0, x2, y2](因为每个128位行都是单独处理的)。我想实现[x0, y0, x1, y1]

这有什么内在/指示吗?或者,如果没有,达到预期结果的最快方法是什么?

2 个答案:

答案 0 :(得分:2)

请注意,您想要的所有值都在输入向量的低通道中。

每个输入的128b低半部分的

_mm_unpacklo_pd / _mm_unpackhi_pd会为vinsertf128设置。 (如果调整Sandybridge / Ivybridge,你可以使用整数shuffle(vpunpcklqdq / hqdq)来获得128b操作,以获得比FP shuffle更好的吞吐量。因为我认为这对任何支持AVX1的CPU都没有影响,它和#39;这不是一个坏主意。)

如果高低通道需要相同的东西,那么使用256b的通道内解包指令并对该结果的128b通道进行随机播放。 _m256_permute2f128_pd尽可能使用gcc / clang编译为vinsertf128,但不能编译为ICC或MSVC,因此编写效率更高

// much faster on Ryzen/KNL, same on Intel mainstream
__m256d lohalves_insert(__m256d lo, __m256d hi) {
    return _mm256_insertf128_pd(lo, _mm256_castpd256_pd128(hi), 1);
}

了解各种编译器如何在the Godbolt compiler explorer上优化这些内容。

可能只有2指令方式才能完成AVX1,但可能没有。

使用AVX2,您可以vinsertf128将每个输入的低128b转换为单个向量的两个通道。然后使用AVX2 vpermpd将跨越通道的元素移动到最终位置。

Ryzen的情况比两个128b vunpckl/hpd + vinsertf128更糟糕,但英特尔的吞吐量更高。对于2-lane-crossing shuffle(3 + 3c = 6c)与1 + 1(资源冲突)+ 3c = 5c,3-shuffle方式,在Intel Haswell及更高版本,或者在Sandybridge / Ivybridge,如果你没有#39; t对128b操作使用整数随机数。 (参见Agner Fog的insn表,标签wiki中的链接。)

答案 1 :(得分:1)

在我的情况下,我实际上需要处理数据的高/低部分,因此需要两个向量的四个指令:unpackhi / unpacklo并将它们的低/高一半洗牌