2012-12-30

たまにはベンチとかして遊んでみる

年末でおうちにいるので、ちょっと遊んでみることにしましょう。
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秒ということになります。
これがどのへんの位置になるかというと、

Scala1.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 件のコメント:

コメントを投稿