なぜmemcmp(a, b, size)
は以下よりもはるかに速いのですか?
for(i = 0; i < nelements; i++) {
if a[i] != b[i] return 0;
}
return 1;
MemcmpはCPU命令か何かですか?ループ全体でmemcmp
を使用して大幅なスピードアップを得たので、かなり深いはずです。
memcmp
は、Cの単純なループよりもmuch高速化できる多数のアーキテクチャ固有の機能を利用するために、アセンブリに実装されることがよくあります。
GCCはmemcmp
(および他の多数の関数)を builtins としてサポートします。 GCCの一部のバージョン/構成では、memcmp
の呼び出しは__builtin_memcmp
として認識されます。 call
をmemcmp
ライブラリ関数に発行する代わりに、GCCは関数の最適化されたインラインバージョンとして機能するためのいくつかの命令を発行します。
X86では、これはcmpsb
命令の使用を活用します。これは、あるメモリ位置のバイト文字列を別のメモリ位置と比較します。これは、repe
接頭辞と組み合わせられるため、文字列は、等しくなくなるか、カウントがなくなるまで比較されます。 (正確にmemcmp
が何をするか)。
次のコードがあるとします:
int test(const void* s1, const void* s2, int count)
{
return memcmp(s1, s2, count) == 0;
}
Cygwinのgcc version 3.4.4
は、次のアセンブリを生成します。
; (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)
参照:
memcmp
の高度に最適化されたバージョンは、多くのC標準ライブラリに存在します。これらは通常、アーキテクチャ固有の命令を利用して、大量のデータを並行して処理します。
Glibcには、以下の命令セット拡張を利用できるmemcmp
x86_64の場合 のバージョンがあります。
sysdeps/x86_64/memcmp.S
sysdeps/x86_64/multiarch/memcmp-sse4.S
sysdeps/x86_64/multiarch/memcmp-ssse3.S
素晴らしい点は、glibcが(実行時に)CPUが持つ最新の命令セットを検出し、それに最適化されたバージョンを実行することです。 sysdeps/x86_64/multiarch/memcmp.S
の次のスニペットを参照してください:
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は、x-86_64用にmemcmp
の最適化バージョンを備えていないようですが、memcpy
には Arch/x86/lib/memcpy_64.S
で含まれています。これは、実行時に使用するバージョンを決定するだけでなく、alternativesインフラストラクチャ( Arch/x86/kernel/alternative.c
)を使用することに注意してください。ただし、実際にはパッチ自体で、起動時に一度だけこの決定を行います。
MemcmpはCPU命令か何かですか?
これは、少なくとも非常に高度に最適化されたコンパイラー提供の組み込み関数です。おそらく、指定していないプラットフォームに応じて、1つまたは2つの機械命令。
これは通常、メモリのブロックを比較するための特殊な命令を使用して高速アセンブリに変換されるコンパイラ組み込み関数です。