Je veux connaître le nombre de processeurs sur la machine locale utilisant Python. Le résultat doit être user/real
comme sortie de time(1)
lorsqu'il est appelé avec un programme à mise à l'échelle optimale de l'espace utilisateur.
Si vous êtes intéressé par le nombre de processeurs disponibles par rapport à votre processus actuel, vous devez d'abord vérifier cpuset . Sinon (ou si cpuset n'est pas utilisé), multiprocessing.cpu_count()
est le chemin à parcourir dans Python 2.6 et plus récent. La méthode suivante a recours à plusieurs méthodes alternatives dans les anciennes versions de Python:
import os
import re
import subprocess
def available_cpu_count():
""" Number of available virtual or physical CPUs on this system, i.e.
user/real as output by time(1) when called with an optimally scaling
userspace-only program"""
# cpuset
# cpuset may restrict the number of *available* processors
try:
m = re.search(r'(?m)^Cpus_allowed:\s*(.*)$',
open('/proc/self/status').read())
if m:
res = bin(int(m.group(1).replace(',', ''), 16)).count('1')
if res > 0:
return res
except IOError:
pass
# Python 2.6+
try:
import multiprocessing
return multiprocessing.cpu_count()
except (ImportError, NotImplementedError):
pass
# https://github.com/giampaolo/psutil
try:
import psutil
return psutil.cpu_count() # psutil.NUM_CPUS on old versions
except (ImportError, AttributeError):
pass
# POSIX
try:
res = int(os.sysconf('SC_NPROCESSORS_ONLN'))
if res > 0:
return res
except (AttributeError, ValueError):
pass
# Windows
try:
res = int(os.environ['NUMBER_OF_PROCESSORS'])
if res > 0:
return res
except (KeyError, ValueError):
pass
# jython
try:
from Java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass
# BSD
try:
sysctl = subprocess.Popen(['sysctl', '-n', 'hw.ncpu'],
stdout=subprocess.PIPE)
scStdout = sysctl.communicate()[0]
res = int(scStdout)
if res > 0:
return res
except (OSError, ValueError):
pass
# Linux
try:
res = open('/proc/cpuinfo').read().count('processor\t:')
if res > 0:
return res
except IOError:
pass
# Solaris
try:
pseudoDevices = os.listdir('/devices/pseudo/')
res = 0
for pd in pseudoDevices:
if re.match(r'^cpuid@[0-9]+$', pd):
res += 1
if res > 0:
return res
except OSError:
pass
# Other UNIXes (heuristic)
try:
try:
dmesg = open('/var/run/dmesg.boot').read()
except IOError:
dmesgProcess = subprocess.Popen(['dmesg'], stdout=subprocess.PIPE)
dmesg = dmesgProcess.communicate()[0]
res = 0
while '\ncpu' + str(res) + ':' in dmesg:
res += 1
if res > 0:
return res
except OSError:
pass
raise Exception('Can not determine number of CPUs on this system')
Si vous avez python avec une version> = 2.6, vous pouvez simplement utiliser
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html#multiprocessing.cpu_count
Une autre option consiste à utiliser la bibliothèque psutil
, qui s'avère toujours utile dans les cas suivants:
>>> import psutil
>>> psutil.cpu_count()
2
Cela devrait fonctionner sur n’importe quelle plate-forme supportée par psutil
(Unix et Windows).
Notez que dans certaines occasions, multiprocessing.cpu_count
peut générer un NotImplementedError
tandis que psutil
pourra obtenir le nombre de processeurs. C’est simplement parce que psutil
essaie d’abord d’utiliser les mêmes techniques que celles utilisées par multiprocessing
et, si celles-ci échouent, il utilise également d’autres techniques.
Dans Python 3.4+: os.cpu_count () .
multiprocessing.cpu_count()
est implémenté en termes de cette fonction mais soulève NotImplementedError
si os.cpu_count()
renvoie None
("ne peut pas déterminer le nombre de CPU").
import os
print(os.cpu_count())
plateforme indépendante:
psutil.cpu_count (logical = False)
multiprocessing.cpu_count()
renvoie le nombre de processeurs logiques. Ainsi, si vous disposez d'un processeur quad-core avec hyperthreading, il renverra 8
. Si vous souhaitez connaître le nombre de processeurs physiques, utilisez les liaisons python avec hwloc:
#!/usr/bin/env python
import hwloc
topology = hwloc.Topology()
topology.load()
print topology.get_nbobjs_by_type(hwloc.OBJ_CORE)
hwloc est conçu pour être portable sur plusieurs systèmes d'exploitation et architectures.
len(os.sched_getaffinity(0))
est ce que vous voulez habituellement
https://docs.python.org/3/library/os.html#os.sched_getaffinity
os.sched_getaffinity(0)
(ajouté dans Python 3) renvoie l'ensemble des processeurs disponibles en considérant sched_setaffinity
appel système Linux , ce qui limite les processeurs et leurs enfants. peut courir sur.
0
signifie obtenir la valeur du processus en cours. La fonction retourne une set()
des CPU autorisées, d'où la nécessité de len()
.
multiprocessing.cpu_count()
, d'autre part, renvoie simplement le nombre total de processeurs physiques.
La différence est particulièrement importante car certains systèmes de gestion de grappe, tels que Platform LSF , limitent l’utilisation de la CPU par le travail avec sched_getaffinity
.
Par conséquent, si vous utilisez multiprocessing.cpu_count()
, votre script peut essayer d'utiliser beaucoup plus de cœurs que ce dont il dispose, ce qui peut entraîner une surcharge et des délais.
Nous pouvons voir la différence concrètement en limitant l'affinité avec l'utilitaire taskset
.
Par exemple, si je limite Python à un seul noyau (core 0) dans mon système à 16 cœurs:
taskset -c 0 ./main.py
avec le script de test:
main.py
#!/usr/bin/env python3
import multiprocessing
import os
print(multiprocessing.cpu_count())
print(len(os.sched_getaffinity(0)))
alors la sortie est:
16
1
nproc
respecte toutefois l’affinité par défaut et:
taskset -c 0 nproc
les sorties:
1
et man nproc
rend cela très explicite:
imprimer le nombre d'unités de traitement disponibles
nproc
a le drapeau --all
pour le cas le moins fréquent où vous souhaitez obtenir le nombre de CPU physique:
taskset -c 0 nproc --all
Le seul inconvénient de cette méthode est que cela semble être uniquement UNIX. Je suppose que Windows doit avoir une API d'affinité similaire, éventuellement SetProcessAffinityMask
, alors je me demande pourquoi elle n'a pas été portée. Mais je ne connais rien de Windows.
Testé sous Ubuntu 16.04, Python 3.5.2.
Ceux-ci vous donnent le nombre de CPU hyperthreaded
multiprocessing.cpu_count()
os.cpu_count()
Ceux-ci vous donnent le nombre de CPU de la machine virtuelle
psutil.cpu_count()
numexpr.detect_number_of_cores()
Ne compte que si vous travaillez sur des VM.
Vous ne savez pas comment ajouter au code ou comment répondre au message, mais voici le support technique pour jython que vous pouvez intégrer avant d'abandonner:
# jython
try:
from Java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass
Vous pouvez également utiliser "joblib" à cette fin.
import joblib
print joblib.cpu_count()
Cette méthode vous donnera le nombre de processeurs dans le système. joblib doit cependant être installé. Plus d'informations sur joblib peuvent être trouvées ici https://pythonhosted.org/joblib/parallel.html
Sinon, vous pouvez utiliser le paquet numexpr de python. Il a beaucoup de fonctions simples utiles pour obtenir des informations sur le processeur système.
import numexpr as ne
print ne.detect_number_of_cores()
import os
import sys
def cpu_count():
'''
Returns the number of CPUs in the system
'''
if sys.platform == 'win32':
try:
num = int(os.environ['NUMBER_OF_PROCESSORS'])
except (ValueError, KeyError):
num = 0
Elif 'bsd' in sys.platform or sys.platform == 'darwin':
comm = '/sbin/sysctl -n hw.ncpu'
if sys.platform == 'darwin':
comm = '/usr' + comm
try:
with os.popen(comm) as p:
num = int(p.read())
except ValueError:
num = 0
else:
try:
num = os.sysconf('SC_NPROCESSORS_ONLN')
except (ValueError, OSError, AttributeError):
num = 0
if num >= 1:
return num
else:
raise NotImplementedError('cannot determine number of cpus')
Une autre option si vous n'avez pas Python 2.6:
import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")