@ledsun blog

無味の味は佳境に入らざればすなわち知れず

Ractorで並列に動いているっぽい?

次の感じのRubyソースコードがあります。

annotations_collection_with_doc.each do |annotations, doc|
  messages += Annotation.prepare_annotations!(annotations, doc, options)
end

Annotation.prepare_annotations!(annotations, doc, options)の先の処理はテキスト処理でCPUバウンドであることがわかっています。 またannotations_collection_with_docは数十であることもわかっています。 そこでつぎのように、入ってきただけバカスカRactorをつくっって並列かしてみました。

Ractor.make_shareable(TextAlignment::CHAR_MAPPING)
Ractor.make_shareable(TextAlignment::LCSMin::PLACEHOLDER_CHAR)
ractors = annotations_collection_with_doc.collect do |annotations, doc|
  r = Ractor.new do
    a, d, o = Ractor.receive
    m = Annotation.prepare_annotations!(a, d, o)
    Ractor.yield [m, a]
  end

  r.send [annotations, doc.dup, options]
  [r, doc]
end

annotations_collection_with_doc = ractors.each do |r, doc|
  error_messages, annotations = r.take
  messages += error_messages

  [annotations, doc]
end

ざっくり見たかんじでは2倍ぐらいの速度では動きました。 4コアあるので、理想的には4倍の速さになって欲しいです。 スレッドを立てすぎて遅いのか、Ractor間のデータのやりとりで遅いのかは謎です。

たぶんキュー作ってワーカーモデルで、並列数を制限すればいいんですけど、面倒臭いですよね。 なるほどー、MaNyでRactorとネイティブスレッドがM:Nで動いてほしいです。

https://github.com/grosser/parallel を使ったら簡単に並列数を制限できるのでしょうか?