2012-12-30

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

年末でおうちにいるので、ちょっと遊んでみることにしましょう。
satosystemsさんによる、こんなブログエントリ「フィボナッチで各種言語をベンチマーク」をみつけました。ほんとに沢山の言語で同じアルゴリズムのプログラムを記述して実行に必要な時間を計測してます。で、結果は記事を見ていただくとして、

Python(CPython) 53.651
Lisp (GNU CLisp) 211.802

とか書いてあるわけです。んー、よりによってCLispですか。この処理系はちょっと遅いしなぁ。他の言語はNative Code Compilerとか使ってるし、ワシが日頃使っているCommon Lisp処理系であるところのSBCLで計測してみました。コードは全く同じで以下の通り。
  1. (defun fib (n)  
  2.   (if (< n 2) n  
  3.       (+ (fib (- n 2)) (fib (- n 1)))))  
SBCL 1.0.55のコンパイラによるNative Codeの出力は以下のとおり。
  1. ; disassembly for FIB  
  2. 0784808D:       488B55F0         MOV RDX, [RBP-16]  
  3. ;      091:       BF04000000       MOV EDI, 4  
  4. ;      096:       488D0C2530040020 LEA RCX, [#x20000430]      ; GENERIC-<  
  5. ;      09E:       FFD1             CALL RCX  
  6. ;      0A0:       0F8C94000000     JL L1  
  7. ;      0A6:       488B55F0         MOV RDX, [RBP-16]  
  8. ;      0AA:       BF04000000       MOV EDI, 4  
  9. ;      0AF:       4C8D1C255B020020 LEA R11, [#x2000025B]      ; GENERIC--  
  10. ;      0B7:       41FFD3           CALL R11  
  11. ;      0BA:       480F42E3         CMOVB RSP, RBX  
  12. ;      0BE:       488D5C24F0       LEA RBX, [RSP-16]  
  13. ;      0C3:       4883EC18         SUB RSP, 24  
  14. ;      0C7:       488B0562FFFFFF   MOV RAX, [RIP-158]  
  15. ;      0CE:       B902000000       MOV ECX, 2  
  16. ;      0D3:       48892B           MOV [RBX], RBP  
  17. ;      0D6:       488BEB           MOV RBP, RBX  
  18. ;      0D9:       FF5009           CALL QWORD PTR [RAX+9]  
  19. ;      0DC:       480F42E3         CMOVB RSP, RBX  
  20. ;      0E0:       488955F8         MOV [RBP-8], RDX  
  21. ;      0E4:       488B55F0         MOV RDX, [RBP-16]  
  22. ;      0E8:       BF02000000       MOV EDI, 2  
  23. ;      0ED:       4C8D1C255B020020 LEA R11, [#x2000025B]      ; GENERIC--  
  24. ;      0F5:       41FFD3           CALL R11  
  25. ;      0F8:       480F42E3         CMOVB RSP, RBX  
  26. ;      0FC:       488D5C24F0       LEA RBX, [RSP-16]  
  27. ;      101:       4883EC18         SUB RSP, 24  
  28. ;      105:       488B0524FFFFFF   MOV RAX, [RIP-220]  
  29. ;      10C:       B902000000       MOV ECX, 2  
  30. ;      111:       48892B           MOV [RBX], RBP  
  31. ;      114:       488BEB           MOV RBP, RBX  
  32. ;      117:       FF5009           CALL QWORD PTR [RAX+9]  
  33. ;      11A:       480F42E3         CMOVB RSP, RBX  
  34. ;      11E:       488BFA           MOV RDI, RDX  
  35. ;      121:       488B55F8         MOV RDX, [RBP-8]  
  36. ;      125:       4C8D1C25E0010020 LEA R11, [#x200001E0]      ; GENERIC-+  
  37. ;      12D:       41FFD3           CALL R11  
  38. ;      130:       480F42E3         CMOVB RSP, RBX  
  39. ;      134: L0:   488BE5           MOV RSP, RBP  
  40. ;      137:       F8               CLC  
  41. ;      138:       5D               POP RBP  
  42. ;      139:       C3               RET  
  43. ;      13A: L1:   488B55F0         MOV RDX, [RBP-16]  
  44. ;      13E:       EBF4             JMP L0  
  45. ;      140:       CC0A             BREAK 10                   ; error trap  
  46. ;      142:       02               BYTE #X02  
  47. ;      143:       18               BYTE #X18  
  48. ;      144:       54               BYTE #X54                  ; RCX  
型宣言とかしてないので、GENERIC-+とかCallしていてイマイチな感じだけれども、実行してみます。マシンはCore2Quad Q9550 2.8GHz, Memory 4GiB、Gentoo GNU/Linux Kernel 3.6.6です。
  1. CL-USER> (time (print (fib 38)))  
  2.   
  3. 39088169   
  4. Evaluation took:  
  5.   1.630 seconds of real time  
  6.   1.704106 seconds of total run time (1.704106 user, 0.000000 system)  
  7.   104.54% CPU  
  8.   4,617,572,036 processor cycles  
  9.   0 bytes consed  
  10.     
  11. 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)) とかしてみたり、色々と弄り回しても、生成コードも実行時間もほとんど変化しませんでした。元記事の結果を見れば分かるのですが、同じ言語でも処理系によって全然結果が違います。つまりは、「言語というより処理系のベンチマーク」ってことなわけですね。

注:コンパイル時に評価しちゃうとか色々と反則技はありますが、こういうのは普通にやってこそ意味があるっぽいので、モヒカンな方々は野暮なツッコミしないでね!

2012-12-11

PySpaとPyFesに参加するワケ

はい。こんにちは。「ワシがいる会社はCommon Lispな会社じゃねーよ。Primary LanguageはPythonだよ!」と誤解を払拭して回る最近ですが、皆様いかがお過ごしでしょうか。さて、PySpaアドベントカレンダーになんか書こうと思って、このブログページの編集を開始してみたら、前回投稿が2年前というアレゲな状態で、もう、なんというか。

で、PySpaって、参加経験がある人にとっては「ああ、楽しいよね。アレ」という存在であり、また、参加したことの無い人にとっては「アレって、いったい何やってるんだ?」という、ものすごく「よくわからない」イベントなわけです。

当時はPython hack-a-thon、今はPython Developers Festaと呼ばれるPythonの名を冠している割には全然Pythonじゃないイベントに顔を出し始めて、そこでPySpaというなにやら怪しげ/楽しそうなイベントがあるという情報をキャッチしたのが3年くらい前。そして過去3回ほどPySpaに参加してるわけですが、妻子持ちのイイ年ぶっこいたオッサンが、空気も読まずに連続参加するには、それなりの理由があるわけです。



ワシがいま居る会社は、ネット広告の配信をやっていて、エンジニアは広告配信とその関連システムをひたすら作るのがミッションなわけです。自社サービスのためのシステム開発なので、リリースはあっても納品とかありません。基本的にエンドレスでひたすらマイルストーンを目指して、それを通過していくわけです。広告技術の進歩は早くて、それをキャッチアップすべく、どんどん前に進んでいかざるを得ないので、ネット広告というドメインでの技術力はどんどんUPしていきます。とにかく目の前の課題に集中しなくちゃやっていけないので、それ以外の部分がどうにも疎かになりがちです。ようするに「今、コレがアツい!」の波に乗り遅れるどころか、気づかずにスルーとか、平気で起こっちゃう。

この文章を読んでいる多くの方が、まだお若いのだと思うのですが、アラフォーともなってくると、それなりの功夫(kung-fu)も積んできていて、よくあるパターンな部分は、その経験で処理できちゃうという場面が多くなってきます。つまり新しい事を積極的に学ばなくても、日常には不便しなくなってくる。さらに20代の頃のあの2徹、3徹をものともしない体力、新しい概念とかを苦もなく吸収できていた脳力もだんだんと………。夢も希望も無い話なんですが、自分が実際にその年に到達してみる
とよく分かるものです。

で、こういう状況を打破する、最も簡単かつ、効果的な方法。「外に出る」です。社内で蛸壺に篭っていても、行き着く先はともすれば尸解仙。とにかく雑多な話題が多く飛び出す場に自分を置くことが大切になってきます。そして面白そうなトピックを集めて、実際に自分であれこれ弄り回すこと。

結婚して、子供が生まれて、社内でもそれなりのポジションになっていってと、まぁ昭和的なストーリーを地で行っちゃうと、エンジニアにとって最も重要な「自分のための時間投資」がどんどんできなくなってきます。休日に技術書を読んで写経してみる。こんな当たり前にできていたことが、子供の「お父さん遊んで〜」に阻まれるのです。まぁピカピカ&カチンコチン泥団子を作ったりして一緒に楽しく遊んじゃうわけですが。ならば、その少ない自分のために使える時間の密度を上げる必要があります。

世の中には多くの「勉強会」が開催されています。専門的なものや、明日の業務に即使える的なものもあるでしょう。そのような中、できる限り参加しようと決めているのは、Python Developers Festa と PySpaという2つです。この選択には、これらのイベントの「雑食性」という大きな理由があります。

Python Developers Festaに参加したことがある方なら、分かると思うのですが、このイベントには普通の「勉強会」にありがちな「今回はみんなでこれをやりましょう」的な縛りがものすごく希薄で、それはもう、参加者それぞれが思い思いに過ごす場として機能しています。ルネッサンスから近代にかけての宮廷のサロン状態とでもいいましょうか。とにかくカバーできる話題の広さといったら、素晴らしいの一言。

このネットの時代に、せっかく沢山の人が集まるメリットは何かということを考える時、この雑多感が非常に重要なものに思えるのです。1つ2つの小さなテーマにまとまるのなら、オンラインの方がよっぽど効率がいいでしょう。そしてPySpaはPyFesの濃縮度を更にUPした環境といえば、間違いは無いはずです。

実はPySpa参加者は妻帯者が多いのです。「熱海」の「温泉旅館」で「3日間」という、これはもう「テッキーな野郎共とモヒモヒしに行くだけだよ〜」という言葉が完全に意味をなさず「ぜってー浮気だろ」なシチュエーションにも関わらず、困難を極めるであろうYAuthを取得して皆が芳泉閣にやってくるのです。これだけで、このPySpaというイベントの持つ引力がどれほどのものかを十分にあらわしているはずです。

そうそう。PySpaとかPyFesとか、なんか凄そうな人たちばっかりで、(俺|私)ごときが参加しても大丈夫なのだろうかと、尻込みしているそこの貴方へ。

自分が大したことでは無いと思っていることが、他の人にとっては魔法であることは、よくあることである 
「お客さん」にならずに「参加者」になろう。たまにマサカリが飛んでくることがあるかもしれないけれど、それは貴方の人格をdisっているわけじゃない。色々なバックグラウンドを持つ人と色々な話をしよう。自分の持っているものを吐き出した人の所にこそ、色々なものが集まってきて、それはきっと貴方の大切な財産になるだろうから。