プロセッサ親和性

プロセッサ親和性、プロセッサアフィニティ (英Processor affinity) とは、中央制御のキューを用いたタスクスケジューリングのアルゴリズムの派生形で、タスクが特定のプロセッサと関連付けられるよう制御を行う。キュー内の各タスク（プロセスないしスレッド）が、推奨の（あるいは指定の）プロセッサを示すタグを持ち、各タスクはタグで指定されたプロセッサを割り当てられる。
プロセスは、実行されるとプロセッサ内に状態として残る（特に、キャッシュメモリ) 。プロセスがあるプロセッサで実行された後、同じプロセスが次回動作する際、プロセッサ親和性を用いて前回と同じプロセッサで動作させるようにすると、他のプロセッサで実行するより効率的に動作できるようになる。
プロセッサ親和性を用いたスケジューリングアルゴリズムの実装は、プロセッサとの親和性をどの程度強く持つかによって異なる。実装によって、別のプロセッサでタスクを実行したほうがよければ動作させるプロセッサを換える場合もありえる。わかりやすい例として、プロセッサによる演算中心の二つのタスク(A, B)が一つのプロセッサに親和性を持ってしまうと、他のプロセッサは利用されなくなってしまう。そこで多くの実装では、タスク B を二つ目のプロセッサに移動させ、プロセッサの使用率を最大に引き上げようとする。タスク A は元のプロセッサとの親和性を持ち続けるが、 B は二つ目のプロセッサとの親和性を持つようになる。
プロセッサ親和性を用いると、キャッシュの問題をうまく軽減させることができるが、 ロードバランスの問題を抑制することはできない 。
プロセッサ親和性は、非対称的なアーキテクチャではより複雑なものとなる。例として、 ハイパースレッディング・テクノロジーに対応したデュアルコアプロセッサを２つ搭載したシステムの場合、 CPU のスケジューリングは非常に難しくなる。同一コア上に実装されたハイパースレッディングによる二つの仮想 CPU 間には完全な親和性があり、同じチップ上の二つのコア（コア同士がキャッシュなどの何らかの資源を共有している）同士には若干の親和性、物理的なチップが異なる場合には親和性はない。
キャッシュ以外のリソースも共有されるため、プロセスを特定の CPU に割り当てる基本的な方法として、プロセッサ親和性だけを用いることはできない。たとえばあるプロセスがハイパースレッディングによる仮想的 CPU で動作し、現在はその仮想 CPU がビジーでもう一方がアイドルであるような場合、キャッシュの親和性を考慮すればプロセスはアイドルのプロセッサに割り当てられるべきである。しかし、二つの仮想 CPU はほとんどの演算処理や、キャッシュ、メモリ資源を利用する動作で互いに競合を引き起こすため、一般的には別のコアか CPU が利用できればプロセスをそちらに割り当てる方が効率的である。その場合、プロセスにはキャッシュにデータを入れなおすというペナルティが生じるが、プロセスが CPU 内の機能ユニット資源を巡って競合する必要がないため、おそらく総合的な性能は高い。
Linuxでは、プロセスの CPU 親和性を taskset(1) プログラムで変更することができる。
SGIのシステムでは、 dplace によってプロセスを複数の CPU に結びつける。
NetBSD 5.0 以上のバージョンでは、 pthread_setaffinity_np/pthread_getaffinity_np が利用可能である。また、psrset ユーティリティ によって、一群の CPU に対するスレッドの親和性を設定することができる。
Windows NTでは、スレッドとプロセスの CPU 親和性は、SetThreadAffinityMaskおよび SetProcessAffinityMask API を用いて別個に設定できる。プロセスの親和性はタスクマネージャーからも設定できる。