使用 AVX 异或两个 zmm(512 位)寄存器

Using AVX to xor two zmm (512 bit) registers

我想对 zmm0 和 zmm1 进行位运算。 我在互联网上阅读并尝试过:

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

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

但是编译器给出了"Error: number of operands mismatch for `vpxorq'".

我做错了什么?

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

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

VPXOR ymm1, ymm2, ymm3/m256

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

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

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

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

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

不安全,因为你没有 "memory" clobber 告诉编译器你 read/write 内存,而且你没有在 zmm0 上声明 clobber或 zmm1.

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


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

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