Windows: Prozessaffinität setzen

Veröffentlicht am Published on 发表于 1. Februar 2026 um at , 6:36

In früherer Zeit war diese Funktion vermutlich eher selten von Nutzen, aber da sich der physikalische Grundaufbau von x86-Prozessoren in den letzten Jahren stark geändert hat kann man heute froh sein das es diese API-Funktion gibt. Die Rede ist von der sogenannten Prozessaffinität: Damit kann man bestimmen auf welchem logischen Prozessor ein Task ausgeführt werden soll.

Wofür man das gebrauchen könnte wird schnell klar sobald man darüber nachdenkt, wie heutige CPUs funktionieren (auch ARM). Vor allem bei Intel gibt es mittlerweile „Performance“- und „Effizienzkerne“. Bei AMD gibt es Modelle wie beispielsweise den Ryzen 9 5900X bzw. 5950X*, in denen zwei Chiplets zu je 6 bzw. 8 Kernen verbaut sind und nur das erste Chiplet die beworbenen Taktraten schafft, da eines mit besserer Siliziumqualität verbaut wurde.

Prozesse auf logische Kerne bzw. Threads zu verteilen macht normalerweise der Scheduler im Betriebssystem von selbst, also leistungshungrige Prozesse auf bekanntermaßen leistungsstarke Kerne schieben. Wenn man sich darauf aber nicht verlassen will ist es möglich das zu erzwingen.

Kompatibilität

Die zugrunde liegenden Windowsfunktionen auf Basis der „winbase.h“ existieren seit Windows XP bzw. Windows Server 2003. Die Library ist Kernel32.lib mit der dazugehörigen Kernel32.dll. Man kann die Prozessaffinität also bei allen Betriebssystemen seit inklusive Windows XP setzen.

Funktionsweise

Wichtig zu wissen ist das die Mehrheit aller x86-Prozessoren „Simultaneous Multithreading“ bzw. „Hyperthreading“ beherrschen und somit mehr als einen Thread pro physikalischen Prozessorkern ausführen können. Daher die Formulierung „logischer Prozessor“, damit ist jeder Thread und nicht jeder Kern gemeint.

Um beim Beispiel des AMD Ryzen 9 5950X zu bleiben: Diese CPU hat 16 physikalische Kerne, die mit aktivem SMT 32 Threads bieten. Die Prozessaffinitätsmaske / das System sieht also wieviele CPUs?
Richtig, 32.

Das ist wichtig im Hinterkopf zu behalten. Die interne Verteilung folgt der Initialisierungslogik des Systems, also im Beispiel eines 4 Kern / 8 Thread Prozessors mit aktivem SMT:

Physikalischer KernPhysikalischer Thread 1Physikalischer Thread 2Logischer Prozessor, physikalischLogischer Prozessor, SMT
001CPU0CPU1
123CPU2CPU3
245CPU4CPU5
367CPU6CPU7

Mit deaktiviertem SMT würde es dann so aussehen:

Physikalischer KernPhysikalischer Thread 1Physikalischer Thread 2Logischer Prozessor, physikalischLogischer Prozessor, SMT
00CPU0
11CPU1
22CPU2
33CPU3

Manuelle Aktivierung

Ganz simpel: Der Prozess muss laufen – Dann startet man den Taskmanager, wechselt in die Detailansicht und rechtsklickt auf den Prozess. Ein Klick auf „Zugehörigkeit festlegen“ öffnen ein Dialogfeld in dem man exakt anhaken kann auf welchen logischen Prozessoren der Prozess laufen soll und welchen nicht:

Im „Process Explorer“ von SysInternals funktioniert das ebenso über das Kontextmenü des Prozesses.

Permanente Anwendung an einem Prozess

Da wird es jetzt etwas komplexer: Die Funktion arbeitet mit Bitmasken. Um also festzulegen auf welchen genauen logischen Prozessoren ein Task laufen soll muss gerechnet werden:

Logischer ProzessorDezimal2 x Dezimal -1Hexadezimal
CPU0111
CPU1232
CPU2474
CPU38158

