記事の概要
IBM Power10プロセッサ搭載サーバーで、GCCのOpenMPスレッド並列なジョブを実行する際の環境変数GOMP_CPU_AFFINITYの設定方法について。
想定環境
例としてPower10の物理プロセッサ16コア搭載するサーバーで、SMT=8の環境を想定する。OSはLinuxを想定。
ppc64_cpu --info というコマンドでは以下のように見えている。
$ ppc64_cpu --info
Core 0: 0* 1* 2* 3* 4* 5* 6* 7*
Core 1: 8* 9* 10* 11* 12* 13* 14* 15*
Core 2: 16* 17* 18* 19* 20* 21* 22* 23*
Core 3: 24* 25* 26* 27* 28* 29* 30* 31*
Core 4: 32* 33* 34* 35* 36* 37* 38* 39*
Core 5: 40* 41* 42* 43* 44* 45* 46* 47*
Core 6: 48* 49* 50* 51* 52* 53* 54* 55*
Core 7: 56* 57* 58* 59* 60* 61* 62* 63*
Core 8: 64* 65* 66* 67* 68* 69* 70* 71*
Core 9: 72* 73* 74* 75* 76* 77* 78* 79*
Core 10: 80* 81* 82* 83* 84* 85* 86* 87*
Core 11: 88* 89* 90* 91* 92* 93* 94* 95*
Core 12: 96* 97* 98* 99* 100* 101* 102* 103*
Core 13: 104* 105* 106* 107* 108* 109* 110* 111*
Core 14: 112* 113* 114* 115* 116* 117* 118* 119*
Core 15: 120* 121* 122* 123* 124* 125* 126* 127*
16スレッド並列実行
例えば16スレッド並列で実行する場合、以下のように指定すると(一般に)パフォーマンスが出やすい。
$ export OMP_NUM_THREADS=16
$ export GOMP_CPU_AFFINITY="0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120"
32スレッド並列実行
例えば32スレッド並列で実行する場合、以下のように指定すると(一般に)パフォーマンスが出やすい。(GOMP_CPU_AFFINITY="0,4,8,12,16,・・・" ではない点に注意。)
$ export OMP_NUM_THREADS=32
$ export GOMP_CPU_AFFINITY="0,1,8,9,16,17,24,25,32,33,40,41,48,49,56,57,64,65,72,73,80,81,88,89,96,97,104,105,112,113,120,121"
あるいは、以下のように指定することもできる。
$ export OMP_NUM_THREADS=32
$ export MAXT=127
$ export GOMP_CPU_AFFINITY="0-$MAXT:8,1-$MAXT:8,2-$MAXT:8,3-$MAXT:8,4-$MAXT:8,5-$MAXT:8,6-$MAXT:8,7-$MAXT:8"
上記の場合、GOMP_CPU_AFFINITYの内容は展開されて、
"0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,1,9,17,25,33,41,49,57,65,73,81,89,97,105,113,121,2,10,18,26,34,42,50,58,66,74,82,90,98,106,114,122,3,11,19,27,35,43,51,59,67,75,83,91,99,107,115,123,4,12,20,28,36,44,52,60,68,76,84,92,100,108,116,124,5,13,21,29,37,45,53,61,69,77,85,93,101,109,117,125,6,14,22,30,38,46,54,62,70,78,86,94,102,110,118,126,7,15,23,31,39,47,55,63,71,79,87,95,103,111,119,127"
と同値になる。
前述の32スレッド並列と比べると、割り当ての順番は変わるが、使用する論理プロセッサは同じ。(OMP_NUM_THREADSを64,128などと変化させてベンチマークする場合等はこちらが便利。GOMP_CPU_AFFINITYを書き換える必要がないので。)
ちなみに、seqコマンドやrsコマンドが使える場合、以下のコマンドで同様の文字列(カンマ区切りの数列)を生成することも可能。
$ seq 0 127 | rs 0 8 | rs -T | rs 1 0 | sed "s/ */,/g"
0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,1,9,17,25,33,41,49,57,65,73,81,89,97,105,113,121,2,10,18,26,34,42,50,58,66,74,82,90,98,106,114,122,3,11,19,27,35,43,51,59,67,75,83,91,99,107,115,123,4,12,20,28,36,44,52,60,68,76,84,92,100,108,116,124,5,13,21,29,37,45,53,61,69,77,85,93,101,109,117,125,6,14,22,30,38,46,54,62,70,78,86,94,102,110,118,126,7,15,23,31,39,47,55,63,71,79,87,95,103,111,119,127