Nodeで動かして完結編
終わる終わる詐欺ではありません。アクエリアスと体当たり爆沈して終了です。
Haskell vs F#
↑のエントリを見て、↓の2つのエントリを書いた。今日はその完結編。
HaskellとF#の解読の練習とちょっとした疑問でRubyに移植してみた
Cに書き直して満足して終了
元エントリの中の人とゆかいな仲間達の間では道具選びの結論が出て、既にアルゴリズム改良にいそしんでいます。が、その裏で、未だにワタクシおなじみの言語で書き換えたらどうなるかを一人でやってます。器用貧乏のサガですね。
今日はコードをCoffeeScript(JavaScript)に直して、Node.jsで動かしてみました。おお。速い。
実行結果
$ node --version v0.6.10 $ coffee --version CoffeeScript version 1.2.0 $ coffee -c hoge.coffee $ time node hoge.js 999.9999999999998 node hoge.js 8.26s user 0.08s system 100% cpu 8.289 total
おお!Haskellの15倍の処理時間(15倍遅い)!これは速いほう!!(過去エントリ参照(Ruby編, C編)
v8エンジンって結構優れてるんですね。
感想めいたもの
作りたいアプリケーションに合わせて道具を選びましょうという超当たり前の感想と、F#見直したわーくらいしかなくて、Cに書き直して満足して終了で書いたのと一緒w。
比較表
処理系と実装 | Haskellを1とした場合 | 実処理時間(s) |
---|---|---|
C(llvm-gcc-4.2) | 0.1 | 0.070 |
Haskell (7.4.1) | 1.0 | 0.534 |
Ruby very slow(YARV 1.9.3p0) | 54.2 | 28.935 |
Ruby slow(YARV 1.9.3p0) | 26.8 | 14.296 |
Ruby very slow(JRuby 1.6.5.1) | 58.3 | 31.139 |
Ruby slow(JRuby 1.6.5.1) | 14.5 | 7.724 |
Ruby very slow(MacRuby 0.10) | 331.0 | 176.73 |
Ruby slow(MacRuby 0.10) | 24.1 | 12.855 |
Ruby (MacRuby 0.10) 並列化 | 18.2 | 9.729 |
JavaScript(Node.js 0.6.10) | 15.5 | 8.289 |
CoffeeSctipt
induceBackwardVerySlow = (nodes, values) -> n = Math.floor(values.length / 2) nodes.map*1[0] console.log(Math.max((value(i) for i in [1..ITERATION])...))
しかし、はてなダイアリーってCoffeeScriptのシンタックスハイライト無いんだね…。なんかがっかりだなぁ。。。
コンパイル後のJavaScript
(function() { var ITERATION, i, induceBackwardVerySlow, last_values, test_tree, value; induceBackwardVerySlow = function(nodes, values) { var n; n = Math.floor(values.length / 2); return nodes.map(function(node) { return node.branches.map(function(branch) { return branch.p * values[n + branch.k] * node.df; }).reduce(function(a, b) { return a + b; }); }); }; ITERATION = 1000; last_values = function(i) { var n, _results; _results = []; for (n = 0; n <= 200; n++) { _results.push(i); } return _results; }; test_tree = function() { var _i, _results; return (function() { _results = []; for (_i = 0; _i <= 99; _i++){ _results.push(_i); } return _results; }).apply(this).map(function(i) { var _i, _results; return (function() { _results = []; for (var _i = -i; -i <= i ? _i <= i : _i >= i; -i <= i ? _i++ : _i--){ _results.push(_i); } return _results; }).apply(this).map(function(j) { return { df: 1.0, branches: [ { k: j - 1, p: 1.0 / 6.0 }, { k: j, p: 2.0 / 3.0 }, { k: j + 1, p: 1.0 / 6.0 } ] }; }); }); }; value = function(i) { return test_tree().reverse().reduce(function(values, nodes) { return induceBackwardVerySlow(nodes, values); }, last_values(i))[0]; }; console.log(Math.max.apply(Math, (function() { var _results; _results = []; for (i = 1; 1 <= ITERATION ? i <= ITERATION : i >= ITERATION; 1 <= ITERATION ? i++ : i--) { _results.push(value(i)); } return _results; })())); }).call(this);
*1:node) -> node.branches.map((branch) -> branch.p * values[n + branch.k] * node.df ).reduce((a, b) -> a + b) ) ITERATION = 1000 last_values = (i) -> (i for n in [0..200]) test_tree = -> [0..99].map((i) -> [-i..i].map((j) -> { df: 1.0, branches: [{k: j - 1, p: 1.0 / 6.0}, {k: j , p: 2.0 / 3.0}, {k: j + 1, p: 1.0 / 6.0}] } ) ) value = (i) -> test_tree(). reverse(). reduce((values, nodes) -> induceBackwardVerySlow(nodes, values) , last_values(i