マシンの負荷を見ると、16あるCPUコアの1つに負荷が偏っている状態でIO負荷も低いので、並列処理による高速化が期待できるのは明白なのだが、並列処理には近寄りがたい雰囲気を感じていた。「変数が破壊される」「プロセスが無限に生成されてマシンが停止してしまう」といった恐れがあるのでPerlの解説書では「黒魔術」とも呼ばれる並列処理だが、悠長なことは言ってられない。解説書やWebサイトを見ながら検証を進めることにした。
Perlによる並列処理には、fork()を使ったマルチプロセスとithreadによるマルチスレッドの2種類が考えられる。今回は並列実行している処理間で一部の変数を共有する必要があるため、マルチスレッドを選択した。
詳細についてはPerlマルチスレッドのWikにまとめたので、そっちを参照してもらいたいが、まあ一筋縄ではいかなかった。苦労した点は次の通り
- 呼び出し元のルーチン(通常はmain)でスレッドセーフでないモジュールを利用するとsegmentaion falutが発生する。実はEncodeモジュールがそれに該当するらしく、このエラーを解決するのに手間取った。
- Thread::Semaphoreで共有する変数の宣言の場所によっては「Scalars leaked」をいう意味不明な警告が発生する。
- threads::sharedによって共有した変数にアクセスするコストがバカにならない(ロックなしで参照だけでも)。頻繁にアクセスさせず、サブルーチンのスコープで変数を保持して、そこに求める値がなければ共有変数にアクセスする、といった工夫が必要。
0 コメント:
コメントを投稿