__m512 的压缩位测试

问题描述 投票:0回答:1

__m512 打包位测试没有内在的内容(如

_mm512_testz_si512
)。

最好的方法是什么?

x86-64 intrinsics avx512
1个回答
0
投票

_mm512_test_epi32_mask(v,v) == 0
是直接替代品。

测试掩码,然后测试掩码以获得标量

bool
您可以分支或其他。

如果您不想立即在其上分支并且不需要需要将其转换为

bool
,或者如果您想知道,您也可以将掩码用作0或非零整数其中设置的位是(位扫描或弹出计数)。或者使用它来零屏蔽或合并屏蔽其他 AVX-512 操作。

    __mmask16 mask == _mm512_test_epi32_mask(v,v);   // 0 or non-zero integer
    if (mask != 0) {  // __mmask16 is in practice an alias for uint16_t
          // You might have further use for the mask, e.g.
          int first_match_index = std::countr_zero(mask);
    }

在asm中,如果使用周围的代码进行优化,它可能看起来像这样:

  vptestmd  k0, zmm1, zmm1     ; mask of elements where zmm1&zmm1 was non-zero.

; branch on it.  Or a compiler might use cmovz or setz (create an actual bool)
  kortestw  k0, k0             ; set integer FLAGS according to k0|k0
  jz        vec_was_all_zero   ; branch if ZF==1

; or get a 0 / non-0  int  you can return, or bit-scan to find the first non-zero element
  kmovw     eax, k0

或者根据您想要对掩码执行的操作,

_mm512_testn_epi32_mask(v,v)
获得 NAND 而不是 AND。
testn(v,v) == ~test(v,v)
。但是,如果您只想测试掩码,您同样可以执行
_mm512_test_epi32_mask(v,v) == 0xFFFF
来检查所有 16 个元素是否都有非零位,而不是检查
testn
结果是否为 0。除了机器代码之外,这并不便宜尺寸,因此最重要的是避免在
countr_zero
或其他任何事情之前翻转掩模。


AVX-512 比较和测试仅适用于将掩码寄存器作为目标 (

k0-k7
),有点像将比较 +
vpmovmskb
卷入一条单微指令指令中。 (
_mm256_movemask_epi8
ps/pd
。这些的AVX-512版本提取每个元素的高位,是
vpmovd2m
_mm512_movepi32_mask
),可用于每个元素大小,包括16位,例如抓取整数或浮点数的符号位。)

获得掩码后,有两条指令用于根据

k
寄存器设置整数FLAGS条件:
kortest
(根据2个掩码或掩码与其自身的按位或来设置FLAGS)和AVX512DQ /BW
ktest
(... AND 2 个面具...)。

因此,您实际上可以一次测试两个向量是否有任何非零元素,例如

 __mmask16 mask1 = _mm512_test_epi32_mask(v1,v1);
 __mmask16 mask2 = _mm512_test_epi32_mask(v2,v2);
 // or any other condition you want to check, like _mm512_cmple_epu32(x,y)
 if (mask1 | mask2) {
    // At least one was non-zero; sort out which if it matters.
    // Or maybe concatenate them (e.g. kunpckwd) and bit-scan the 32-bit mask
    //  to find an element index, maybe into memory they were loaded from
 }

这将编译为 2x

vptestmd
和 1x
kortestw
。在这种情况下,与向量相同的微指令数 OR + 1
vptestmd
+
kortest
;能够检查两个掩码中任何一个中的任何设置位对于更复杂的比较(例如精确相等)可能很有用。


无论如何,在主流 Intel CPU 上,

SSE4 / AVX

ptest
转换为整数 FLAGS 始终为 2 uops (https://uops.info/)。像
_mm256_testz_si256
这样的内在函数公开了您可以检查的各种 FLAGS 条件,在本例中为 ZF==1,让编译器发出诸如
jz
jnz
cmovz ecx, edx
setz al
之类的指令,具体取决于您的方式使用结果
bool

传统 SSE

ptest
(不覆盖源寄存器)的好处之一在 AVX 3 操作数指令中不存在,但当输入向量不比较时,获取 AND 或 ANDN 结果偶尔仍然有用结果或其他全 0/全 1 掩码。 (比较 + ptest + jcc 比比较 / pmovmskb / 宏融合
test+jcc
更差,总共 3 个 uops)。

AVX-512 是围绕每个元素掩码进行大量设计的(例如,我们不只是将

_mm256_xor_si256
扩大到 512,而是使用
_mm512_xor_epi32
64
作为
_mm512_maskz_and_epi32
的无掩码版本。同样,AVX -512 版本的
ptest
现在是掩码寄存器中每个元素的东西。除了标量 FP 比较到像
vucomisd
这样的 EFLAGS 之外,AVX-512 正则化了东西,所以比较/测试总是进入掩码寄存器,而不是像
 那样的 EFLAGS ptest
或通用寄存器,如
pmovmskb

相关:

© www.soinside.com 2019 - 2024. All rights reserved.