提问人:user2052436 提问时间:11/3/2023 最后编辑:Peter Cordesuser2052436 更新时间:11/3/2023 访问量:47
__m512的包装位测试
Packed bit test for __m512
答:
_mm512_test_epi32_mask(v,v) == 0
是直接替换。
测试到掩码中,然后测试掩码以获得可以分支的标量或其他任何东西。如果您只关心整个向量是否在任何地方都有非零位,则测试的元素大小无关紧要,但可以使用 8/16/32/64 的元素大小(asm 手册/内部指南)。bool
如果您不想立即对掩码进行分支并且不需要将其转换为 ,或者如果您想知道设置位的位置(位扫描或 popcount),您也可以将掩码用作 0 或非零整数。或者使用它对其他 AVX-512 操作进行零屏蔽或合并屏蔽。bool
__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中,测试/分支或获取GPR整数可能如下所示:
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
或者根据你想用掩码做什么,得到NAND而不是AND。但是,如果您只想测试掩码,则同样可以检查所有 16 个元素是否具有非零位,而不是检查结果是否为 0。除了机器代码大小之外,这并不便宜,因此最重要的是避免在之前反转掩模或其他任何事情。_mm512_testn_epi32_mask(v,v)
testn(v,v) == ~test(v,v)
_mm512_test_epi32_mask(v,v) == 0xFFFF
testn
countr_zero
AVX-512 比较和测试仅适用于将掩码寄存器作为目标 (k0-k7
),有点像将比较 + 整合到一个单一 uop 指令中。( 或 .这些元素的 AVX-512 版本提取每个元素的高位,是 vpmovd2m
(),可用于包括 16 位在内的所有元素大小,例如抓取 int 或 floats 的符号位。vpmovmskb
_mm256_movemask_epi8
ps/pd
_mm512_movepi32_mask
获得掩码后,有两个指令用于基于寄存器设置整数 FLAGS 条件:kortest
(根据 2 个掩码的按位 OR 或带有自身的掩码设置 FLAGS)和 AVX512DQ/BW ktest
(...和 2 个面具......k
因此,您实际上可以一次测试两个向量是否具有任何非零元素,例如
__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 和 1x 。在这种情况下,与向量 OR + 1 + 相同的 uops 数量;能够检查两个掩码中的任何一个中的任何设置位对于更复杂的比较(例如精确相等)可能很有用。vptestmd
kortestw
vptestmd
kortest
无论如何,SSE4 / AVX 转换为整数 FLAGS 在主流 Intel CPU 上始终是 2 uops(https://uops.info/)。内部函数 like 公开了您可以检查的各种 FLAGS 条件,在本例中为 ZF==1,让编译器发出类似 、 、 或 的指令,具体取决于您如何使用生成的 .ptest
_mm256_testz_si256
jz
jnz
cmovz ecx, edx
setz al
bool
AVX 3 操作数指令不存在 legacy-SSE(不覆盖源寄存器)的好处之一,但是当输入向量不是比较结果或其他 all-0 / all-1 掩码时,偶尔获得 AND 或 ANDN 结果仍然很有用。(比较 + ptest + jcc 比 compare / pmovmskb / macro-fused 差,后者总共有 3 个 uops)。ptest
test+jcc
AVX-512 是围绕每个元素的遮罩而设计的(例如,我们不是简单地扩展到 512,而是作为 .同样,AVX-512 版本现在是将每个元素的东西放入掩码寄存器中。除了标量 FP 与 EFLAGS 进行比较之外,AVX-512 正则化的东西,因此比较/测试始终进入掩码寄存器,而不是像 EFLAGS 这样的 EFLAGS 或像 这样的通用寄存器。_mm256_xor_si256
_mm512_xor_epi32
64
_mm512_maskz_and_epi32
ptest
vucomisd
ptest
pmovmskb
相关:
如何仅在元素不为零时进行 AVX-512 整数增量显示了 () 的示例,以获取 where 元素的掩码
vptestmw
_mm512_test_epi16_mask(v,v)
缺少用于掩模的 AVX-512 内在功能?- 因为我提到了像 .通常,由编译器决定是否将掩码转换为整数注册表(如果您再次将它们用作 AVX-512 掩码,则返回)。
kunpckwd
kmov
下一个:YMM寄存器之间的逻辑转换
评论