Linux Prozess an (physischen) CPU Kern binden / wie?

Fallaxia

Lieutenant
Registriert
Okt. 2012
Beiträge
684
Hi Leute,

vielleicht kann mir jemand hierbei helfen. Situation:
Serversystem mit 128 physischen / 256 virtuellen CPU Kernen, Ubuntu 20.04 LTS

Es läuft pro physischem CPU Kern je ein Prozess, der den Kern auslastet.
Der Scheduler geht her und "switcht" die ganze Zeit die Prozesse hin und her, also zwischen physischen und virtuellen CPU Kernen, im htop sieht man also eine Auslastung von etwa 50% pro Kern, anstatt 100% auf den physischen Kernen und 0% auf den virtuellen Kernen.

Wenn ich mit taskset die Prozesse festpinne hört das natürlich auf, aber das ist ja nur für den Moment. Wie bringe ich dem Scheduler bei die physischen CPU Kerne zu bevorzugen und nicht wild hin und her zu switchen? Oder übersehe ich hier was?
 
Frage: was erhoffst du dir davon?

Du denkst, dass du es besser machst als der scheduler?
 
Sephe schrieb:
Frage: was erhoffst du dir davon?

Du denkst, dass du es besser machst als der scheduler?

Wenn ein Task nur einen Kern nutzt ist es besser. Das hin und her wecheln frist leistung.
Ich weiß zwar nicht wie es mit Linux geht aber unter Windows geht es mit Process Lasso unter Linux gibt es bestimmt ähnliches.
 
Das denke ich nicht nur, da bin ich sogar sicher, weil ich es getestet habe.
Der Scheduler switcht die einzelnen Simulations Prozesse mehrere Male pro Sekunde zu einem anderen Kern rüber.

Wenn ich die Prozesse mit taskset festpinne ist die Performance um etwa 25% besser, also die Simulation ist deutlich eher fertig gestellt als wenn ich den Scheduler einfach "machen lasse".

Also ja, ich erwarte eine deutliche Effizienzsteigerung. Nur möchte ich verständlicher Weise nicht zu der Simulation das manuell eingeben müssen.
Ergänzung ()

aber unter Windows geht es mit Process Lasso
Genau. Unter Windows nutze ich auch Prozess Lasso, was in dem Fall sehr hilfreich ist und sehr gute Ergebnisse bringt. Nur unter Linux frage ich mich wie ich dem Scheduler einfach sagen kann:

#1 Nimm die physischen CPUs
#2 Lass den Prozess so lange auf dem Kern bis er fertig ist und wechsel nicht.
 
wenn der server nur für diese aufgabe da ist, dann deaktivier einfach ht/smt im bios. alternativ kann man die virtuellen cores auch zur laufzeit deaktivieren. um taskset um die prozesse zu pinnen kommst du aber nicht rum, es sei denn die anwendung kann sich selbst pinnen.

Sephe schrieb:
Du denkst, dass du es besser machst als der scheduler?
wichtig ist das u.a. bei dual-cpu systemen. dort sind geräte wie z.b. netzwerkkarten mit pcie direkt an eine cpu angebunden und sind über die andere cpu nur mit extra latenzen verfügbar. pinnt man dann eine anwendung auf die cpu mit direkter anbindung hat man mehr durchsatz.
 
Zuletzt bearbeitet:
Einfach HT deaktivieren hilft nur wenig, da der Scheduler die einzelnen Prozesse bei nicht 100% Auslastung weiter fröhlich hin und her schiebt, auch über CPU Sockel Grenzen hinweg, also von CPU Sockel 1 zu CPU Sockel 2 und so. So bewegt sich ein einzelnen Prozess mehrmals pro Sekunde "woanders" hin, mit all den Nachteilen die damit verbunden sind.

Wie stelle ich das ab?
 
dafür ist doch genau taskset da. wie benutzt du es denn? bereits zum starten des programms oder erst nachdem das programm läuft?
 
Ich benutze taskset hier zum manuellen Festlegen der Zugehörigkeit des laufenden tasks per PID.

Aber das bringt mir manuell ja nicht viel.
Die Hauptanwendung startet sagen wir mal 100 PIDs mit je einer Simulation, ich habe also 100 Prozesse. Die laufen ein paar Minuten, sind dann fertig und dann kommen neue 100 Prozesse/PIDs.

