gpt4 book ai didi

sse - 使用 SSE/AVX/AVX2 检查 __m128i 的所有字节是否与单个字节匹配

转载 作者:行者123 更新时间:2023-12-02 16:59:17 27 4
gpt4 key购买 nike

我正在寻找计算以下函数的有效方法:

输入:__m128i数据,uint8_t in;

输出: bool 值,指示 data 中的任何字节是否在 in 中。

我实际上是在使用它们为容量为 8 的字节实现空间/时间高效堆栈。我最有效的解决方案是首先计算一个 __m128i tmp,所有字节都作为 in。然后检查 tmp\xor data 中的任何字节是否为零字节。

最佳答案

是的,AVX2 具有高效的字节广播。带有全零掩码的 SSSE3 pshufb 同样便宜,但您必须创建洗牌控制向量。 AVX512BW/F 甚至只有单指令 vpbroadcastb/w/d/q x/y/zmm, r32 . (使用可选的掩码,因此您可以根据需要将一些向量置零或与现有向量合并,例如,使用单位掩码插入到某个位置。)

幸运的是,编译器知道如何在实现 _mm_set1_epi8 时执行此操作,因此我们可以将其留给编译器。

然后它只是归结为通常的 pcmpeqb/pmovmskb 以获得一个整数,该整数将具有用于匹配元素的 1 位,这你可以分支。

// 0 for not found, non-zero for found.  (Bit position tells you where).
unsigned contains(__m128i data, uint8_t needle) {
__m128i k = _mm_set1_epi8(needle);
__m128i cmp = _mm_cmpeq_epi8(data, k); // vector mask
return _mm_movemask_epi8(cmp); // integer bitmask
}

如您所料,所有编译器都使用此 asm ( Godbolt )

contains(long long __vector(2), unsigned char):
vmovd xmm1, edi
vpbroadcastb xmm1, xmm1
vpcmpeqb xmm0, xmm0, xmm1
vpmovmskb eax, xmm0
ret

MSVC 除外,它首先在 movsx eax, dl 上浪费了一条指令。 (Windows x64 在 RDX 中传递第二个参数,而 x86-64 System V 在 RDI 中传递第一个 integer arg。)


如果没有 AVX2,使用 SSSE3 或更高版本你会得到类似的东西

# gcc8.3 -O3 -march=nehalem
contains(long long __vector(2), unsigned char):
movd xmm1, edi

pxor xmm2, xmm2
pshufb xmm1, xmm2 # _mm_shuffle_epi8(needle, _mm_setzero_si128())

pcmpeqb xmm0, xmm1
pmovmskb eax, xmm0
ret

或者仅使用 SSE2(x86-64 的基线):

contains(long long __vector(2), unsigned char):
mov DWORD PTR [rsp-12], edi
movd xmm1, DWORD PTR [rsp-12] # gcc's tune=generic strategy is still store/reload /facepalm
punpcklbw xmm1, xmm1 # duplicate to low 2 bytes
punpcklwd xmm1, xmm1 # duplciate to low 4 bytes
pshufd xmm1, xmm1, 0 # broadcast

pcmpeqb xmm1, xmm0
pmovmskb eax, xmm1
ret

相关:

关于sse - 使用 SSE/AVX/AVX2 检查 __m128i 的所有字节是否与单个字节匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54897297/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com