gpt4 book ai didi

将 16 字节字符串与 SSE 进行比较

转载 作者:行者123 更新时间:2023-12-04 02:00:10 26 4
gpt4 key购买 nike

我有 16 字节的“字符串”(它们可能更短,但您可能会假设它们在末尾用零填充),但您可能不会假设它们是 16 字节对齐的(至少并非总是如此)。

如何编写一个例程将它们(相等)与 SSE 内在函数进行比较?我发现这个代码片段可能会有所帮助,但我不确定它是否合适?

register __m128i xmm0, xmm1; 
register unsigned int eax;

xmm0 = _mm_load_epi128((__m128i*)(a));
xmm1 = _mm_load_epi128((__m128i*)(b));

xmm0 = _mm_cmpeq_epi8(xmm0, xmm1);

eax = _mm_movemask_epi8(xmm0);

if(eax==0xffff) //equal
else //not equal

有人可以解释这个或写一个函数体吗?

它需要在 GCC/mingw(在 32 位 Windows 上)中工作。

最佳答案

vector 比较指令根据相应源元素之间的比较,将其结果作为掩码,由全 1(真)或全 0(假)的元素组成。

请参阅 https://stackoverflow.com/tags/x86/info 以获取一些链接,这些链接将告诉您这些内在函数的作用。

问题中的代码看起来应该可以工作。

如果您想找出哪些元素不相等,请使用 movemask 版本( pmovmskbmovmskps )。您可以 tzcnt/bsf 对第一次匹配进行位扫描,或 popcnt 对匹配进行计数。 All-equal 给你一个 0xffff 掩码,non-equal 给你 0

您可能想知道 SSE4.1 ptest 在这里是否有用。它可用,但实际上并没有更快,特别是如果您对结果进行分支而不是将其转换为 bool 值 0/-1。

 // slower alternative using SSE4.1 ptest
__m128i avec, bvec;
avec = _mm_loadu_si128((__m128i*)(a));
bvec = _mm_loadu_si128((__m128i*)(b));

__m128i diff = _mm_xor_si128(avec, bvec); // XOR: all zero only if *a==*b

if(_mm_test_all_zeros(diff, diff)) { //equal
} else { //not equal
}

在 asm 中, ptest 是 2 uops,并且不能与 jcc 条件分支进行宏融合。因此,前端的总 pxor + ptest + branch 是 4 uops,并且仍然会破坏其中一个输入,除非您有 AVX 将异或结果放入第三个寄存器。
pcmpeqb xmm0, xmm1/ pmovmskb eax, xmm0/ cmp/jcc 总共是 3 uop,在 Intel 和 AMD CPU 上,cmp/jcc 融合为 1 uop。

如果您有更宽的元素,您可以对 movmskps 的结果使用 movmskpdpcmpeqd/q 以获得 4 位或 2 位掩码。如果您想在不为每个元素除以 4 或 8 个字节的情况下进行位扫描或 popcnt,这将非常有用。 (或者使用 AVX2,8 位或 4 位而不是 32 位掩码。)

如果您不需要任何额外的指令来为其构建输入,那么 ptest 只是一个好主意:测试是否为全零,带或不带掩码。例如检查每个元素或某些元素中的某些位。

关于将 16 字节字符串与 SSE 进行比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31999284/

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