2007-12-25[n年前へ]
2009-10-06[n年前へ]
■無料配布MathematicaカーネルとNET Framework実装IronRubyでグリッド・Matheatica計算環境は5分で作れる
今日も、「無料配布のMathematicaカーネルと(やはり同じく無料で使うことができる).NET Framework上で動作するRubyであるIronRuby」を使って色々なことをしてみよう、という話の続きです。もちろん、さらにパワーアップした可能性を追求してみたいと思います。
数式処理環境であるMathematicaには、オプション製品としてgridMathematicaという製品があります。Mathematicaでグリッド・コンピューティングを実現する、というようなネーミングの製品ではありますが、実際にはMathematicaで並列(パラレル)計算を実現するための拡張オプションです。価格は・・・眼の球が10cmくらいは前に突き出てしまうほどのお値段になっています。
さて、「無料配布のMathematicaカーネルと(やはり同じく無料で使うことができる).NET Framework上で動作するRubyであるIronRuby」を使えば、色々なことができるわけです。そこで、今日はgridMathematicaが可能にするようなことを、誰でも入手可能なツールで実現してみることに挑戦してみようと思います。
本来ならば、分散処理環境をRubyで実装したdRubyなどを使いたいところですが、いくつかの理由から、今日は(IronRubyで動作する)ごくごく普通のRubyライブラリを使って、Mathematicaカーネルをネットワーク上で並列計算させることができるコードを書いてみることにします。
まずは、(無料配布されている)Mathematicaカーネルを扱うサーバ・アプリを書いてみます。といっても、単にこれだけのコードです。
class Mathematica require 'Wolfram.NETLink' include Wolfram::NETLink def initialize() end def open @kernelLink=MathLinkFactory.CreateKernelLink() @kernelLink.WaitAndDiscardAnswer() end def do(command) @kernelLink.EvaluateToInputForm(command, 0) end def close @kernelLink.EvaluateToInputForm('MVClose[]', 0) end end require 'webrick' include WEBrick m=Mathematica.new m.open s=HTTPServer.new(:Port=>ARGV[0].to_i, :DocumentRoot=>'', :RequestTimeout=>600, :MaxClients=>1) s.mount_proc("/restart") {m.close;m.open} s.mount_proc("/shutdown") {s.shutdown} s.mount_proc("/"){|req,res| res.body='use /evaluate/command' if /evaluate\/(.+)$/=~req.path res.body=m.do($1) end } trap("INT"){m.close;s.shutdown} s.startこれは、例題のため、多くの処理をはしょっていますが、例題の範囲ではきちんと動作するコードです。ひとことで言えば、URIを介して渡されたコマンドを実行した結果を返すWEBサーバアプリです。
ちなみに、このスクリプトを mathematicaServer.rb と名付ければ、
ir.exe mathematicaServer.rb 80という具合で、ポート80番でコマンドを待ち受けるWEBサーバが起動します。あるいは、
ir.exe mathematicaServer.rb 81とすれば、ポート81番でコマンドを待ち受けるWEBサーバが起動します。複数台のPC上で実行しても構いませんし、あるいは、(テスト用として)一台のPC上で複数のサーバを実行しても構いません。もちろん、多数台のPC上でサーバー群を立ち上げる方が高性能になるのは言うまでもありません。
さて、ここまで来たら、後はそれらのサーバ群に"Mathematica"による並列計算をさせるスクリプトを書いてみることにしましょう。たとえば、こんな感じです。
require 'pp' require 'net/http' Net::HTTP.version_1_2 result=[] threads = [] command='2+2' uri=['localhost','localhost'] port=[80,81] 2.times do |i| threads.push( Thread.new do Net::HTTP.start(uri[i],port[i]){ |http| r=http.get('/evaluate/'+command); result<<r.body;} end ) end threads.each do |t| t.join end pp resultこのスクリプトをmathematicaController.rbとでも名付け、
ir.exe mathematicaController.rbという風に起動してやります。もちろん、この並列計算を行わせるコントローラ側はIronRubyである必要はありませんから、
ruby mathematicaController.rbでも構いませんし、計算サーバ群は結局のところ単なるWEBサーバ群なのですから、Rubyプログラムである必要もありません。
このスクリプトの内容はとても簡単です。上の例であれば、ローカルPC上で動いている、2つのMathematicaカーネルを使ったサーバに対して、"2+2"という計算をパラレル(並列)に投げて、その結果を受け取りまとめているわけです。その結果、
["4","4"]という計算結果が最終的には手に入ることになります。httpを使い、また、コマンドのをエンコード処理を行わずGETで投げつけていますが、それはあくまで簡単なテスト用であるためです。
Mathematicaという最高の開発環境を使い、並列計算も可能にし、さらに、そういったプログラムを自分で書くことができる・・・なんて、とても楽しそうではありませんか?この「無料配布のMathematicaカーネルと(やはり同じく無料で使うことができる).NET Framework上で動作するRubyであるIronRubyを使って、遊んでみよう」というシリーズ!?の可能性はまだまだ広がりそうです。
さまざまなデータに対し透過的にアクセスが可能で、並列計算もとても簡単にできたなら、色々なことができそうだ、と思えますよね?無料配布のMathematicaカーネルとNET Framework実装IronRubyでグリッド・Matheaticaコンピューティングのプログラムは、実際のところ5分程度で作ることができます。
無料配布のMathematicaカーネルなのに、それが実に多くのことができることに驚かされます。少し時間ができたとき、こんなプログラムを作って遊んでみるのはいかがでしょうか。
2009-10-21[n年前へ]
■無料のMathematicaカーネルとIronRubyでP2Pグリッド数式処理システムを作ってみよう
少し前、「無料配布のMathematicaカーネルと(やはり同じく無料で使うことができる).NET Framework上で動作するRubyであるIronRuby」を使い、「無料配布MathematicaカーネルとNET Framework実装IronRubyでグリッド・Matheatica計算環境は5分で作れる」 という記事で、Mathematicaで並列計算を可能にするためのコード例を書きました。制御用マシンと計算用サーバ間の通信はhttpを使い、多数のサーバ群で高機能数式処理並列計算を実行することができるシステムを無料で構築しよう、というアイデア・実装です。
今日は、その時書いたコードをもう少し書きなおしてみました。書き直した点をひとことで言えば、それは「制御用マシン(用ソフト)」「計算用サーバソフト」といった区別をなくしたクラスを作ってみたということになります。また、それに加えてコマンドの投げ方を替えた&コマンドを投げる際にURLエンコードをかけるようにした、という変更を行いました。それが、下の(Iron)Rubyクラスです。
というわけで、まずはこんなコードを書いてみましょう。名前は、mathnode.rbとでもしておきます。
class Mathematica require 'Wolfram.NETLink' include Wolfram::NETLink PAR="-linkmode launch -linkname 'C:\\Program Files\\Wolfram Research\\ Mathematica Player\\7.0\\MathKernel.exe'" def initialize() end def open @kernelLink=MathLinkFactory.CreateKernelLink(PAR) @kernelLink.WaitAndDiscardAnswer() end def do(q) @kernelLink.EvaluateToInputForm(q, 0) end def close @kernelLink.EvaluateToInputForm('MVClose[]', 0) end end class Mathnode require 'webrick' include WEBrick require 'net/http' require 'uri' Net::HTTP.version_1_2 attr_reader :server def initialize() @m=Mathematica.new @m.open end def start(port) @server=Thread.new do @s=HTTPServer.new(:Port=>port, :DocumentRoot=>'', :RequestTimeout=>600, :MaxClients=>1) @s.mount_proc("/restart") {@m.close;@m.open} @s.mount_proc("/shutdown") {@s.shutdown} @s.mount_proc("/"){|req,res| res.body='use /evaluate/command' res.body=URI.encode(@m.do(URI.decode(req.query['q']) )) if req.query['q'] } trap("INT"){@m.close;@s.shutdown} @s.start end end def stop @server.shutdown end def sendCommand(host,port,q) result='' Net::HTTP.start(host,port){ |http| r=http.get('/evaluate?q='+URI.encode(q)) result=URI.decode( r.body ) } result end endこのクラスを使い、たとえば、こんなコードを書きます。
require 'mathnode.rb' mathnode=Mathnode.new mathnode.start(ARGV[0].to_i) mathnode.server.join名前は、node.rbとでもしておきましょうか。そして、コマンドラインから、こんな風に実行します。引数は、httpでコマンドを待ち受けるTCP/IPのポート番号です。
ir.exe node.rb 80これで、ポート番号80を用い、プロトコルはhttpで、コマンドを待ち受け続けるサーバが立ち上がります。
さて、同じmathnode.rbを使って、今度は計算をさせるための制御用コントローラを書いてみましょう。名前は、main.rbとでもしましょうか。
require 'mathnode.rb' mathnode=Mathnode.new puts mathnode.sendCommand( 'localhost',ARGV[0].to_i, 'Solve[x+y==3,x]')これで、先ほど立ち上げた「計算用サーバ」に対して、x+y==3という一次代数方程式をxについて解かさせるプログラムのできあがり、です。使い方は、
ir.exe main.rb 80です。これで、localhostの80番ポートでMathematicaコマンドを待ち受けるサーバに、x+y==3という一次代数方程式をxについて解かせるプログラムの出来上がりです。
重要なのは、「計算用サーバ」と「制御用コントローラ」は、主従関係にあるようなクラスではなく、完全に同一のクラスである、ということです。ですから、peer to peer でデータ・命令を投げ合うグリッド計算システムを書き上げることもできるわけです。
もちろん、前回「無料配布MathematicaカーネルとNET Framework実装IronRubyでグリッド・Matheatica計算環境は5分で作れる」で書いたようなプログラムとして、こんな風に書いても構いません。
require 'pp' require 'net/http' require 'uri' Net::HTTP.version_1_2 result=[] threads = [] command='Solve[x+y==3,x]' uri=['localhost'] port=[80] 2.times do |i| threads.push( Thread.new do Net::HTTP.start(uri[i],port[i]){ |http| r=http.get('/evaluate?q='+URI.encode(command)); result<<URI.decode( r.body );} end ) end threads.each do |t| t.join end pp resultこれでも、全く同じ計算結果を得ることができる、無料のMathematica並列計算環境ができあがります。
実際の使い勝手としては、「制御用マシン」「計算用サーバ群」という作りでも良いような気もしますが、それだけではつまらないので、今日はP2Pグリッド数式処理システムを作ってみた、というわけです。無料で使える道具だけで作ることができて、なおかつ、広い可能性が感じられるもの、ではないでしょうか。