今回もperlのお話。初期化に100秒くらいかかる処理を最大で50回くらい繰り返す必要がある。そもそも100秒かかるのってどうなのよという議論もあるものの、差し当たっては現行仕様にて対応を検討する。幸い並行処理のコストは殆どないと考えてよいので、並列化する事で実行時間を短縮したい。並列処理と言えばスレッド、スレッドと言えばJAVAというのが自分の先入観だが、前回同様perlの手軽さに慣れつつある現状、この処理もperlで作成してみようと思う。まずはググったり、詳しい人にヒアリングしたりで情報収集。
ググった限りでは、perlのスレッドはバージョン5.8以降で大分よくなった模様。しかし、perl経験者に聞いてみるとやはりスレッドに対する不安感は払拭し切れていないようでマルチプロセスを薦められる。確かに5.8系のスレッドでも、生成に時間がかかるなどの不具合はあるらしい。今回はスレッド間でステータスの共有などをしたいので、(プロセスモデルでも出来るのかもしれないが)ともかくスレッドで作ってみて不具合が起きるようであれば再検討する事とする。という訳で、next stepとしてサンプル探しとコーティングに移る。
サンプルも思ったより幾つもあるし、スレッドを使用するに当たって特にモジュール・インストール等も必要ないようだ。以下のようなサンプルを作って実際の動きを試してみたところ、あっさりと期待通りの結果となり、またしてもperlの手軽さを実感する。
use threads; use threads::shared; for (1..5) { threads->new(&main, $_); } $_->join for threads->list; sub main { for (1..10) { sleep 1; print "thread => @_, count => $_ n"; } } |
見慣れない処理の説明だけ加えておくと、各スレッドの処理が完了するのを待つ為に『$_->join for threads->list;』という命令を入れている。この処理に今度は、スレッド間で共有するステータス管理用のハッシュを追加する。このような変数は『our %status : shared;』のように定義する。これを加えてみたサンプルが以下。
use threads; use threads::shared; our %status : shared; for (1..5) { $status{$_} = "starting"; threads->new(&main, $_); } for my $name (sort keys %status) { print "thread$name status : $status{$name}n"; } $_->join for threads->list; for my $name (sort keys %status) { print "thread$name status : $status{$name}n"; } sub main { for (1..10) { sleep 1; print "thread => @_, count => $_ n"; } $status{$_} = "done"; } |
これも期待通りの動き。特にスレッドの生成に時間がかかるということもなく普通に動いてくれる。今回の処理には最低でも2回に分けて動かすなど更に幾つかの要件があるが、それらは特に言語でどうこうという話でもないので、このサンプルを元にperlのスレッドを使って実装していく事にする。