x86 - AVX2中广播高字

标签 x86 intel simd micro-optimization avx2

vpbroadcastw AVX2 中引入的指令方便 (?) 将低 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 字节随机控制。

最佳答案

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

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

  • 使用 in-lane 填充高 qword vpshufhw 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 (带有控制向量)广播高双字。但这无济于事,因为 vpblendw即使在 SKL/SKX 上也是 p5-only。

    如果 shuffle 吞吐量是瓶颈,则存储/重新加载也是一种选择,例如vextracti128的高半,然后从高字广播负载。 (但比双字更窄的广播负载仍然需要 shuffle uop)。

    关于x86 - AVX2中广播高字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57505111/

    相关文章:

    c++ - 在嵌入 C++ 的 x86 程序集中调用/返回

    linux - assembly 中的倒车阵列故障

    linux - 如何强制禁用 intel_pstate?即使在 grub 中使用 intel_pstate=disable 选项,intel_pstate 也会在重新启动时启用

    c# - 使用 .Net System.Numeric 的新矢量仅填充矢量长度的一半

    assembly - 汇编指令数据库?

    c++ - Asm CALL 指令 - 它是如何工作的?

    c++ - 英特尔 C++ 编译器是否优化了代码中从未调用过的函数?

    c++ - VS 10 中英特尔 C++ 编译器的矢量化报告目录

    c - x86_64 SSE 对齐 : differences between GCC and Clang

    C++ 错误 : ‘_mm_sin_ps’ was not declared in this scope