satosystemsさんによる、こんなブログエントリ「フィボナッチで各種言語をベンチマーク」をみつけました。ほんとに沢山の言語で同じアルゴリズムのプログラムを記述して実行に必要な時間を計測してます。で、結果は記事を見ていただくとして、
Python(CPython) | 53.651 |
Lisp (GNU CLisp) | 211.802 |
とか書いてあるわけです。んー、よりによってCLispですか。この処理系はちょっと遅いしなぁ。他の言語はNative Code Compilerとか使ってるし、ワシが日頃使っているCommon Lisp処理系であるところのSBCLで計測してみました。コードは全く同じで以下の通り。
(defun fib (n) (if (< n 2) n (+ (fib (- n 2)) (fib (- n 1)))))SBCL 1.0.55のコンパイラによるNative Codeの出力は以下のとおり。
; disassembly for FIB ; 0784808D: 488B55F0 MOV RDX, [RBP-16] ; 091: BF04000000 MOV EDI, 4 ; 096: 488D0C2530040020 LEA RCX, [#x20000430] ; GENERIC-< ; 09E: FFD1 CALL RCX ; 0A0: 0F8C94000000 JL L1 ; 0A6: 488B55F0 MOV RDX, [RBP-16] ; 0AA: BF04000000 MOV EDI, 4 ; 0AF: 4C8D1C255B020020 LEA R11, [#x2000025B] ; GENERIC-- ; 0B7: 41FFD3 CALL R11 ; 0BA: 480F42E3 CMOVB RSP, RBX ; 0BE: 488D5C24F0 LEA RBX, [RSP-16] ; 0C3: 4883EC18 SUB RSP, 24 ; 0C7: 488B0562FFFFFF MOV RAX, [RIP-158] ; 0CE: B902000000 MOV ECX, 2 ; 0D3: 48892B MOV [RBX], RBP ; 0D6: 488BEB MOV RBP, RBX ; 0D9: FF5009 CALL QWORD PTR [RAX+9] ; 0DC: 480F42E3 CMOVB RSP, RBX ; 0E0: 488955F8 MOV [RBP-8], RDX ; 0E4: 488B55F0 MOV RDX, [RBP-16] ; 0E8: BF02000000 MOV EDI, 2 ; 0ED: 4C8D1C255B020020 LEA R11, [#x2000025B] ; GENERIC-- ; 0F5: 41FFD3 CALL R11 ; 0F8: 480F42E3 CMOVB RSP, RBX ; 0FC: 488D5C24F0 LEA RBX, [RSP-16] ; 101: 4883EC18 SUB RSP, 24 ; 105: 488B0524FFFFFF MOV RAX, [RIP-220] ; 10C: B902000000 MOV ECX, 2 ; 111: 48892B MOV [RBX], RBP ; 114: 488BEB MOV RBP, RBX ; 117: FF5009 CALL QWORD PTR [RAX+9] ; 11A: 480F42E3 CMOVB RSP, RBX ; 11E: 488BFA MOV RDI, RDX ; 121: 488B55F8 MOV RDX, [RBP-8] ; 125: 4C8D1C25E0010020 LEA R11, [#x200001E0] ; GENERIC-+ ; 12D: 41FFD3 CALL R11 ; 130: 480F42E3 CMOVB RSP, RBX ; 134: L0: 488BE5 MOV RSP, RBP ; 137: F8 CLC ; 138: 5D POP RBP ; 139: C3 RET ; 13A: L1: 488B55F0 MOV RDX, [RBP-16] ; 13E: EBF4 JMP L0 ; 140: CC0A BREAK 10 ; error trap ; 142: 02 BYTE #X02 ; 143: 18 BYTE #X18 ; 144: 54 BYTE #X54 ; RCX型宣言とかしてないので、GENERIC-+とかCallしていてイマイチな感じだけれども、実行してみます。マシンはCore2Quad Q9550 2.8GHz, Memory 4GiB、Gentoo GNU/Linux Kernel 3.6.6です。
CL-USER> (time (print (fib 38))) 39088169 Evaluation took: 1.630 seconds of real time 1.704106 seconds of total run time (1.704106 user, 0.000000 system) 104.54% CPU 4,617,572,036 processor cycles 0 bytes consed 39088169元記事のsatosystemsさんの実行環境は
すべての言語と処理系の実行環境は Ubuntu 10.04 が搭載された Let's Note Y4(Pentium M 778MHz、メモリ 1GB)です。とのことなので、直接値の比較はできません。自分のマシン上でのCPythonの結果は22.84秒でしたので、satosystemsさんのマシンより (53.65 / 22.84 =) 2.35倍速いと仮定すると、SBCLでの推定実行時間は (1.63 * 2.35 =) 3.83秒ということになります。
これがどのへんの位置になるかというと、
Scala | 1.90 |
Fortran (gfortran) | 1.92 |
Go (run) | 1.96 |
Haskell (ghci) | 1.99 |
Scheme (ikarus) | 2.07 |
JavaScript (node.js) | 2.62 |
Boo (compile) | 2.67 |
Java (gcj) | 2.88 |
Boo (interpret) | 3.56 |
Common Lisp (SBCL) | 3.83 |
Scheme (Gambit: gcs -O2) | 4.52 |
Scheme (Gambit: gcs) | 7.13 |
Forth (gforth-fast) | 7.39 |
OCaml (ocaml) | 7.53 |
OCaml (ocamlc) | 7.53 |
Forth (gforth) | 8.39 |
Python (CPython) | 58.65 |
Lisp (GNU CLisp) | 211.80 |
Ruby (CRuby) | 213.18 |
と、まぁ、妥当な線に落ち着いたかと。ちなみに、目一杯(declare (optimize (speed 3) (safety 0)) (type fixnum n)) とかしてみたり、色々と弄り回しても、生成コードも実行時間もほとんど変化しませんでした。元記事の結果を見れば分かるのですが、同じ言語でも処理系によって全然結果が違います。つまりは、「言語というより処理系のベンチマーク」ってことなわけですね。
注:コンパイル時に評価しちゃうとか色々と反則技はありますが、こういうのは普通にやってこそ意味があるっぽいので、モヒカンな方々は野暮なツッコミしないでね!
0 件のコメント:
コメントを投稿