OpenMP 4.0 では、プログラム内の OpenMP スレッドがプロセッサにバインドされる方法を指定するために OMP_PLACES および OMP_PROC_BIND 環境変数を提供しています。これらの 2 つの環境変数は多くの場合、相互に組み合わせて使用します。OMP_PLACES は、スレッドがバインドされるマシン上の場所を指定するために使用します。OMP_PROC_BIND は、スレッドが場所に割り当てられる方法を規定するバインディングポリシー (スレッドアフィニティーポリシー) を指定するために使用します。OMP_PLACES を単独で設定してもバインディングは有効になりません。OMP_PROC_BIND も設定する必要があります。
OpenMP 仕様では、OMP_PLACES の値は 2 種類の値のどちらかに設定できます。一連の場所 (スレッド、コア、またはソケット) を示す抽象名、または負でない数で示された場所の明示的なリストです。間隔を使用して場所を定義することもできます。その場合、<lowerbound> : <length> : <stride> 表記法を用いると、"<lower-bound>, <lower-bound> + <stride>, …, <lower-bound> + (<length>-1)*<stride>" という数値リストを表現できます。<stride> を省略すると、ユニットの刻み幅が想定されます。OMP_PLACES を設定しない場合、デフォルト値はコア数になります。
使用例 14 各場所にハードウェアスレッドが 1 つある場合% OMP_PLACES="{0:1}:8:32" {0:1} defines a place which has one hardware thread only, namely place {0}. The interval {0:1}:8:32 is therefore equivalent to {0}:8:32, which defines 8 places starting with place {0}, and the stride is 32. So the list of places is as follows: Place 0: {0} Place 1: {32} Place 2: {64} Place 3: {96} Place 4: {128} Place 5: {160} Place 6: {192} Place 7: {224}使用例 15 各場所にハードウェアスレッドが 2 つある場合
% OMP_PLACES="{0:2}:32:8" {0:2} defines a place which has two hardware threads, namely place {0,1}. The interval {0:2}:24:8 is therefore equivalent to {0,1}:24:8 which defines 24 places starting with place {0,1}, and the stride is 8. So the list of places is as follows: Place 0: {0,1} Place 1: {8,9} Place 2: {16,17} Place 3: {24,25} Place 4: {32,33} Place 5: {40,41} Place 6: {48,49} Place 7: {56,57} Place 8: {64,65} Place 9: {72,73} Place 10: {80,81} Place 11: {88,89} Place 12: {96,97} Place 13: {104,105} Place 14: {112,113} Place 15: {120,121} Place 16: {128,129} Place 17: {136,137} Place 18: {144,145} Place 19: {152,153} Place 20: {160,161} Place 21: {168,169} Place 22: {176,177} Place 23: {184,185}
OpenMP 4.0 では、2 つの環境変数 OMP_PLACES および OMP_PROC_BIND に加え、parallel ディレクティブで指定できる proc_bind 節も提供しています。proc_bind 節は、並列領域を実行するスレッドのチームがプロセッサにバインドされる方法を指定するために使用します。
OMP_PLACES および OMP_PROC_BIND 環境変数と proc_bind 節の詳細は、OpenMP 4.0 仕様を参照してください。
このセクションでは、OpenMP 4.0 仕様の OpenMP スレッドアフィニティーの制御に関するセクション 2.5.2 について詳しく説明します。
スレッドが proc_bind 節を含む並列構文を検出すると、OMP_PROC_BIND 環境変数を使用して、スレッドを場所にバインディングするためのポリシーが決定されます。並列構文に proc_bind 節が含まれている場合は、その proc_bind 節で指定されたバインディングポリシーによって、OMP_PROC_BIND で指定されたポリシーがオーバーライドされます。チーム内のスレッドが場所に割り当てられると、実装時にそれが別の場所に移動されることはありません。
マスタースレッドアフィニティーポリシーは、チーム内のすべてのスレッドをマスタースレッドと同じ場所に割り当てるよう実行環境に指示します。このポリシーで場所パーティションは変更されないため、それぞれの暗黙的タスクは、親の暗黙的タスクの place-partition-var 内部制御変数 (ICV) を継承します。
クローズスレッドアフィニティーポリシーは、チーム内のスレッドを親スレッドの場所に近い場所に割り当てるよう実行環境に指示します。このポリシーで場所パーティションは変更されないため、それぞれの暗黙的タスクは、親の暗黙的タスクの place-partition-var ICV を継承します。T がチーム内のスレッド数で、P が親の場所パーティション内の場所の数である場合、チーム内のスレッドの場所への割り当ては次のようになります。
T <= P。マスタースレッドは親スレッド (つまり、並列構文を検出したスレッド) の場所で実行されます。次にもっとも小さいスレッド番号を持つスレッドが場所パーティション内の次の場所で実行され (以下同様に続く)、マスタースレッドの場所パーティションからラップアラウンドします。
T > P。それぞれの場所 P には連続するスレッド番号を持つ Sp のスレッドが入ります。ここでは、floor(T/P) <= Sp <= ceiling(T/P) です。最初の S0 スレッド (マスタースレッドを含む) は親スレッドの場所に割り当てられます。次の S1 スレッドは場所パーティション内の次の場所に割り当てられ (以下同様に続く)、マスタースレッドの場所パーティションからラップアラウンドします。T が P によって均等に分けられない場合、特定の場所に含まれるスレッドの正確な数は実装によって定義されます。
分散スレッドアフィニティーポリシーの目的は、T 個のスレッドから成るチームを親の場所パーティションの P 個の場所に配分するための疎配分を作成することです。疎配分を求めるには、最初に親パーティションを T 個のサブパーティション (T <= P の場合) または P 個のサブパーティション (T > P の場合) にさらに分けます。次に、1 つのスレッド (T <= P) または 1 組のスレッド (T > P) が各サブパーティションに割り当てられます。それぞれの暗黙的タスクの place-partition-var ICV がそのサブパーティションに設定されます。サブパーティション分割は、疎配分を求めるためのメカニズムであるだけでなく、入れ子並列領域の作成時に使用するスレッドの一部の場所も定義します。スレッドの場所への割り当ては次のとおりです。
T <= P。親スレッドの場所パーティションは T 個のサブパーティションに分けられ、各サブパーティションには floor(P/T) または ceiling(P/T) の連続する場所が含まれます。各サブパーティションには 1 つのスレッドが割り当てられます。マスタースレッドは、親スレッドの場所で実行され、その場所を含むサブパーティションに割り当てられます。次にもっとも小さいスレッド番号を持つスレッドが次のサブパーティション内の最初の場所に割り当てられ (以下同様に続く)、マスタースレッドの元の場所パーティションからラップアラウンドします。
T > P。親スレッドの場所パーティションは P 個のサブパーティションに分けられ、それぞれが 1 つの場所から成ります。各サブパーティションには連続するスレッド番号を持つ Sp のスレッドが割り当てられます。ここでは、floor(T/P) <= Sp <= ceiling(T/P) です。最初の S0 スレッド (マスタースレッドを含む) は親スレッドの場所を含むサブパーティションに割り当てられます。次の S1 スレッドは次のサブパーティションに割り当てられ (以下同様に続く)、マスタースレッドの元の場所パーティションからラップアラウンドします。T が P によって均等に分けられない場合、特定のサブパーティションに含まれるスレッドの正確な数は実装によって定義されます。