len(os.sched_getaffinity(0))
ist das, was Sie normalerweise wollen
https://docs.python.org/3/library/os.html#os.sched_getaffinity
os.sched_getaffinity(0)
(in Python 3 hinzugefügt) gibt die Menge der verfügbaren CPUs zurück, unter Berücksichtigung des sched_setaffinity
Linux-Systemaufrufs, der die CPUs einschränkt, auf denen ein Prozess und seine Kinder ausgeführt werden können.
0
bedeutet, den Wert für den aktuellen Prozess zu erhalten. Die Funktion gibt ein set()
von erlaubten CPUs zurück, daher die Notwendigkeit von len()
.
multiprocessing.cpu_count()
und os.cpu_count()
hingegen geben nur die Gesamtzahl der logischen CPUs zurück, das heißt z.B. die Anzahl der CPUs unter Berücksichtigung von Hyperthreading.
Der Unterschied ist besonders wichtig, da bestimmte Cluster-Verwaltungssysteme wie Platform LSF die CPU-Auslastung von Jobs mit sched_getaffinity
begrenzen.
Wenn Sie also multiprocessing.cpu_count()
verwenden, könnte Ihr Skript versuchen, viel mehr Kerne zu verwenden, als verfügbar sind, was zu Überlastungen und Zeitüberschreitungen führen kann.
Wir können den Unterschied konkret sehen, indem wir die Affinität mit dem Dienstprogramm taskset
einschränken, das uns ermöglicht, die Affinität eines Prozesses zu steuern.
Minimalbeispiel für taskset
Zum Beispiel, wenn ich Python auf nur einen Kern (Kern 0) in meinem 16-Kern-System beschränke:
taskset -c 0 ./main.py
mit dem Testskript:
main.py
#!/usr/bin/env python3
import multiprocessing
import os
print(multiprocessing.cpu_count())
print(os.cpu_count())
print(len(os.sched_getaffinity(0)))
dann ist die Ausgabe:
16
16
1
Vs nproc
nproc
respektiert standardmäßig die Affinität und:
taskset -c 0 nproc
gibt aus:
1
und man nproc
macht das sehr deutlich:
Gibt die Anzahl der verfügbaren Verarbeitungseinheiten aus
Also verhält sich len(os.sched_getaffinity(0))
standardmäßig wie nproc
.
nproc
hat die Option --all
für den selteneren Fall, dass Sie die Anzahl der physischen CPUs erhalten möchten, ohne taskset zu berücksichtigen:
taskset -c 0 nproc --all
Dokumentation zu os.cpu_count
Die Dokumentation von os.cpu_count
erwähnt dies auch kurz https://docs.python.org/3.8/library/os.html#os.cpu_count
Diese Zahl entspricht nicht der Anzahl der CPUs, die der aktuelle Prozess verwenden kann. Die Anzahl der verwendbaren CPUs kann mit len(os.sched_getaffinity(0))
erhalten werden
Derselbe Kommentar wird auch in der Dokumentation von multiprocessing.cpu_count
kopiert: https://docs.python.org/3/library/multiprocessing.html#multiprocessing.cpu_count
Im Quellcode von 3.8 unter Lib/multiprocessing/context.py
sehen wir auch, dass multiprocessing.cpu_count
einfach an os.cpu_count
weiterleitet, mit der Ausnahme, dass die multiprocessing
-Version eine Ausnahme auslöst, anstatt None zurückzugeben, wenn os.cpu_count
fehlschlägt:
def cpu_count(self):
'''Gibt die Anzahl der CPUs im System zurück'''
num = os.cpu_count()
if num is None:
raise NotImplementedError('Anzahl der CPUs kann nicht ermittelt werden')
else:
return num
Verfügbarkeit von 3.8: Systeme mit einer nativen sched_getaffinity
-Funktion
Der einzige Nachteil dieser os.sched_getaffinity
ist, dass dies bis Python 3.8 offenbar nur UNIX-exklusiv ist.
cpython 3.8 versucht anscheinend einfach, während der Konfigurationszeit ein kleines C "Hello World" mit einem Aufruf der Funktion sched_setaffinity
zu kompilieren, und wenn diese nicht vorhanden ist, wird HAVE_SCHED_SETAFFINITY
nicht gesetzt sein und die Funktion wird wahrscheinlich fehlen:
psutil.Process().cpu_affinity()
: Drittanbieterversion mit einer Windows-Portierung
Das Drittanbieter-Paket psutil
package (pip install psutil
) wurde in einem Beitrag erwähnt: https://stackoverflow.com/a/14840102/895245 aber nicht die Funktion cpu_affinity
: https://psutil.readthedocs.io/en/latest/#psutil.Process.cpu_affinity
Verwendung:
import psutil
print(len(psutil.Process().cpu_affinity()))
Diese Funktion tut dasselbe wie die Standardbibliothek os.sched_getaffinity
unter Linux, aber sie haben sie auch für Windows implementiert, indem sie einen Aufruf der Windows-API-Funktion GetProcessAffinityMask
machen:
Mit anderen Worten: Die Windows-Benutzer müssen aufhören, faul zu sein und einen Patch an die Upstream-Standardbibliothek senden :-)
Getestet in Ubuntu 16.04, Python 3.5.2.
0 Stimmen
Wenn Sie Torch verwenden, können Sie
import torch.multiprocessing; mp.cpu_count()
ausführen.7 Stimmen
Du solltest cpusets (in Linux) im Kopf behalten. Wenn du in einem cpuset bist, geben die unten stehenden Lösungen immer noch die Anzahl der echten CPUs im System an, nicht die Anzahl, die deinem Prozess zur Verfügung steht.
/proc//status
hat einige Zeilen, die dir die Anzahl der CPUs im aktuellen cpuset anzeigen: Suche nachCpus_allowed_list
.