Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 测试xmm寄存器中的任何字节是否为0_String_Assembly_X86_Simd_Sse2 - Fatal编程技术网

String 测试xmm寄存器中的任何字节是否为0

String 测试xmm寄存器中的任何字节是否为0,string,assembly,x86,simd,sse2,String,Assembly,X86,Simd,Sse2,我目前正在自学SIMD,并正在编写一个相当简单的字符串处理子程序。然而,我被限制在SSE2上,这使得我无法使用ptest来查找空终端 我目前试图找到空终端的方式使我的SIMD循环有>16条指令,这与使用SIMD的目的背道而驰,或者至少使它不值得 //Check for null byte pxor xmm4, xmm4 pcmpeqb xmm4, [rdi] //Generate bitmask movq rax, xmm4 t

我目前正在自学SIMD,并正在编写一个相当简单的字符串处理子程序。然而,我被限制在SSE2上,这使得我无法使用ptest来查找空终端

我目前试图找到空终端的方式使我的SIMD循环有>16条指令,这与使用SIMD的目的背道而驰,或者至少使它不值得

//Check for null byte
pxor xmm4, xmm4
pcmpeqb xmm4, [rdi]                                   //Generate bitmask
movq rax, xmm4
test rax, 0xffffffffffffffff                          //Test low qword
jnz .Lepilogue
movhlps xmm4, xmm4                                    //Move high into low qword
movq rax, xmm4
test rax, 0xffffffffffffffff                          //Test high qword
jz .LsimdLoop                                         //No terminal was found, keep looping
我在想,如果没有ptest,是否有更快的方法可以做到这一点,或者这是否是最好的方法,我将不得不进一步优化循环的其余部分

注意:我确保输入使用SIMD的循环的字符串地址是16B对齐的,以允许对齐的指令。

您可以使用(
pmovskb
指令)从比较结果中获得位掩码(生成的掩码包含向量中每个字节的最高有效位)。然后,测试任何字节是否为零意味着测试掩码中的16位中是否有非零位

pxor xmm4, xmm4
pcmpeqb xmm4, [rdi]
pmovmskb eax, xmm4
test eax, eax          ; ZF=0 if there are any set bits = any matches
jnz .found_a_zero
找到具有任何匹配项的向量后,您可以使用
bsf eax,eax
找到第一个匹配位置,以获得位掩码中的位索引,这也是16字节向量中的字节索引


或者,您可以检查与
pcmpeqb
/
pmovmskb
/
cmp eax、0xffff
匹配的所有字节(例如,像在memcmp/strcmp中那样),以检查是否设置了所有位,而不是检查至少1位集。

@Liqs:
pmovmskb
在所有x86 CPU上都很便宜。只有1个uop(英特尔上的端口0)和大约3个周期的延迟。看到或看到。如果这个基准测试比您的movq/movq/or方法慢,那么您可能会遇到其他一些性能问题。也许@Liqs:它执行的指令比你的答案,甚至是你问题中的代码都多,这是不合理的。您确定每次都在测量相同的输入数据,并且只计算进程的
perf stat-e任务时钟、周期:u、指令:u
用户空间指令的事件吗?@Liqs:也相关:re:通过使用
por
,在整个向量缓存线上摊销任何零测试,然后找出零的位置。如果您想要一个精确的字节位置,您可以
bsf
注意到的
pmovmsk
结果:。也。真正的库在strleny中使用
pmovmskb
/
cmp
。您的代码会找到第一个非零字节。但是OP想找到第一个零字节(只需将
cmp
替换为
test
)@Liqs:检查对这个答案的更新:它之前正在寻找一个不全为零的向量。如果您在没有检查正确性的情况下进行了基准测试,这可以解释为什么您的基准测试结果发现执行了更多的指令,如果您的代码实际上做了更多的工作。(测试优化的正确性和速度始终是一个好主意,尤其是当您发现执行了更多指令等令人惊讶的结果时。)参见
test rax,0xffffffffffffff
相当于
test rax,rax