首页 > 解决方案 > 在 AVX2 中广播高位字

问题描述

AVX2 中引入的vpbroadcastw指令方便地 (?) 将低 16 位 WORD 广播到 32 字节ymm寄存器中的所有位置。

因为我是一个逆势者,所以我想将 AVX2 寄存器的高位字(位 255:240)广播给所有元素。

我能想到的最好的办法是交叉洗牌,然后是逐pshufb字节洗牌,如下所示:

inline __m256i bcast_mse(__m256i v) {
    __m256i temp = _mm256_permute2x128_si256(v, v, 0x11);
    __m256i ctrl = _mm256_set_epi8(  // clang-format off
        15, 14, 15, 14, 15, 14, 15, 14,
        15, 14, 15, 14, 15, 14, 15, 14,
        15, 14, 15, 14, 15, 14, 15, 14,
        15, 14, 15, 14, 15, 14, 15, 14
    );  // clang-format on
    return _mm256_shuffle_epi8(temp, ctrl);
}

有更好的吗?显然我更喜欢单指令,但假设这不会发生,可能涉及到需要这个 32 字节的随机播放控制。

标签: x86intelsimdmicro-optimizationavx2

解决方案


AVX512BWvpermw可以在 SKX 及更高版本上执行此操作。在 SKX 上为 2 uop,但在后来的 Intel 上降至 1 uop。


使用 AVX2,您可以分 2 步进行广播,并立即进行两次随机播放,无需控制 vec:

  • 使用in-lane填充高qwordvpshufhw ymm
    _mm256_shufflehi_epi16(v, _MM_SHUFFLE(3,3,3,3))
  • 立即广播vpermq
    _mm256_permute4x64_epi64或者_mm256_permutex_epi64(v2, _MM_SHUFFLE(3,3,3,3))

我认为至少需要 2 个非洗牌指令(如vpsrld/ vpblendw)来设置一个vpermd(带有控制向量)来广播高位 dword。但这无济于事,因为vpblendw即使在 SKL/SKX 上也只有 p5。


如果 shuffle 吞吐量是瓶颈,例如高一半的瓶颈,那么存储/重新加载也是一个选项vextracti128,然后从高位广播负载。(但广播负载比 dword 窄仍然需要 shuffle uop)。


推荐阅读