Abstract
並列化の方針には,1) 1タスクあたりの実行時間を削減する方針 (ストロング・スケーリング [1]) と,2) 1タスクの実行時間はそのままだが,多数のタスクでも1タスクの時と同じ実行時間で処理する方針 (ウィーク・スケーリング [1]) の 2 種類がある.OpenMP は「OpenMP が使用できない環境では無視されるディレクティブ [2]」を用いて,for 文単位で並列化を行うため,ストロング・スケーリングに向いているが,実際には,並列化をタスク単位に調整すれば,ウェーク・スケーリングに利用できる.
並列化を行う場合に,まず思い浮かべるのは,スレッドを生成しての並列化である.C++11 からは std::thread が標準化されているため,Windows か Linux かを意識せずに並列化できる.しかしながら,単純にタスクをスレッド数で割って処理させると,実行時間の不均一性から,処理の後半でプロセッサに空きができるなど問題がある.プロセッサを遊ばせないためには,タスクを一度スレッドプールに集約し,スレッドプールから,各 CPU に処理を振る必要がある.このような煩雑な処理の実装は,非常に骨の折れる作業である.このような状況に際しても,OpenMP は,ディレクティブ 1 行で並列化され,schedule(guided) オプション1つでスレッドプーロを生成する.
実際に並列化が必要とされる状況について,例えば,多量のデータを扱う場合,CSV 等からタスクの一覧を読み込み,タスクごとに処理することは多い.これは,アムダールの法則 [3] を考えた場合,処理の単位が大きく並列化不能な箇所が少ないため,並列度を上げて実行時間を削減し易い.また,実装に際しても,大きな単位でのみ並列化の面倒を見ればよいため,実装の負担が少ない.
本投稿では,OpenMP の簡単な実装例/実行例を示した後,多数のグラフプロットを必要とする GIF 動画の生成について,OpenMP を用いた並列化を行う.
並列化を行う場合に,まず思い浮かべるのは,スレッドを生成しての並列化である.C++11 からは std::thread が標準化されているため,Windows か Linux かを意識せずに並列化できる.しかしながら,単純にタスクをスレッド数で割って処理させると,実行時間の不均一性から,処理の後半でプロセッサに空きができるなど問題がある.プロセッサを遊ばせないためには,タスクを一度スレッドプールに集約し,スレッドプールから,各 CPU に処理を振る必要がある.このような煩雑な処理の実装は,非常に骨の折れる作業である.このような状況に際しても,OpenMP は,ディレクティブ 1 行で並列化され,schedule(guided) オプション1つでスレッドプーロを生成する.
実際に並列化が必要とされる状況について,例えば,多量のデータを扱う場合,CSV 等からタスクの一覧を読み込み,タスクごとに処理することは多い.これは,アムダールの法則 [3] を考えた場合,処理の単位が大きく並列化不能な箇所が少ないため,並列度を上げて実行時間を削減し易い.また,実装に際しても,大きな単位でのみ並列化の面倒を見ればよいため,実装の負担が少ない.
本投稿では,OpenMP の簡単な実装例/実行例を示した後,多数のグラフプロットを必要とする GIF 動画の生成について,OpenMP を用いた並列化を行う.