Sun Grid Engine を使ってみた
某所で使えたので、手を染めてみました。
まず、実行するプログラムの用意。最近のコンピュータは速いので、ちょっとした計算は直ぐに実行が終わってしまっておもしろくない。以下の様な(超無駄な)乱数を持った行列生成スクリプト make_rand_matrix.rb を用意。2行目(#$の行)は、後でqsubに実行シェルを渡すおまじない。
使い方
./make_rand_matrix.rb 3 500
結果。3x500の行列(各要素は1か-1)を生成して、各行の平均と標準偏差を計算する
0 -0.16 0.99713876380658 1 -0.16 0.99713876380658 2 -0.08 1.00691486781178 Start: Fri Apr 17 13:24:57 +0900 2009 End: Fri Apr 17 13:24:57 +0900 2009 Time: 0.000339
#!/usr/bin/env ruby #$ -S /usr/local/bin/ruby def rand_matrix(n, m) matrix = [] 1.upto(n) do row = Array.new(m).fill(0.0) row_new = row.map do v = rand() if v < 0.5 -1.0 else 1.0 end end matrix << row_new end return matrix end def row_stat(matrix) row_num = 0 matrix.each do |row| sum = 0.0 row.each do |v| sum += v end avg = sum / row.size sd = 0.0 row.each do |v| sd += (v - avg) * (v - avg) end sd = Math.sqrt(sd / (row.size - 1)) print "#{row_num.to_s}\t#{avg.to_s}\t#{sd.to_s}\n" row_num += 1 end end row_num = ARGV.shift col_num = ARGV.shift start_time = Time.now matrix = rand_matrix(row_num.to_i,col_num.to_i) row_stat(matrix) end_time = Time.now diff_time = end_time - start_time print "Start: #{start_time.to_s}\n" print "End: #{start_time.to_s}\n" print "Time: #{diff_time}\n"
これをSun Grid Engineに投入して実行してみる。
% qsub -o `pwd`/stdout.txt -e `pwd`/stderr.txt ./make_rand_matrix.rb 3 50
- o は実行時の標準出力を書き出すファイル。-eはエラー出力のもの。出力がどこで実行しても$HOMEに行くので、カレントディレクトリを頭に付けている。暫くすると実行が終わる。qstat で状態監視できる。
% less stdout.txt [sesejun@gw10] 0 -0.12 1.00285307284481 1 0.12 1.00285307284481 2 -0.04 1.0093440990089 Start: Fri Apr 17 13:30:51 +0900 2009 End: Fri Apr 17 13:30:51 +0900 2009 Time: 0.002694
もっとでかいのも、投入してみる
% qsub -o `pwd`/stdout.txt -e `pwd`/stderr.txt ./make_rand_matrix.rb 3000 5000
(略) 2999 -0.0108 1.00004168746872 Start: Fri Apr 17 13:32:51 +0900 2009 End: Fri Apr 17 13:32:51 +0900 2009 Time: 608.556413
以上は、シングルプロセスだけの話なので、いろいろなサイズの行列を作る作業を並列化する(実行時間にばらつきを持たせたいので)。qsub下では、$HOMEからのパスで指定しないといけないことに注意。
% less make_rand_matrix.sh #!/usr/local/bin/zsh #$ -S /usr/local/bin/zsh for i in {1..10}; do /path/to/qsub -o $WORK_DIR/avg_$i.txt $WORK_DIR/make_rand_matrix.rb `expr $i \* 200` 6000; done;
各実行時間は、以下の感じ。数字が小さい方が実行時間が速いはず何だけと、jobが投入されたマシンによってばらつきがある。同じマシンで、他の重たいjobでも動いていたか?単独で動かしても 1600 x 6000の行列は遅いので、何か別の要因かも。
% tail -n1 avg_{1..10}.txt ==> avg_1.txt <== Time: 19.025231 ==> avg_2.txt <== Time: 72.483549 ==> avg_3.txt <== Time: 163.00908 ==> avg_4.txt <== Time: 294.959056 ==> avg_5.txt <== Time: 472.732914 ==> avg_6.txt <== Time: 704.010809 ==> avg_7.txt <== Time: 964.453544 ==> avg_8.txt <== Time: 1267.160671 ==> avg_9.txt <== Time: 708.957818 ==> avg_10.txt <== Time: 238.609282
全体の実行時間は、20分強(avg_8.txtと同じくらい)でした。単に並列でうごかしただけなので、一番遅いプロセスに引きずられました。