概要
OpenMP プログラムをマルチコアプロセッサで実行する場合に、どのスレッドをどの物理コアに割り当てるかを手動で制御する方法についてのメモ。
昨今の SMT なプロセッサであれば、物理コア 1 つに対して複数の論理コアを備えているように見えるため、意識しないと、マルチコアプロセッサで別の物理コアがあるにもかかわらず、複数のスレッドが同じ物理コアに割り当てらてしまうことがあるようです。割り当て方法については掘り下げませんが、別の物理コアが余ってるならそちらに振り分けたい!ということで。
(追記)OMP_PLACES の挙動が Intel OpenMP Runtime Library と GOMP で違うっぽいので別々に分けました。。。
OMP_PLACES を使った方法
環境変数 OMP_PLACES でスレッドIDと物理コアの関連付けを指定できます。物理コア内は中括弧で記述します。例えば、
export OMP_PLACES="{0,1},{2,3}"
であれば、CPU0 にスレッド0とスレッド1が、CPU1にスレッド2とスレッド3が割り当てられます。
export OMP_PLACES="{0,2},{1,3}"
であれば、CPU0 にスレッド0とスレッド2が、CPU1にスレッド1とスレッド3が割り当てられます。2スレッドでプログラムを動かす場合、後者の方が性能がよい場合が多いです。
実行時に指定してももちろんOK
OMP_PLACES="{0,2},{1,3}" <exec_prog>
GOMP_CPU_AFFINITY を使った方法 (GOMP)
GCC の OpenMP 実装 (GOMP) は OMP_PLACES が上記のように動いていない気がするので、GOMP_CPU_AFFINITY を使うほうがよさげです。CPU0 にスレッド0とスレッド2を、CPU1にスレッド1とスレッド3を割り当てる場合は以下のとおり。
GOMP_CPU_AFFINITY="0,2 1,3" <exec_prog>
参考資料
OMP_PLACES 自体は OpenMP の仕様(OpenMP 4.0 Complite specification p.241)に書いてあったりします。指定の記法は他にもいろいろあるみたい。実際の振る舞いは実装依存のようなので、ランタイムによっては未実装だったり、うまくいかない場合もあるかもしれません。私は Intel OpenMP Runtime Library で動作を確認しています。