【问题标题】:Broadcasting the high word in AVX2在 AVX2 中广播高位字
【发布时间】:2019-12-21 15:01:14
【问题描述】:

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

因为我是个逆势者,我想改为将 AVX2 寄存器的 high 字(位 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 字节的随机播放控制。

【问题讨论】:

    标签: x86 intel simd micro-optimization avx2


    【解决方案1】:

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


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

    • 使用in-lane vpshufhw ymm填充高qword
      _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-only。


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

    【讨论】:

    • 嗯,很好的解决方案 - clang 的 shuffle 优化器没有找到那个。太糟糕了vpermq 在 Zen 上很慢。
    • @BeeOnRope:哦,是的,如果你经常在车道上这样做vpshufb 加上vperm2i128 在Zen2 上应该会更好。但是出于某种原因,vperm2i128 在 Zen1 上甚至比 vpermq 还要糟糕。 (Agner 发现 vperm2f128 = 8 uops,未测试 vperm2i128
    • vperm2i128 的奇怪之处在于,无论控制如何,您都可以通过vextracti128vinserti128 和一些混合的某种组合构建一个严格更快的版本。 IE。所有这些的逆吞吐量之和小于单个vperm2i128,在大多数情况下,您只需要其中的 1 或 2 个。也许是 vperm2i128 的归零功能杀死了它。
    猜你喜欢
    • 2019-05-31
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多