2007.05.24 14:37
RubyでえせMapReduceもどきを作ってみた。
Enumerable#map_reduceを定義した。
このメソッドは二つの引数をとる。
一つ目はmap実行用のprocオブジェクト、
二つ目はreduce実行用のprocオブジェクトである。
こんな感じで使える:
1から100000までの二乗和を
・普通にmapとinjectで求めたもの
・map_reduceで求めたもの
それぞれベンチマークをとってみた。
Erlangのような素敵な環境と、RubyのThreadを
何も考えずに使ったときの違いは言わずもがなである。
プロセッサの数などおかまいなし。
みんなの予想通り、ベンチマーク結果はこんな感じ:
26倍ほど遅くなった。
(ちなみに7.56/0.29≒26はghciで計算した)
ruby 1.9で試してみると、
ありゃりゃ、死んじゃった。
Enumerable#map_reduceを定義した。
このメソッドは二つの引数をとる。
一つ目はmap実行用のprocオブジェクト、
二つ目はreduce実行用のprocオブジェクトである。
module Enumerable
def map_reduce(map, reduce)
aggr = self.map {|i|
Thread.start { map.call(i) }
}
aggr.map {|t| t.value }.inject(&reduce;)
end
end
こんな感じで使える:
[1, 2, 3, 4, 5].map_reduce(lambda {|i| i**2 },
lambda {|r, e| r + e })
1から100000までの二乗和を
・普通にmapとinjectで求めたもの
・map_reduceで求めたもの
それぞれベンチマークをとってみた。
# 1から100000までの二乗和を計算する
require 'benchmark'
Benchmark.bm do |x|
x.report {
(1..100000).map {|i| i**2 }.inject {|r, e| r + e }
}
x.report {
(1..100000).map_reduce(
lambda {|i| i**2 },
lambda {|r, e| r + e } )
}
end
Erlangのような素敵な環境と、RubyのThreadを
何も考えずに使ったときの違いは言わずもがなである。
プロセッサの数などおかまいなし。
みんなの予想通り、ベンチマーク結果はこんな感じ:
user system total real
0.280000 0.010000 0.290000 ( 0.282418)
4.350000 3.210000 7.560000 ( 7.568136)
26倍ほど遅くなった。
(ちなみに7.56/0.29≒26はghciで計算した)
ruby 1.9で試してみると、
user system total real
0.220000 0.010000 0.230000 ( 0.227644)
map_reduce.rb:5:in `start': can't create Thread (35) (ThreadError)
from map_reduce.rb:5:in `block in map_reduce'
from map_reduce.rb:4:in `each'
from map_reduce.rb:4:in `map'
from map_reduce.rb:4:in `map_reduce'
from map_reduce.rb:18:in `block (2 levels) in '
from /Users/ujihisa/Documents/ruby-1.9.0/lib/ruby/1.9/benchmark.rb:293:in `measure'
from /Users/ujihisa/Documents/ruby-1.9.0/lib/ruby/1.9/benchmark.rb:377:in `item'
from map_reduce.rb:17:in `block in '
from /Users/ujihisa/Documents/ruby-1.9.0/lib/ruby/1.9/benchmark.rb:177:in `benchmark'
from /Users/ujihisa/Documents/ruby-1.9.0/lib/ruby/1.9/benchmark.rb:207:in `bm'
from map_reduce.rb:13:in `'
ありゃりゃ、死んじゃった。
コメント