Aufgabensatz funktioniert nicht über eine Reihe von Kernen im Isolationsmodus

12

Zum Vorwort verwende ich Debian Wheezy mit Kernel 3.2 auf einem AMD64-Chipsatz. Meine Maschine hat zwei Xeon E5-2690-Kerne. Ich habe die Boot-Parameter so eingestellt, dass alle Kerne auf einer CPU einem einzigen Prozess zugeordnet sind. Dazu habe ich in grub isolcpus = 8,9,10,11,12,13,14,15 gesetzt.

So weit, ist es gut. Nehmen wir nun an, ich möchte die isolierten CPUs für einen bestimmten Befehl verwenden. Um einfach zu sein, verwende ich nur eine einfache Endlosschleife:

$ taskset -c 8-15 bash -c 'während true; hallo wiederholen> / dev / null; erledigt' &

So weit so gut, zeigt top, dass Core 8 sich bis zu nahezu 100% auslastet. Nehmen wir nun an, ich starte den Befehl erneut:

$ taskset -c 8-15 bash -c 'während true; hallo wiederholen> / dev / null; erledigt' &

Das obere Bild zeigt, dass die Kerne 9-15 inaktiv bleiben und die beiden Prozesse den Kern 8 gemeinsam nutzen. Wenn ich dies stattdessen tue:

$ taskset -c 8 Bash -c 'während true; hallo wiederholen> / dev / null; erledigt' &

$ taskset -c 9 bash -c 'while true; hallo wiederholen> / dev / null; erledigt' &

Die Kerne 8 und 9 werden jeweils zu 100% ausgelastet. Dies gilt nur für Isolcpus, da derselbe Tasksatz mit den Kernen 1-7 die Prozesse ordnungsgemäß auf die relevanten Kerne verteilt. Außerdem zeigt "taskset -p", dass die Affinitätsmaske für die 8-15-Prozesse korrekt eingestellt ist. Es sieht so aus, als ob der Kernel-Scheduler es ablehnt, irgendetwas anderes als den niedrigsten Kern zu verwenden, der auf einer Isolcpus-Affinitätsmaske angegeben ist.

Normalerweise würde das mit meinen obigen Beispielen keine große Rolle spielen, spezifizieren Sie einfach einzelne Kerne für jeden Prozess. Ich möchte jedoch eine Anwendung mit mehreren Threads auf der dedizierten CPU ausführen. Ich möchte den Kernsatz angeben und den Thread-Pool automatisch verwenden lassen, ohne die Prozessoraffinität für jeden einzelnen Thread, der erzeugt wird, einzeln zurücksetzen zu müssen.

Hat jemand eine Idee, wie man den Scheduler dazu bringt, mir mehr als einen Core aus dem Isolcpu-Set zu geben?

user79126
quelle
Können Sie versuchen, ein Multithread-Programm zu verwenden? Bash ist kein Multithread
c4f4t0r
1
Ja, das hat mich ursprünglich auffallen lassen (mein Multithread-Programm verwendete nicht mehr als einen Kern). Ein einfaches Python-Skript, das viele Threads erstellt, verwendet nicht mehr als einen Kern, wenn es auf der isolcpus-Gruppe ausgeführt wird. (Beim Betrieb mit nicht isolierten Kernen werden alle verfügbaren 8 Kerne verwendet.)
User79126
Lesen Sie diese linuxtopia.org/online_books/linux_kernel/kernel_configuration/… , um einen CPU vom Kernel-Scheduler auszuschließen. Möchten Sie jedoch nach dem Ausschließen von CPU einen Prozess auf dem ausgeschlossenen CPU ausführen?
c4f4t0r
1
Der Kernel plant keinen Thread oder Prozess auf der Isolations-CPU, es sei denn, die Prozessor-Affinitätsmaske gibt an, dass er verwendet werden sollte. Andernfalls ist isolcpus dasselbe wie das Ausschalten des Kerns, wenn der Zweck darin besteht, einen Kern aus einem benutzerdefinierten Grund zu reservieren und sicherzustellen, dass kein unerwünschter Prozess ihn verwendet. Taskset legt die Affinitätsmaske so fest, dass alle Kerne im Bereich von 8 bis 15 verwendet werden (der beim Einchecken von / proc korrekt eingestellt ist), sodass der Kernel den Prozess für die inaktiven Kerne planen sollte.
user79126

Antworten:

9

Nach einem Tag voller Frustration habe ich eine Lösung gefunden. Dieses Verhalten scheint ein Artefakt des Standard-Kernel-Scheduler-Algorithmus zu sein (SCHED_OTHER für diese Distribution / diesen Kernel). Durch die Umstellung des Prozesses auf einen anderen Algorithmus wird das Problem beseitigt. Isolationspuffer werden über die Prozesse / Threads hinweg in angemessener Weise verwendet.

Am Ende habe ich SCHED_RR verwendet, aber ich habe auch SCHED_FIFO und SCHED_IDLE getestet. Beide scheinen zu funktionieren. Der Prozess kann mit dem alternativen Algorithmus mithilfe des Dienstprogramms chrt gestartet werden:

$ sudo chrt -r 1 [Befehl]

(Wenn Sie als Nicht-Root-Benutzer ausgeführt werden möchten, können Sie das Dienstprogramm setcap verwenden, um CAP_SYS_NICE für die Binärdatei zu aktivieren, die sich auf den Befehl bezieht.)

user79126
quelle
1
Obwohl die Affinität zu Kernen auf 0,1 eingestellt wurde, verwendete meine Java-Anwendung nur den ersten Kern. 'sudo chrt -r 1 [Befehl]' löste auch mein Problem.
Barry NL