こんばんは、kazunyaaanです。今回は並列処理の速度比較を行います。
(個人的に専門が数値計算で、MPI等でごりごり並列化をおこなっているのでとてもわくわくです(笑))
前回の記事で、RubyにおけるThreadは多くの場合にて
"並行処理となる"
ことに簡単にふれてみました。
今回は、Threadだけでなく、Forkも含めた、
Rubyでのマルチスレッドおよびマルチプロセスのプログラムとその速度比較を行ってみたいとおもいます。
まず実験環境
今回は贅沢に
Intel Xeon E5-2690 v3 @ 2.60GHz (Turbo Boost時 3.5) 12Core × 1
DDR4 ECC 16GByte @ 2133MHz × 4
の計算機サーバを使って、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でプロットした結果です。まずはそのまま結果をプロット。
続いて、Normalに対する速度向上比を見てみます。
考察
それぞれ普通に書く場合、マルチスレッドの場合、マルチプロセスの場合を比較しました。
やはり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が活かしにくいプログラムとなっています