为什么memcmp比for循环检查快得多?

为什么memcmp比for循环检查快得多?

memcmp通常是在程序集中实现的,以利用许多特定于体系结构的特性,这使得它比C中的简单循环要快得多。

作为“内建物”

GCC支持memcmp (以及大量其他功能)作为http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html。在GCC的某些版本/配置中,对memcmp的调用将被识别为__builtin_memcmp。GCC将发出一些指令,作为函数的优化内联版本,而不是向call库函数发出一个memcmp。

在x86上,这利用了cmpsb指令的使用,该指令将一个内存位置的字节字符串与另一个字节进行比较。这与repe前缀耦合在一起,因此对字符串进行比较,直到它们不再相等,或者耗尽计数。(这正是memcmp所做的)。

考虑到以下代码:

代码语言:javascript运行复制int test(const void* s1, const void* s2, int count)

{

return memcmp(s1, s2, count) == 0;

}Cygwin上的gcc version 3.4.4生成以下程序集:

代码语言:javascript运行复制; (prologue)

mov esi, [ebp+arg_0] ; Move first pointer to esi

mov edi, [ebp+arg_4] ; Move second pointer to edi

mov ecx, [ebp+arg_8] ; Move length to ecx

cld ; Clear DF, the direction flag, so comparisons happen

; at increasing addresses

cmp ecx, ecx ; Special case: If length parameter to memcmp is

; zero, don't compare any bytes.

repe cmpsb ; Compare bytes at DS:ESI and ES:EDI, setting flags

; Repeat this while equal ZF is set

setz al ; Set al (return value) to 1 if ZF is still set

; (all bytes were equal).

; (epilogue) 参考资料:

说明作为图书馆的功能

许多C标准库中都存在高度优化的memcmp版本。它们通常会利用特定于体系结构的指令来并行处理大量数据。

在Glibc中,有一些版本的memcmp 64可以利用以下指令集扩展:

SSE2 - sysdeps/x86_64/memcmp.SSSE4 - sysdeps/x86_64/multiarch/memcmp-sse4.SSSSE3 - sysdeps/x86_64/multiarch/memcmp-ssse3.S最酷的部分是glibc将检测(在运行时)您的CPU拥有的最新指令集,并执行为其优化的版本。从sysdeps/x86_64/multiarch/memcmp.S看到这个片段

代码语言:javascript运行复制ENTRY(memcmp)

.type memcmp, @gnu_indirect_function

LOAD_RTLD_GLOBAL_RO_RDX

HAS_CPU_FEATURE (SSSE3)

jnz 2f

leaq __memcmp_sse2(%rip), %rax

ret

2: HAS_CPU_FEATURE (SSE4_1)

jz 3f

leaq __memcmp_sse4_1(%rip), %rax

ret

3: leaq __memcmp_ssse3(%rip), %rax

ret

END(memcmp)在Linux内核中

Linux似乎没有优化版本的memcmp for x86_64,但在arch/x86/lib/memcpy_64.S中为memcpy提供了优化版本。注意,它使用替代基础设施(arch/x86/kernel/alternative.c)不仅在运行时决定要使用哪个版本,而且实际上是修补自己,使其在启动时只做出一次决定。

相关推荐

365bet投注网站 索尼VAIO PCG系列

索尼VAIO PCG系列

📅 07-04 👁️ 6344
365bet体育在线平台 nexus mod manager下载

nexus mod manager下载

📅 07-28 👁️ 8574