ボトルネック分析によってOpenMPの潜在能力を開放する
Carlo del Mundo, Contributing Editor

並列プロセッサーの潜在的計算能力を実現するためには、アプリケーションを制限するボトルネックを、プログラマーが確認する必要がある。これらのボトルネックは、アプリケーションの完全な潜在能力を妨げ、性能を鎖でつないでいる。性能分析は、プログラムの最適化の機会を確認するために、必要なデータと洞察を一般的に提供する。
Inderprastha工科大学の研究者は、OpenMPプログラミング・モデルを使って、マルチコアCPUのために、一般的なボトルネックを確認する。Intdeprastha工科大学の教員であるAlok Katiyer氏は、次のように注意する。「OpenMPプログラムの作成は簡単ですが、単にディレクティブを挿入するだけでは充分でありません。得られたプログラムは期待される性能に届かないかもしれませんし、どのように状況を直すべきか明らかでない場合もあります。」
International Journal of Computer Scienseに最近掲載された論文において、Katiyar氏はOpenMPプログラムのためのボトルネック分析に関する一般的な規則とヒントを提案した。要約すると、次に集中するようにプログラマーに勧めている。(1) 同期 (2) 記憶アクセス・パターン (3) ロード・アンバランス。
以下は、OpenMPプログラマーへのtipsの概要である。
「critical region」を避けるか、取り除きなさい。同期において、「critical」と「barrier」は、アプリケーションのオーバーヘッドに大きく影響する。可能な場合はいつでも、領域中のコードを減らすか取り除くことによって、大きな「critical region」を避けなさい。「critical region」は、他のスレッドが何もしていない間に、マスター・スレッドだけが実行する。この技法によって、「critical region」がアトミックに実行されると保証される。貧弱な性能は、しばしば、「critical region」の数と大きさに相関している。
ループの回し方を変えて、アクセス・パターンを最適化しなさい。最適なアクセス・パターンは、記憶階層の有効利用によって特徴付けられる。ループの入れ換え、アンローリング、融合、分割は、アプリケーションの性能を向上させられるかもしれない、ループの変更例である。交換は、内側のループと外側のループの入れ換えに集中し、記憶レイアウトを利用して、性能を改善できることがある。例えば、列方向(row-major)アクセス・パターンは、同一のキャッシュ・ラインにある複数のデータ要素にまとめてアクセスできることがある。(訳注:多次元配列を多重ループで処理する際に、Fortranならば左側、Cならば右側の添え字を、内側のループで回せということである。逆にすると、複数のスレッドが同一のキャッシュ・ラインにアクセスする偽共有(false sharering)が発生して速度が落ちる。)アンローリングは、ループ変数と関連するオーバーヘッドを減らす。融合は、連続するループを一つにまとめることで、分割はその逆である。個々の技法を使うべきかどうかは、アプリケーションに依存する。
(訳注:ループの融合と分割については、理化学研究所の青山氏幸也氏が執筆した「チューニング技法入門」いわゆる「虎の巻」が詳しい。http://accc.riken.jp/secure/4467/tuning-technique_main.pdf)
ワークロードをバランスさせなさい。より多くの作業をするスレッドがより長時間実行されるために、ワークロードのアンバランスが起きる。chunkごとの作業量の違いが少なくなるように、プログラマーは作業を分割できる必要がある。どれだけの作業量があるか事前に解っている場合には、「static」なスケジュールは完全に妥当である。しかし、例えば、作業量が入力データに依存して実行時に動的に決まる場合には、「dynamic」なスケジュールがより適切である。プログラマーは、OpenMP指示行で「static」と「dynamic」を選択できる。
Katiyer氏の注釈によると、これらの最適化をOpenMPによる行列積に適用し、改良前より相当な性能向上をできた。