OpenMP* スレッド・アフィニティーの制御

同カテゴリーの次の記事

OpenMP* ループ・スケジュール

この記事は、インテル® ソフトウェア・サイトに掲載されている「OpenMP* Thread Affinity Control」(2013年2月時点) の日本語参考訳です。


はじめに

インテルの OpenMP* ランタイム・ライブラリーには、OpenMP* スレッドを物理処理ユニットにバインドする機能があります。これは、KMP_AFFINITY 環境変数を使用します。システム (マシン) のトポロジー、アプリケーション、オペレーティング・システムによってスレッド・アフィニティーはアプリケーションの速度に大きく影響します。

トピック

スレッド・アフィニティーは、特定のスレッド (仮想実行ユニット) をマルチプロセッサー・コンピューターの物理処理ユニットの一部に限定します。マシンのトポロジーにより、スレッド・アフィニティーはプログラムの実行速度に大きな影響を与えます。

OpenMP* のスレッド化とアフィニティーには、スレッド数の決定と、特定のプロセッサー・コアへのスレッドのバインド方法の決定という 2 つの考慮事項があります。

スレッド化

インテル® Xeon Phi™ コプロセッサーは、コアあたり 4 つのスレッド・コンテキストをサポートしています。そのため、1 つ目の考慮事項は、このプロセッサーで最適なアプリケーション・スレッド数はいくつであるか、ということです。この答えはアプリケーションに依存します。一般に、スレッド数が多ければアプリケーションの本来のレイテンシーは隠蔽されます (1 つのスレッドがメモリーのために待機していても、残りの 3 個のスレッドをプロセッサーで利用できます)。

インテル® Xeon® アーキテクチャーでは、CPU に負担がかかる HPC アプリケーションはハイパースレッディングによるメリットを得られないことが知られていますが、インテル® メニー・インテグレーテッド・コア (インテル® MIC) アーキテクチャーにはこれは当てはまりません。そのため、インテル® Xeon Phi™ コプロセッサーで利用可能な 4 つのスレッド・コンテキストを複数使用してみることが重要です。

具体的には、オフロード・プログラムを N-1 スレッドから 4x(N-1) スレッドまでの異なるスレッド数で実行してみます (N はプロセッサーの物理コアの数)。4 つの単純なパターンを実行します。まず、N-1 スレッドでアプリケーションを実行します。次に、2x(N-1)、3x(N-1)、4x(N-1) スレッドで実行して、スレッド・コンテキストを追加することでアプリケーションのパフォーマンスが向上するかどうかを判断します。

なぜ N ではなく N-1 なのでしょうか? OS のオーバーヘッド – OS および MPSS スレッドもプロセッサーのサイクルを使用するため、OS スレッドが使用しているコアにワーカースレッドをスケジュールすることは非効率です。これは、2 つ目の考慮事項である、インテル® Xeon Phi™ コプロセッサーのコアにスレッドを配置する方法にも関係します。特に、OS スレッドがどのコアを使用しているのか、また OS スレッドが使用しているコアでスレッドがスケジューリングされない方法を考慮します。

ネイティブに実行するアプリケーションでは、OS のオーバーヘッドが少ないため、利用可能なスレッドをすべて (4xN) 使用することもできます。OpenMP* パラメーターのデフォルト値はオフロード実行とネイティブ実行で異なることに注意してください。

アフィニティーと KMP_AFFINITY 環境変数

関連記事: KMP_AFFINITY を使用して OS プロセス ID に対する OpenMP* スレッドマップを作成する (英語)

OpenMP* スレッド・アフィニティーおよび KMP_AFFINITY 環境変数の使い方がよく分からない場合は、まず『インテル® コンパイラー XE ユーザー・リファレンス・ガイド』の「スレッド・アフィニティー・インターフェイス」および「インテル® MIC アーキテクチャー向けプログラミング」をお読みください。

スレッド・アフィニティー・インターフェイスのオンライン・ドキュメント

OpenMP* スレッド・アフィニティーの制御について馴染みがあり、MIC 向けのプロセッサー・マッピングの情報が知りたい場合は、KMP_AFFINITY の 2 つのオプションを試してみてください。

export KMP_AFFINITY=granularity=fine,balanced
export KMP_AFFINITY=granularity=fine,compact

パフォーマンスに影響を与えるもう 1 つの OMP パラメーターは KMP_BLOCKTIME で、OMP ランタイム設定 (スレッドがスリープ状態に移行するまでの待機時間) に影響します。このパラメーターのデフォルト値は 200 ミリ秒です。OpenMP* は、並列領域が別の OpenMP* 領域になる可能性を想定して、この期間スレッドプールを保持します。KMP_BLOCKTIME の値を変更して (0、50、infinite)、パフォーマンスが向上するかどうかを確認してください。

ロード・インバランスが大きい場合は 0 を指定します。(オフロード・アプリケーションでは、MIC_ENV_PREFIX=MIC を指定して MIC_KMP_BLOCKTIME 環境変数に適切な値を設定する必要があることに注意してください)。

まとめ

OpenMP* ランタイムは、OpenMP* ワーカースレッドを特定のプロセッサーにバインドするメカニズムを提供します。インテル® Xeon Phi™ コプロセッサーは、コアあたり 4 つのスレッド・コンテキストをサポートしています。適切な数のスレッド・コンテキストを使用することで、アプリケーションのパフォーマンスが向上します。

インテル® Xeon Phi™ コプロセッサーで N-1 スレッドから 4x(N-1) スレッドまでの 4 つの異なるスレッド数で実行してみます (N はプロセッサーの物理コアの数)。まず、N-1 スレッドでアプリケーションを実行します。次に、2x(N-1)、3x(N-1)、4x(N-1) スレッドで実行して、スレッド・コンテキストを追加することでアプリケーションのパフォーマンスが向上するかどうかを判断します。

各アプリケーションで理想的なスレッド数を調べてください。次に、OS スレッドを実行しているコアを利用しないようにして、OS スレッドとの競合を回避します。以下の設定を試してください。

  • KMP_AFFINITY=granularity=fine,balanced
  • KMP_AFFINITY=granularity=fine,compact

次のステップ

この記事は、「Programming and Compiling for Intel® Many Integrated Core Architecture」の一部「OpenMP* Thread Affinity Control」の翻訳です。インテル® Xeon Phi™ コプロセッサー上にアプリケーションを移植し、チューニングを行うには、各リンクのトピックを参照してください。アプリケーションのパフォーマンスを最大限に引き出すために必要なステップを紹介しています。

「効率良い並列化」に戻る

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

関連記事