「dRubyで並列処理 - ohacの日記」を読んだ

dRubyで並列処理 - ohacの日記をいう記事を見たのですが
自分の読解力不足だったので時間をかけて読んだ。
面白かったのでコメントをつけて紹介させて頂きます。

なにか

このサンプルコードは500万回の疑似乱数の中から最も0に近い実数を見つけだすというプログラムです。

http://d.hatena.ne.jp/ohac/20091211/1260503455

dRubyを使ってRubyでネイティブスレッドのようなことを実現しています。

ソースコード

#!/usr/bin/ruby
require 'drb/drb'
class MonteCarlo
  def initialize(seed)
    srand(seed)
  end
  
  #引数:何個の数を調べるか
  #返値:一番小さかった数
  def dice(n)
    best = rand
    n.times do
      r = rand
      best = r if r < best
    end
    best
  end
end

#プロセッサの数(並列にする数)
PROCESSORS = (ARGV[0] || 1).to_i

pids = []

#プロセッサの数だけdRubyサーバとdRubyクライアントを生成する
#workersはMonteCarloの分散オブジェクトの配列
workers = PROCESSORS.times.map do |i|
  uri = "druby://localhost:#{12345 + i}"
  pids << fork { DRb.start_service(uri, MonteCarlo.new(i)); sleep }
  DRbObject.new_with_uri(uri)
end

begin
  n = 5000000 / PROCESSORS
  q = Queue.new
  sleep 0.1
  ts = workers.map do |foo|
    #dice(n)をThreadを使って(ほぼ)同時に呼び出し
    #処理はforkされたdRubyサーバが行うのでRubyでもネイティブスレッドのように動作する
    Thread.start(foo) {|f| q.push(f.dice(n))}
  end
  ts.each{|t| t.join} #子Thread内で例外が起きていればjoinで捕捉できる
  p q.size.times.map{q.pop}.min #キューを配列にしてminで最小値を取得
ensure
  pids.each {|pid| Process.kill(:TERM, pid)} #例外が発生していればdRubyサーバを落とす
end

見所はやはり、連続でdRubyサーバをforkしつつ分散オブジェクトをつくり、分散オブジェクトをThreadで非同期で呼び出すというところです。
dRubyの珍しい使い方なんじゃないでしょうか。とても面白いです。