私は関数 を書きました。Str::Compare
これは基本的にstrcmp
別の方法で書き直したものです。2つの関数を比較すると、ループが500'000'000回繰り返されると、strcmp
実行が速すぎて、約x750倍速くなります。
このコードは、パラメータがアクティブな状態で C ライブラリにコンパイルされました-Os
。
int Str::Compare(char* String_1, char* String_2)
{
char TempChar_1, TempChar_2;
do
{
TempChar_1 = *String_1++;
TempChar_2 = *String_2++;
} while(TempChar_1 && TempChar_1 == TempChar_2);
return TempChar_1 - TempChar_2;
}
その関数の実行時間は です3.058s
が、strcmp
だけです0.004s
。
なぜこんなことが起こるのでしょうか?
また、ベンチマーク ループを実装した方法は次のとおりです。
int main()
{
char Xx[] = {"huehuehuehuehuehuehuehuehuehuehuehuehuehue"},
Yy[] = {"huehuehuehuehuehuehuehuehuehuehuehuehuehue"};
for(int i = 0; i < 500000000; ++i)
Str::Compare(Xx, Yy);
}
編集: コードをテストしながら最適化を行ったところ、Str::Compare
速度が大幅に向上しました。以前strcmp
はx750倍速くなったのは今だけ250倍新しいコードは次のとおりです。
int Str::Compare(char* String_1, char* String_2)
{
char TempChar_1, TempChar_2, TempChar_3;
while(TempChar_1 && !TempChar_3)
{
TempChar_1 = *String_1++;
TempChar_2 = *String_2++;
TempChar_3 = TempChar_1 ^ TempChar_2;
}
return TempChar_1 - TempChar_2;
}
新しい実行時間は です0.994s
。
ベストアンサー1
私はそれについて興味があったので、テストプログラムを作成しました:
#include <string.h>
compare(char* String_1, char* String_2)
{
char TempChar_1,
TempChar_2;
do
{
TempChar_1 = *String_1++;
TempChar_2 = *String_2++;
} while(TempChar_1 && TempChar_1 == TempChar_2);
return TempChar_1 - TempChar_2;
}
int main(){
int i=strcmp("foo","bar");
int j=compare("foo","bar");
return i;
}
gcc 4.7.3 を使用してアセンブラにコンパイルしたところ、gcc -S -Os test.c
次のアセンブラが生成されました。
.file "test.c"
.text
.globl compare
.type compare, @function
compare:
.LFB24:
.cfi_startproc
xorl %edx, %edx
.L2:
movsbl (%rdi,%rdx), %eax
movsbl (%rsi,%rdx), %ecx
incq %rdx
cmpb %cl, %al
jne .L4
testb %al, %al
jne .L2
.L4:
subl %ecx, %eax
ret
.cfi_endproc
.LFE24:
.size compare, .-compare
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "bar"
.LC1:
.string "foo"
.section .text.startup,"ax",@progbits
.globl main
.type main, @function
main:
.LFB25:
.cfi_startproc
movl $.LC0, %esi
movl $.LC1, %edi
call compare
movl $1, %eax
ret
.cfi_endproc
.LFE25:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3"
.section .note.GNU-stack,"",@progbits
私は x86 アセンブラにそれほど詳しくありませんが、私が見る限り、strcmp への呼び出しは削除され、単に定数式 ( movl $1, %eax
) に置き換えられます。したがって、テストに定数式を使用する場合、gcc はおそらく strcmp を定数に最適化します。