はじめに
SetThreadAffinityMaskについて, 私のライブラリの対応が甘かったので書き記します.
ただし, 公式のはっきりしたドキュメントを見つけていないため, 全て推測です.
これが気になる理由は, SIMTの効率を考えると, 物理プロセッサ単位で拘束したいためです. OSは賢いので気にしなくても良きに計らってくれるようにも思いますが.
Microsoft Reference の記述には次のようにあります,
A thread affinity mask is a bit vector in which each bit represents a logical processor that a thread is allowed to run on.
では, 物理プロセッサと論理プロセッサ, そしてそのマスクの関係はどうなっているのか?ということが気になります.
物理プロセッサ, 論理プロセッサ, そしてマスクの関係
GetLogicalProcessorInformationEx(RelationProcessorCore
で取得できる PROCESSOR_RELATIONSHIP
構造体が答えだと思われます (オレは詳しいんだニキ教えて).
寄り道して, プロセッサグループについて.
Win32 APIの範囲では, 1プロセッサグループあたり, 64論理プロセッサです. Windows ServerもEPYCも所有していないため詳しいことは実験できません. 64論理プロセッサを超えた場合, 別のプロセッサグループに割り当てられるということでしょう. ついでに, 1プロセスは1プロセッサグループを超えてスケジューリングされません.
1プロセッサグループ内の関係は次のようになるのかな?
- 物理プロセッサ数:
PROCESSOR_RELATIONSHIP.GroupCount
- 論理プロセッサ数: SIMTが有効なら物理プロセッサ数×2
- SIMTが有効なとき
PROCESSOR_RELATIONSHIP.Flags
にLTP_PC_SMT
が立つ - 現在2スレッドより多い数のSIMTはないし, 今後半世紀ぐらいは現れない
- 物理プロセッサ単位でSIMTをON・OFFする可能性は考慮されていない
- SIMTが有効なとき
- マスク
-
PROCESSOR_RELATIONSHIP.GroupMask[x].Mask
を見ると, SIMTが有効な場合, 2ビットずつになっていることがわかります. つまり同物理プロセッサ内の論理プロセッサは,Affinity Mask
が隣り合っているはずよね?ということです.
-
まとめ
SIMTが有効な環境で, 物理プロセッサ単位でスレッドを拘束したい場合, SetThreadAffinityMaskは2bits設定してくださいということです.