CPUのAFFINITY的なものでちょっと悩んだ

この記事は外部の日記(ひびろぐ)からマルチポストしています。見た目がおかしいときは本家を参照してやってください。
本家→http://exth.net/~tgbt/wordpress/2011/07/21/3838/

      • -


ので、メモしておく。


ちょいとWestmereEPなCPUを搭載した計算機をいじる機会が巡ってきた。このCPUさん、6コアでHTを使うと12コア。そしてこの計算機には、そのCPUが2つ搭載されているのです。つまり、物理12コア論理24コアのちょっとでかいワークステーション

さて、ちょっと困ったのが、OpenMPの性能確認をしようと思ったのだが、HTなコアに割り当たらないように保証する方法とか、逆にHTなコアにぶつけちゃうようにする方法がよくわからない。MPIだったらnumactlで色々いじれることを把握していたのだが、OpenMPはどうするのだろうかという問題にぶつかった。

webで調べてみたところ、どうやらGNUOpenMPならGOMP_CPU_AFFINITYで設定できるようだという情報を得た。今回は、本当はIntel Compilerで測定したいのだが、とりあえずGCC(g++/gfortran)で測定しているので渡りに船。ちょっと試してみることにした。


まず/proc/cpuinfoを確認。なんとなく使えそうな値としては、processorとphysical idとcore id。ざっと順番に抽出してみるとこんな感じ。

processor	:	0	physical id	:	0	core id	:	0
processor	:	1	physical id	:	0	core id	:	1
processor	:	2	physical id	:	0	core id	:	2
processor	:	3	physical id	:	0	core id	:	8
processor	:	4	physical id	:	0	core id	:	9
processor	:	5	physical id	:	0	core id	:	10
processor	:	6	physical id	:	1	core id	:	0
processor	:	7	physical id	:	1	core id	:	1
processor	:	8	physical id	:	1	core id	:	2
processor	:	9	physical id	:	1	core id	:	8
processor	:	10	physical id	:	1	core id	:	9
processor	:	11	physical id	:	1	core id	:	10
processor	:	12	physical id	:	0	core id	:	0
processor	:	13	physical id	:	0	core id	:	1
processor	:	14	physical id	:	0	core id	:	2
processor	:	15	physical id	:	0	core id	:	8
processor	:	16	physical id	:	0	core id	:	9
processor	:	17	physical id	:	0	core id	:	10
processor	:	18	physical id	:	1	core id	:	0
processor	:	19	physical id	:	1	core id	:	1
processor	:	20	physical id	:	1	core id	:	2
processor	:	21	physical id	:	1	core id	:	8
processor	:	22	physical id	:	1	core id	:	9
processor	:	23	physical id	:	1	core id	:	10

processorは通し番号で決定として、physical idは0と1だからソケット番号と見て間違いないだろう。core idはなんで番号が飛んでいるんだろうってのは置いとくとして、6種類の値があるから物理コア番号だろう。番号が飛んでいる理由はおそらくIDをビットで表現しているから、かな?(0:0000, 1:0001, 2: 0010, 8:1000, 9:1001, 10:1010、なんとなくそれっぽいよね。)


というわけで、まずphysical idでソケットがわかれていて、core idで物理コアもわかれている。あとはphysical idもcore idも同じ2つずつのprocessorが同一論理コア上の2コアということで確定でしょう。


確定的な予想はついたところで、実際に測定してみることにする。
試しにシンプルな三重ループの行列積を作成して、最外ループをOpenMP並列化してみることにした。
並列度を1,2,4,6,8,10,12,14,16,18,20,22,24と設定してみたところ、こんな感じになった:

12並列まで性能が向上した後はむしろ性能が落ちている感じ。余っている計算資源を有効活用するHTのコンセプトからして今回みたいなひたすら同じ演算器ばかり使う計算では性能は上がらないわけで。どうやら、ちゃんと並列度が物理コア数に到達するまでは順番に適当なコアを使ってくれているようだ。(きっと/proc/cpuinfoのprocessorを頭から使っているんだろうけど、そこまでは確実性がない。)


それでは、ということで、GOMP_CPU_AFFINITYを適当にいじりつつ並列度12で実行してみた。
順番に、

export GOMP_CPU_AFFINITY="0-11"
export GOMP_CPU_AFFINITY="6-17"
export GOMP_CPU_AFFINITY="12-23"
export GOMP_CPU_AFFINITY="0-5 12-17"
export GOMP_CPU_AFFINITY="6-11 18-23"
export GOMP_CPU_AFFINITY="0-2 6-8 15-17 21-23"
export GOMP_CPU_AFFINITY="0-2 9-11 15-17 18-20"

と設定してみた。結果はこの通り:

まずABCはphysical idが違う6つずつ、各6つはcore idが違うものを選択。思った通りに前の実験の最速性能と同じくらいになった。
次にDEは意図的に同じphysical idのものばかり使ってみた。結果として前の実験の6コアと同じ性能のようなので、各物理コアに2スレッドずつ割り当たったように見える。
最後にFGは、physical id毎に6つずつ、physical id内ではcore idが重複しない範囲で適当に選んだ。最速性能と同じだった。


まぁこの実験結果で確実に網羅できたわけではないのだが、大体わかったと言って良さそうだ。前の方から使えば変にHTのお世話になることはないだろう。
あと気になるのはこのIDの並び方はどのレベルで決まっているのかと言うこと。再起動しても一緒なのか?とか、OS入れ直したら変わっちゃうのかな?とか、そういうところが気にはなるのだが、まぁまたやってみればわかるよね。



さて、確認ができた気がするところで、時間が時間だしもう寝ようかね。