どんな最適化やねん(3)
- VC++の最適化ってどないやねん
単純なコード
main() { int i,j; for(i=0;i<10000;++i) { for(j=0;j<100000;++j) { // 何もしない } } }
.globl _main .def _main; .scl 2; .type 32; .endef _main: pushl %ebp movl $16, %eax movl %esp, %ebp subl $8, %esp andl $-16, %esp call __alloca call ___main xorl %edx, %edx L9: movl $99999, %eax .p2align 4,,15 L8: decl %eax jns L8 incl %edx cmpl $9999, %edx jle L9 leave ret
てな感じのコードになります.同じコードをVC++2005 Expressで/O2オプションをつけてコンパイルすると.
INCLUDELIB OLDNAMES EXTRN @__security_check_cookie@4:PROC PUBLIC _main _TEXT SEGMENT _main PROC ; COMDAT 00000 33 c0 xor eax, eax 00002 c3 ret 0 _main ENDP _TEXT ENDS END
なんという最適化^^;
…かと思えば,次のようなコード
main() { int i,j; for(i=0;i<10000;++i) { for(j=0;j<100000.0;++j) { // 何もしない } } }
先程と違うのは,内側のループを100000から100000.0に変えただけですが,この場合はGCCが
LC0: .long 1203982336 .text .p2align 4,,15 .globl _main .def _main; .scl 2; .type 32; .endef _main: pushl %ebp movl $16, %eax movl %esp, %ebp subl $8, %esp andl $-16, %esp call __alloca call ___main flds LC0 xorl %edx, %edx .p2align 4,,15 L10: xorl %ecx, %ecx .p2align 4,,15 L9: incl %ecx pushl %ecx fildl (%esp) fxch %st(1) addl $4, %esp fucom %st(1) fnstsw %ax fstp %st(1) sahf ja L9 incl %edx cmpl $9999, %edx jle L10 fstp %st(0) leave ret
で,VC++だと
INCLUDELIB OLDNAMES EXTRN @__security_check_cookie@4:PROC PUBLIC __real@40f86a0000000000 PUBLIC _main EXTRN __fltused:DWORD CONST SEGMENT __real@40f86a0000000000 DQ 040f86a0000000000r ; 100000 CONST ENDS _TEXT SEGMENT _j$ = -4 ; size = 4 _main PROC ; COMDAT 00000 51 push ecx 00001 dd 05 00 00 00 00 fld QWORD PTR __real@40f86a0000000000 00007 ba 10 27 00 00 mov edx, 10000 ; 00002710H $LN6@main: 0000c 33 c9 xor ecx, ecx $LN3@main: 0000e 83 c1 01 add ecx, 1 00011 89 0c 24 mov DWORD PTR _j$[esp+4], ecx 00014 db 04 24 fild DWORD PTR _j$[esp+4] 00017 d8 d9 fcomp ST(1) 00019 df e0 fnstsw ax 0001b f6 c4 05 test ah, 5 0001e 7b ee jnp SHORT $LN3@main 00020 83 ea 01 sub edx, 1 00023 75 e7 jne SHORT $LN6@main 00025 dd d8 fstp ST(0) 00027 33 c0 xor eax, eax 00029 59 pop ecx 0002a c3 ret 0 _main ENDP _TEXT ENDS END
ちょっと変えただけなのに,VC++の最適化がエライ違います.これら4種類のコードを実行すると,後者のVC++バージョンだけやたらと遅いのです.私はGCCが吐いたアセンブリしか見てなかったので,こんなことになっているとは全く考えていませんでした.
どうしてこんなことに悩まされたかと申しますと,ゴルフ脳とも言うべきか10000とか100000という値を1e4とか1e5と,浮動小数で書いてしまう癖が付いてしまっているわけです.Cの場合はあまり型にうるさくありませんし,普段このように書いていてもほとんど問題になりません.しかしVC++だとものすごく差が出てしまうとなると,VC++はつくづくゴルフ向けではないなーと感じます.
…っちゅうか,これだけのことで実行速度が桁違いに変わってしまう最適化って,どないやねん(;´д`)