Um die Bitmaske herauszufinden ist es am einfachsten den Rechner in Windows zu starten und auf den Modus „Programmierer“ umzustellen:

Anschließend rechnet man einfach nur die Dezimalzahlen der gewünschten logischen Prozessoren zusammen und schaut was der Wert in Hexadezimal umgerechnet ergibt. Das ist dann die nötige Bitmaske. Wenn man beispielsweise spezifisch möchte das der Prozess entweder auf Kern 0 oder Kern 3 läuft, geht das auch:
1 + 8 ergibt 9, auch hexadezimal ist das 9 und somit ist „9“ die Bitmaske.

Bei CPUs mit vielen Kernen und / oder Threads werden die Zahlen sehr schnell riesig. Das Limit, bevor NUMA-Beschränkungen auftreten und den Prozess komplexer machen liegt bei 64 logischen Prozessoren.

Tabelle bis zu 32 logische Prozessoren

Hier der Einfachheit halber eine Übersichtstabelle:

Physikalischer ProzessorLogischer ProzessorDezimal2 x Dezimal -1
Kern 0 Thread 1CPU0(20) = 11
Kern 0 Thread 2CPU1(21) = 23
Kern 1 Thread 1CPU2(22) = 47
Kern 1 Thread 2CPU3(23) = 815
Kern 2 Thread 1CPU4(24) = 1631
Kern 2 Thread 2CPU5(25) = 3263
Kern 3 Thread 1CPU6(26) = 64127
Kern 3 Thread 2CPU7(27) = 128255
Kern 4 Thread 1CPU8(28) = 256511
Kern 4 Thread 2CPU9(29) = 5121023
Kern 5 Thread 1CPU10(210) = 10242047
Kern 5 Thread 2CPU11(211) = 20484095
Kern 6 Thread 1CPU12(212) = 40968191
Kern 6 Thread 2CPU13(213) = 819216383
Kern 7 Thread 1CPU14(214) = 1638432767
Kern 7 Thread 2CPU15(215) = 3276865535
Kern 8 Thread 1CPU16(216) = 65536131071
Kern 8 Thread 2CPU17(217) = 131072262143
Kern 9 Thread 1CPU18(218) = 262144524287
Kern 9 Thread 2CPU19(219) = 5242881048575
Kern 10 Thread 1CPU20(220) = 10485762097151
Kern 10 Thread 2CPU21(221) = 20971524194303
Kern 11 Thread 1CPU22(222) = 41943048388607
Kern 11 Thread 2CPU23(223) = 838860816777215
Kern 12 Thread 1CPU24(224) = 1677721633554431
Kern 12 Thread 2CPU25(225) = 3355443267108863
Kern 13 Thread 1CPU26(226) = 67108864134217727
Kern 13 Thread 2CPU27(227) = 134217728268435455
Kern 14 Thread 1CPU28(228) = 268435456536870911
Kern 14 Thread 2CPU29(229) = 5368709121073741823
Kern 15 Thread 1CPU30(230) = 10737418242147483647
Kern 15 Thread 2CPU31(231) = 21474836484294967295

Wenn ich zum Beispiel bei einem AMD Ryzen 9 5950X möchte, das der designierte Prozess nur auf den potenziell schnelleren ersten 8 Kernen bzw. 16 Threads läuft wäre die Bitmaske rechnerisch „FFFF“ .

Scripting

Man kann den Vorgang mit Batch oder PowerShell automatisieren. Ein einfaches Beispiel in Batch:

@echo off
cd "C:\Users\Admin\Desktop\MeineSoftware"
START /min /affinity FFFF cmd /C "MeinProzess.exe -MeinParameter1 -MeinParameter2"

Zusätzlich kann man auch noch gleich die Prozesspriorität setzen:

@echo off
cd "C:\Users\Admin\Desktop\MeineSoftware"
START /high /min /affinity FFFF cmd /C "MeinProzess.exe -MeinParameter1 -MeinParameter2"

Mögliche Werte sind:

/low
/normal
/high
/realtime
/abovenormal
/belownormal

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert