Windowsのスケジューリングの
鍵を握るAffinityマスク
Windowsのスケジューリングアルゴリズムの基本は、優先順位付きキューである。この仕組みをWindowsでは、「ディスパッチャー」と呼ぶ。ディスパッチャーとはタクシーの配車センターなどを指す言葉だが、OSではスレッドの切り替えなどを担当する部分のことを言う。
Windowsでは、スレッドの優先順位は「起動時に指定された順位」をベースにするが、内部的にはこれを上げ下げして調整している。優先順位を変えることで、例えば、“高い優先順位のスレッドが空くのを待っているリソース”を持った、低い優先順位のスレッドなどを優先して実行させることで、待っている高い優先順位のスレッドが早く実行できるようにするといった制御をしている。
マルチプロセッサーシステムの場合、各プロセッサーごとにキューがある。ただしスレッドは必ずしも、入れられたキューを持つプロセッサーでしか実行されないわけではない。マルチプロセッサーシステムの場合、Windowsのディスパッチャーは以下のような手順で、実行するプロセッサーを決定する。
Windowsでは、各プロセッサーごとに「アイドルスレッド」が用意されており、スレッドが割り当てられていないプロセッサーは、このアイドルスレッドを実行している。そこで、現在アイドル中のプロセッサーがひとつだけならば、それがスレッドを実行する。
もし複数のプロセッサーがアイドル状態なら、スレッドの設定により実行する“最適”なプロセッサーを探して実行させる。最適なものがなければ、前回そのスレッドを実行したプロセッサーを探す。プロセッサーがそのどれでもない場合には、ディスパッチャーを実行しているプロセッサーがそのスレッドを実行する。ここで言う“最適”なプロセッサーとは、設定により強制的に指定されたプロセッサーである。また設定がない場合には、最初にそのスレッドを実行したプロセッサーか、複数のスレッドを実行していない物理プロセッサーが割り当てられる。
各スレッドは「Affinityマスク」と呼ばれる情報を持つ。これは64bitのデータで、1bitが論理プロセッサーに対応しており、各スレッドがどの論理プロセッサーで実行可能なのかを示すものだ。ここになにも設定しないと、スレッドはどの論理プロセッサーでも実行が可能となる。しかし、ユーザーやアプリケーション自身がAPIを経由してAffinityマスクをセットすることで、Windowsはスレッドが動作できる論理プロセッサーを、このマスクにしたがって選択するようになる。またスレッドは、自身を最初に起動したプロセッサーを記憶しており、他の条件がなければ、なるべく同じプロセッサーを使う(暗黙的なAffinityと言える)。
ただし、64個以上の論理プロセッサーがある場合には、NUMAの構成ごとにグループを作る。スレッドの割り当てはグループ内でのみ行なうようにして、スレッドを実行可能なプロセッサーを64個以下に制限する。このNUMAグループは、メモリーアクセスのコストが小さくなる単位である。グループを越えてのメモリーアクセスは、遅延が大きくなる。そのため割り当てる論理プロセッサーを制限することで、遠方のメモリーにあるスレッドを実行するような、効率の悪いスレッド割り当てを回避している。
この連載の記事
-
第13回
PC
ARM版Windows 8実現の布石となったWindows 7の「MinWin」 -
第12回
PC
アプリがWindowsの機能を使うには? APIとDLLの仕組み -
第11回
PC
マルチコアCPUの消費電力はスケジューリングで変わる? -
第9回
PC
マルチコアCPUを賢く使いこなす スケジューリングの秘密 -
第8回
PC
意味の違いがわかる? タスクとプロセスとスレッド -
第7回
PC
Windowsのメモリー管理をx86の仕組みから読み解く -
第6回
PC
メモリー不足を根本的に解決する64bit OSの仕組み -
第5回
PC
Windows 8でMetro Styleアプリを動かす「WinRT」 -
第4回
PC
Windowsを動かすデバイスドライバーの仕組み 前編 -
第3回
PC
OSの仕事はハードウェアをアプリから「隠す」こと? - この連載の一覧へ