Das Festlegen der Affinität zum laufenden Prozess zum Task-Set schlägt fehl

9

Ich versuche, einen Prozess auf eine bestimmte Anzahl von CPU-Kernen zu beschränken. Gemäß der Taskset-Manpage und dieser Dokumentation sollte Folgendes funktionieren:

[fedora@dfarrell-opendaylight-cbench-devel ~]$ taskset -pc 0 <PID>
pid 24395's current affinity list: 0-3
pid 24395's new affinity list: 0

Einfach gesagt - das funktioniert nicht. Wenn Sie den Prozess unter Last setzen und beobachten top, liegt die CPU-Auslastung bei etwa 350% (wie ohne Task-Set). Es sollte maximal 100% betragen.

Ich kann die Affinität über die taskset -c 0 <cmd to start process>Prozess-Spawn-Zeit richtig einstellen . Verwenden funktioniertcpulimit -p <PID> -l 99 auch irgendwie . In beiden Fällen führt eine maximale Belastung des Prozesses zu einer maximalen CPU-Auslastung von 100%.

Was läuft hier falsch?

dfarrell07
quelle
Sollte ich dies auf StackExchange # Unix & Linux gepostet haben? Wenn ja, kann jemand es bewegen oder mir sagen, wie ich es bewegen soll?
dfarrell07
Gemäß dieser Frage muss ein Mod es verschieben. Ich werde die Frage für Mod Aufmerksamkeit markieren. Mod - Bitte verschieben Sie diese Frage auf die Unix- und Linux-Stack-Exchange-Site. Entschuldigung für die Verwirrung!
dfarrell07
3
Wie dfarrell07 hervorhob, wirkt sich das Task-Set standardmäßig nicht auf alle Threads (LWPs) eines Prozesses aus. Verwenden Sie die Option "-a" für das Task-Set, um alle Threads im Prozess zu beeinflussen.
Ich habe mit einem Java-Programm nachgefragt und ja, die Option -a wird benötigt (dann funktioniert sie zuverlässig). Ein weiterer Hinweis: Es spielt keine Rolle, wie viele neue Java-Threads in Java erstellt werden, nachdem Sie das Task-Set ausgeführt haben. Das CPU-Limit wird weiterhin angewendet. Anscheinend bedeutet das Wort "Thread" hier etwas anderes als einen Java-Thread.
Stefan Reich

Antworten:

5

Ich habe ein Python-Skript geschrieben, das einfach einige Threads hochfährt und CPU-Zyklen brennt. Die Idee ist, das Task-Set dagegen zu testen, da es ganz einfach ist.

#!/usr/bin/env python

import threading

def cycle_burner():
    while True:
        meh = 84908230489 % 323422

for i in range(3):
    thread = threading.Thread(target=cycle_burner)
    print "Starting a thread"
    thread.start()

Das Ausführen des Python-Skripts verbraucht etwa 150% der CPU-Auslastung.

[~/cbench]$ ./burn_cycles.py
Starting a thread
Starting a thread
Starting a thread

Das Starten meines Python-Skripts mit dem Task-Set funktioniert wie erwartet. Oben sehen Sie den Python-Prozess, der zu 100% ausgelastet ist.

[~/cbench]$ taskset -c 0 ./burn_cycles.py
Starting a thread
Starting a thread
Starting a thread

Interessanterweise begrenzt das Starten des Python-Skripts und das sofortige Verwenden des Task-Sets zum Festlegen der Affinität des gerade gestarteten Prozesses den Prozess auf 100%. Beachten Sie aus der Ausgabe, dass der Linux-Scheduler die Ausführung der Bash-Befehle beendet hat, bevor die Python-Threads erzeugt werden. Also wurde der Python-Prozess gestartet, dann wurde er so eingestellt, dass er auf CPU 0 ausgeführt wird, und dann wurden seine Threads erzeugt, die die richtige Affinität erbten.

[~/cbench]$ ./burn_cycles.py &; taskset -pc 0 `pgrep python`
[1] 8561
pid 8561's current affinity list: 0-3
pid 8561's new affinity list: 0
Starting a thread
[~/cbench]$ Starting a thread
Starting a thread

Dieses Ergebnis steht im Gegensatz zu dieser Methode, die genau dieselbe ist, aber es den Python-Threads ermöglicht, zu erscheinen, bevor die Affinität des Python-Prozesses festgelegt wird. Dies repliziert die oben beschriebenen Ergebnisse "Taskset macht nichts".

[~/cbench]$ ./burn_cycles.py &
[1] 8996
[~/cbench]$ Starting a thread
Starting a thread
Starting a thread
[~/cbench]$ taskset -pc 0 `pgrep python`
pid 8996's current affinity list: 0-3
pid 8996's new affinity list: 0

Was läuft hier falsch?

Anscheinend erben Threads, die erzeugt wurden, bevor die Affinität des übergeordneten Prozesses geändert wurde, nicht die Affinität des übergeordneten Prozesses. Wenn jemand einen Link zur Dokumentation bearbeiten könnte, der dies erklärt, wäre dies hilfreich.

dfarrell07
quelle
Bitte aktualisieren Sie Ihre Antwort, um den -ain den Kommentaren der Frage vorgeschlagenen Parameter aufzunehmen . Ich habe es versucht und es hat bei mir funktioniert.
Nagabhushan SN
4

Ich denke, Sie müssen das Task-Set einmal pro Thread aufrufen, dh ps -eLanstelle von verwenden pgrepund das an weiterleitentaskset -cp 0

ps -eLo cmd,tid | grep python | perl -pe 's/.* (\d+)$/\1/' | xargs -n 1 taskset -cp 0

Dies ruft den Task-Set für alle Thread-IDs auf.

JN
quelle
4

Versuchen Sie stattdessen numactl mit --physcpubind(oder -C). Die Manpage sagt:

... Die Richtlinie ist auf Befehl festgelegt und wird von allen untergeordneten Elementen geerbt.

(In neueren Versionen von tasksetgibt es auch eine -aOption, die Sets or retrieves the CPU affinity of all the tasks (threads) for a given PID.jedoch nicht klar ist, ob dies auch für Tochterprozesse einer gestarteten Aufgabe funktioniert taskset, anstatt einen bereits laufenden Prozess zu ändern.)

Andre Holzner
quelle
Funktioniert unter openSUSE 42.2 -amit bereits ausgeführten Prozessen.
ederag
3

Ich benutze tasksetdie -aOption erfolgreich. Ich habe einen Server namens videoconverterd, der viel CPU verbraucht. topzeigt an

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 8991 root      20   0 1299472 346724  47380 S 385.7  4.3  42:41.37 videoconverterd

Nach dem Ausführen taskset -apc 0 8991sinkt die CPU-Last auf

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 8991 root      20   0 1221832 293344  47380 S  99.7  3.7  49:13.28 videoconverterd

Ich verwende CentOS 7 mit tasksetVersion 2.23.2.

user322804
quelle