【问题标题】:Using AVX to xor two zmm (512 bit) registers使用 AVX 对两个 zmm(512 位)寄存器进行异或运算
【发布时间】:2019-07-29 13:34:55
【问题描述】:

我想用 zmm1 对 zmm0 进行 bit-wisr xor。 我在互联网上阅读并尝试过:

asm volatile(
            "vmovdqa64 (%0),%%zmm0;\n"
            "vmovdqa64 (%1),%%zmm1;\n"
            "vpxorq %%zmm1, %%zmm0;\n"
            "vmovdqa64 %%zmm0,(%0);\n"

            :: "r"(p_dst), "r" (p_src)
             : );

但是编译器给出“错误:‘vpxorq’的操作数数量不匹配”。

我做错了什么?

【问题讨论】:

  • 内联 asm 毫无意义 (gcc.gnu.org/wiki/DontUseInlineAsm),即使您通过添加第三个操作数修复了语法错误,您的代码也不安全且效率低下。使用内部_mm512_xor_epi64( __m512i a, __m512i b);,如intel 的asm 手册中pxor 中所述:felixcloutier.com/x86/pxor。如果您想了解它是如何完成的,请查看编译器生成的 asm。
  • 不安全,因为你没有"memory" clobber 告诉编译器你读/写内存,并且你没有在 zmm0 或 zmm1 上声明 clobber。由于许多原因效率低下,包括强制寻址模式和不使用内存源操作数。并且不让编译器选择要使用的寄存器。

标签: c++ gcc inline-assembly avx512


【解决方案1】:

为此,内联 asm 毫无意义 (https://gcc.gnu.org/wiki/DontUseInlineAsm),即使您通过添加第三个操作数修复了语法错误,您的代码也不安全且效率低下。

使用 Intel's asm manual entry for pxor 中记录的内在 _mm512_xor_epi64( __m512i a, __m512i b);。如果您想了解它是如何完成的,请查看编译器生成的 asm。

不安全,因为您没有 "memory" clobber 来告诉编译器您读/写内存,并且您没有在 zmm0zmm1 上声明 clobber。

而且效率低下有很多原因,包括强制寻址模式和不使用内存源操作数。并且不让编译器选择要使用的寄存器。


只要修复 asm 语法以便编译,就会从一个明显的编译时错误转变为一个微妙而危险的运行时错误,这种错误可能只有在启用优化的情况下才可见。

有关内联汇编的更多信息,请参阅https://stackoverflow.com/tags/inline-assembly/info。但同样,对于大多数 SIMD 使用它基本上是零理由,因为您可以让编译器生成与您可以手动执行的操作一样高效的 asm,并且比这更高效。 p>

【讨论】:

    【解决方案2】:

    大多数 AVX512 指令使用 3+ 个操作数,即您需要添加额外的操作数 - dst 寄存器(它可以与其他操作数之一相同)。

    AVX2 版本也是如此,见https://www.felixcloutier.com/x86/pxor

    VPXOR ymm1, ymm2, ymm3/m256

    VPXORD zmm1 {k1}{z}, zmm2, zmm3/m512/m32bcst

    请注意,以上是 intel 语法,大致翻译为 *mm1 = *mm2 ^ **mm3,在您的情况下,我猜您想使用 "vpxorq %%zmm1, %%zmm0, %%zmm0;\n"

    请注意,使用内联汇编通常是一种不好的做法,仅用于非常特殊的场合。通过使用所有主要编译器支持的内在函数,SIMD 编程会更好(更快、更容易)。你可以在这里浏览它们:https://software.intel.com/sites/landingpage/IntrinsicsGuide/

    【讨论】:

    • OP 使用 AT&T 语法,其中目标是最后一个操作数,而不是第一个。所以仅仅引用英特尔手册的那一部分并不是最有帮助的。
    • @PeterCordes 我不同意,因为我没有在答案中的任何地方提及或说明操作数顺序。只需要那个额外的操作数。我希望尝试在汇编中编程的人能够自己弄清楚它需要成为第一个还是最后一个。不过我会澄清的。
    • 它仍然很有帮助,但我的意思是它没有它本来应该的那么有用。您确实引用了 Intel 语法 VPXORD zmm1 {k1}{z}, zmm2, zmm3/m512/m32bcst,它显然首先具有目标,最后是源。
    • 你也没有指出内联汇编仍然被破坏,只是现在这个错误不是语法错误,它是安全的:像我在这个问题上评论的那样缺少clobbers。我想我应该将其发布为答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-29
    • 2017-01-21
    • 2013-01-11
    相关资源
    最近更新 更多