while(true) ;

クソNoobな情報系学生のblog。c++やRuby, Railsやってます。perlは猛勉強中。

RubyにおけるThreadとForkの速度比較

こんばんは、kazunyaaanです。今回は並列処理の速度比較を行います。
(個人的に専門が数値計算で、MPI等でごりごり並列化をおこなっているのでとてもわくわくです(笑))

前回の記事で、RubyにおけるThreadは多くの場合にて
"並行処理となる"
ことに簡単にふれてみました。

今回は、Threadだけでなく、Forkも含めた、
Rubyでのマルチスレッドおよびマルチプロセスのプログラムとその速度比較を行ってみたいとおもいます。

まず実験環境

今回は贅沢に

の計算機サーバを使って、CentOS7、Ruby 2.2.0 の実験環境を用意しました。

コード

今回は、

  • Normal : 普通に書いた場合

  • Thread : Threadを用いたマルチスレッド

  • Fork : Forkを用いたマルチプロセス

の3つの浮動小数点の加算の速度比較を行います。

以下、Rubyにおけるコードです。

これを実行すると、こんな感じで結果が得られます。

$ruby add_speed.rb                                            
        12    0.000    0.001    0.095
        24    0.000    0.001    0.116
        48    0.000    0.001    0.119
        96    0.000    0.001    0.152
       192    0.000    0.001    0.185
       384    0.000    0.001    0.109
       768    0.000    0.001    0.166
      1536    0.000    0.001    0.127
      3072    0.000    0.001    0.093
      6144    0.000    0.002    0.144
結果

では、今回行ったRubyのNormal, Thread, Forkの速度比較の結果を見ていきます。

gnuplotでプロットした結果です。まずはそのまま結果をプロット。

f:id:kazunyaaan:20150117015131p:plain

続いて、Normalに対する速度向上比を見てみます。

f:id:kazunyaaan:20150117005322p:plain

考察

それぞれ普通に書く場合、マルチスレッドの場合、マルチプロセスの場合を比較しました。

やはりRubyのThreadクラスを用いたマルチスレッドでの処理では、仕様上、複数のプロセスを活かす並列処理を行えませんでした。
(詳しくはこちらRubyのスレッド周りの話 - Qiita)

また、ThreadとForkに関してそれぞれの生成コストがとても大きいことがわかりますね。
(rubyにおいて、普通に書いた、シングルスレッドは相当優秀ですね...)*1

ただ、かなり大掛かりな処理になると、Forkは約10倍の速度向上も見られます。

.


以下、個人的なおまけ。(偏見込み)

おk。重い処理はForkで組めばいいのね。

これは、良くない考えかと思います。 Forkでプログラムを組むと確かに、Ruby複数のコアを活かせる処理ができます。
しかし、デメリットとして、

  • マルチプロセスの為、メモリ空間がプロセス毎に分けられる。
  • 結果等を受け取るには、プロセス間通信が必要。(socketやパイプ)
  • 何より、並列化等実装のコストが...

などなど...。
そもそもRubyに処理速度を求めるのは間違いですね。 速さが重要なら、C++等でGPGPUやMPIですかね。

じゃあ、Threadのメリットって?

今回は活かしきれないThreadですが、

  • クローラー
  • Thread + Queue を使ったプログラム 等に、大きなメリットがあるかと思います。

このへんは、後日簡単なプログラムでメリットを見ていきたいとおもいます。

*1:今回は、Threadが活かしにくいプログラムとなっています