RubyのThread、Fiber、Kernel、forkで並列処理やプロセスの深淵へ:若手エンジニア/初心者のためのRuby 2.1入門(11)(3/3 ページ)
オープンソースのオブジェクト指向プログラミング言語「Ruby」の文法を一から学ぶための入門連載。最新版の2.1に対応しています。今回は、スレッドを扱うクラスや軽量スレッド、「グルー言語」でもあるRubyからプロセスを操るさまざまなメソッドの使い方などを解説します。
「Kernel.#fork」メソッドで別のプロセスとして処理を行わせる
Kernelモジュールに定義されている「fork」メソッドを使うと、Rubyプログラムが自分自身の分身となるようなプロセスを生成して、別のプロセスとして処理を行わせることができます。
forkのメリット/デメリット
冒頭で「並列化による高速化を狙ってThreadクラスを使うことは難しい」と書きましたが、「fork」を行うと、OSレベルで別のプロセスが生成されます。OSは各プロセスにCPUコアを振り分けているので、「fork」によって時間のかかる処理をうまく分散化できる可能性があります。また、「fork」されたプロセスは親プロセスと別の世界で動くというメリットもあります。
ただし利点ばかりではありません。頻繁にforkすると、forkのためのオーバーヘッドが無視できなくなりますし、OSのシステムコールに依存する機能なので、forkシステムコールを持たないようなシステムでは利用することはできません。Windowsはforkシステムコールを持たないようですので、forkの恩恵にあずかることは残念ながらできません。
フォークする/しないの違いを調べるサンプルコード
では、process03.rbとprocess04.rbに例を示しましょう。どちらも1億回(!)実数に「0.001」を足し込むような処理を行います。違いは、process03.rbはプロセスをフォークして実行しており、process04.rbはフォークせずに逐次実行している点です。
f = 0.0 started_time = Time.now.to_i 3.times do fork do 100000000.times { f += 0.001 } printf("%.3f\n", f) end end Process.waitall puts "it takes #{Time.now.to_i - started_time} s"
f = 0.0 started_time = Time.now.to_i 3.times do 100000000.times { f += 0.001 } printf("%.3f\n", f) f = 0 end puts "it takes #{Time.now.to_i - started_time} s"
$ ruby process03.rb 100000.000 100000.000 100000.000 it takes 12 s
$ ruby process04.rb 100000.000 100000.000 100000.000 it takes 26 s
コードの解説
process03.rbもprocess04.rbも大筋は同じです。まず、1行目で変数fを0.0で初期化し、2行目で現在の時刻を取得し、それを「to_i」メソッドでUNIX時刻に変換して変数started_timeに格納します。
続く4行目からの「3.times」とそのブロックで、process03.rbではプロセスを3回フォークしています。「fork」メソッドのブロック引数として、fに1億回「0.001」を足し込むような処理を与えています。process04.rbは、単に逐次的に1億回「0.001」を足し込むような処理を行っています。
最後の行で、どちらのスクリプトも、現在のUNIX時刻と開始時のUNIX時刻の差を取り、処理時間を算出しています。
実行の様子
「htop」というツールを使って、process03.rbとprocess04.rbの実行の様子を比べてみましょう。
ご覧の通り、フォークした場合は「ruby process03.rb」というプロセスが3個立ち上がっていることが分かります。たいていの現代的なOSでは、CPUに負荷を掛けるようなプロセスはなるべく別々のCPUコアに割り当てるようにするので、process03.rbの方が処理時間も短く済んでいます。
また、子プロセスはフォークされた時点で、それぞれメモリ空間などが異なる世界で動くことになります。ですので、process03.rbの6行目で変数fを書き換えても、他の子プロセスの変数fに影響することはないので、きちんといずれの子プロセスでも「100000.000」という計算結果が得られています。
次回はRubyの黒魔術「メタプログラミング」
今回は、Rubyのスレッド、ファイバー、プロセスといった仕組みを学びました。特に、RubyのIOクラスやforkメソッドといった仕組みは、OSそのものと深くつながっています。
例えばforkメソッドですが、UNIX系OSの標準的な「システムコール」の中に、ズバリ「フォーク」というものがあります。今回はあまり詳細に立ち入らずに説明したつもりですが、少し難しかったかもしれません。この辺りの話を深く理解するためにはOSの仕組みやシステムコールを学ぶ必要があるので、スキルアップのためにも、ぜひ勉強することをお勧めします。
次回はRubyの黒魔術、メタプログラミングについて解説したいと思います。メタプログラミングについて理解することは、初心者から一歩踏み出して、エキスパートになるたには必須です。お楽しみに!
- Rubyで逆ポーランド変換機を作りgem作成&コマンドの使い方
- 難しいが強力! Rubyのメタプログラミング、self、特異クラス/メソッド、オープンクラスとモンキーパッチ
- RubyのThread、Fiber、Kernel、forkで並列処理やプロセスの深淵へ
- RubyのFile/IOクラスで入力と出力、ファイルの読み取りと書き込み、フィルター作成
- Rubyの例外とその捕捉――基本のbegin〜rescue〜endからensure、else、retry、後置rescueまで
- Rubyの面白さを理解するためのメソッド、ブロック、Proc、lambda、クロージャの基本
- Rubyのオブジェクト指向におけるクラスとモジュール、継承、Mixin、アクセス制御の使い方
- RubyのNumericとTimeで数値と時間をさまざまな操作・演算・判定
- RubyのString/Regexpクラスによる強力な文字列操作/正規表現
- RubyのRangeクラスと範囲オブジェクト、範囲演算子、イテレーターの使い方
- Rubyの配列、ハッシュテーブルを表現するArray、Hashクラスの使い方
- Ruby 2.1の基本構文/基本文法まとめ&Pryの使い方
- Rubyプログラミングを始めるための基礎知識とインストール
著者プロフィール
麻田 優真(Rails技術者認定シルバー試験問題作成者)
イタリア、ローマ生まれ。中学生のころHSPに初めて触れ、プログラミングの楽しさを知る。オープンソースやハッカーカルチャーを好む。C#からRubyに転向したときに、動的型付け言語の柔軟性やメタプログラミングの魅力に感動し、Rubyとともにプログラマーとしての人生を歩む決意を固める。
現在は奈良先端科学技術大学院大学で学生として所属するかたわら、株式会社アジャイルウェアでプログラマーとして従事。Ruby on Railsによるコンシューマー向けのWebサービスの開発などに尽力している。
好きなメソッドは、define_method。
Twitter:@Mozamimy、ブログ:http://blog.quellencode.org/
監修者プロフィール
山根 剛司(Ruby業務開発歴7年)
兵庫県生まれ。1997年からベンチャー系のパッケージベンダーで10年間勤務。当時、使用していた言語はJavaとサーバーサイドJavaScript。
2007年よりITコンサル会社に転職し、Rubyと出会って衝撃を受ける。基幹システムをRuby on Railsで置き換えるプロジェクトに従事。それ以来Ruby一筋で、Ruby on Railsのプラグインやgemも開発。
2013年より、株式会社アジャイルウェアに所属。アジャイルな手法で、Ruby on Railsを使って企業向けシステムを構築する業務に従事。
Ruby関西所属。
Twitter:@spring_kuma、Facebook:山根 剛司
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- 公用語に英語、「再起動」したRubyKaigi 2013が東京で開催
いったん終了していたRubyコミュニティ主催の年次イベントが再開。技術色、国際色を強め、盛況のうちに幕を閉じた - Web業界、今から行くならRubyエンジニアが狙い目?
不況で冷え込んでいたIT業界の転職市場に、回復の兆しが見え始めている。だが、業種や職種によって採用数や条件に大きな差異が生まれている。転職市場の動向を追い、自身のキャリア戦略立案に生かしてほしい。 - Ruby 2.0.0がリリース、大規模化対応の機能などを搭載
生誕20年となる節目を迎えて、プログラミング言語「Ruby」の最新版がリリースされた - 新バージョンで何が変わるのか、Rubyはどこへ向かうのか:まつもと×笹田、Ruby 1.9を語る
- いよいよ始まるRuby 1.9への移行:開発コアメンバが語るRubyの今とこれから(前編)
- Rubyの今後の進化の方向性とは?:開発コアメンバが語るRubyの今とこれから(後編)
- 互換性や脆弱性の問題にどう対応していくのか:Rubyが抱える課題、NaClの前田氏が講演
- Rails Hub情報局:「なんでRubyなんか作った!? 迷惑だ!」に対するMatzの答え
- Rails Hub情報局:Rubyはイノベーション言語として選ばれている
- Rails Hub情報局:Rubyのまつもと氏は、一発屋で終わるのか?
- Rails Hub情報局:Rubyに魔法は要らない
- 数々の“スペル”で高度なプログラミング:Rubyの魔術
- 晴読雨読@エンジニアライフ:『たのしい開発 スタートアップRuby』――なぜRubyistたちはあれほど楽しそうなのか
- 「JRuby 1.7.0」登場、1年半ぶりのメジャーアップデート
JavaVM上のRuby実装「JRuby」の最新版となる「JRuby 1.7.0」が、10月22日にリリースされた。