Ich kann da ja nicht manuell hinterher laufen und jede PID einem Kern zuweisen. Das muss doch automatisierbar sein.
 
Fallaxia schrieb:
Das muss doch automatisierbar sein.
Die Hauptanwendung könnte es direkt beim Thread spawn. Per Script von außen eher weniger. Also zumindest nicht, wenn das dauernd neue PIDs sind.
Edit: man könnte ein Script basteln (in welchem ein fixes Array existiert), das Script scannt die Threads regelmäßig und weist dem Array die PIDs zu, nicht gefundene werden entfernt, neue in die Lücken geschrieben und dann je mit dem passenden Taskset bearbeitet. Könnte aber den theoretischen Perf.gewinn auch wieder aufbrauchen^^
 
Zuletzt bearbeitet:
am besten wäre es natürlich, wenn die anwendung das selbst machen würde. ansonsten würde ich mir wohl ein script erstellen, dass regelmässig das pinning für die aktuellen prozesse macht. nicht optimal, aber besser als nichts
 
Ich kann die einzelnen Jobs nicht selbst starten, dass macht die Kontrollanwendung. Ein manuelles starten der einzelnen Threads / Prozesse ist nicht möglich.
 
wern001 schrieb:
Wenn ein Task nur einen Kern nutzt ist es besser. Das hin und her wecheln frist leistung.
Ich weiß zwar nicht wie es mit Linux geht aber unter Windows geht es mit Process Lasso unter Linux gibt es bestimmt ähnliches.
Das hin und her wechseln kostet zwar ecakt die Zeit an Leistung, in der die Daten kopiert werden. Wenn deine CPU aber modern ist, fällt dass nicht ins Gewicht, da wenn du die Kerne wechselst, ein Kern nicht so heiß wird und nicht throtteln muss. Also besser, wenn es wechselt.
 
Piak schrieb:
Wenn deine CPU aber modern ist, fällt dass nicht ins Gewicht
hier geht es um multi-socket systeme. wenn da die prozesse zwischen mehreren cpus hin und her kopiert werden oder prozesse auf verschiedenen cpus untereinander kommunizieren, kostet das ordentlich leistung. selbst innerhalb einer cpu mit verschiedenen ccx ist das schon der fall.
 
0x8100 schrieb:
hier geht es um multi-socket systeme. wenn da die prozesse zwischen mehreren cpus hin und her kopiert werden
Wobei das nicht passieren sollte. Scheduler sind ja auch nicht grade dumm, da steckt schon einiges an Know-How drin. Rotation auf einem Sockel ja, aber nicht über mehrere Sockel (denke ich!). CCX ist da ein gutes Beispiel, das Konzept mussten die Scheduler erst mal "lernen".
 
Zuletzt bearbeitet:
playerthreeone schrieb:
Wobei das nicht passieren sollte.
wenn man das nicht möchte, kann man numactl verwenden. habe mal kurz einen test gemacht: per default wird ein prozess munter zwischen den cpus verschoben, sichtbar hier an dem prozess mit 100% single core last.

 
Also entweder kann die Anwendung das oder du musst eben über Spinning eines schedulers wie slurm oder utilities wie numactl oder MPI gehen.

Das bleibt dir nicht erspart.
 
playerthreeone schrieb:
man könnte ein Script basteln (in welchem ein fixes Array existiert), das Script scannt die Threads regelmäßig und weist dem Array die PIDs zu, nicht gefundene werden entfernt, neue in die Lücken geschrieben und dann je mit dem passenden Taskset bearbeitet. Könnte aber den theoretischen Perf.gewinn auch wieder aufbrauchen^^
Mal gucken. Klar. Wenn man das umständlich via ps macht und so dann ist das natürlich ressourcenfressend.
Allerdings gibts ja noch ne andere Möglichkeit als ps und an Child-PIDs zu kommen. Nämlich übers /proc Dateisystem. Da findest Du zu einem Elternprozess mit PID 1000 die Child-Proccess PIDs unter /proc/1000/task/1000/children (Leerzeichen-separiert).
Da guckt man halt regelmäßig nach ob da neue PIDs auftauchen und pinnt die dann entsprechend. Muss man ja nicht per taskset machen. Geht ja im Prinzip auch mit dem entsprechen API-Aufruf (was dann massiv Zeit spart).
 
Zurück
Oben