Comment connaître le nombre de processeurs utilisant python
-
06-07-2019 - |
Question
Je souhaite connaître le nombre de processeurs sur la machine locale utilisant Python. Le résultat doit être utilisateur / réel
, généré par time (1)
lorsqu'il est appelé avec un programme dimensionnant uniquement l'espace utilisateur.
La solution 2
Si le nombre de processeurs disponibles dans votre processus actuel vous intéresse, vous devez vérifier cpuset en premier. Sinon (ou si cpuset n'est pas utilisé), multiprocessing.cpu_count ()
est la voie à suivre dans Python 2.6 et les versions plus récentes. 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')
Autres conseils
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 ces situations:
>>> import psutil
>>> psutil.cpu_count()
2
Ceci devrait fonctionner sur toute plate-forme prise en charge par psutil
(Unix et Windows).
Notez que dans certaines occasions, multiprocessing.cpu_count
peut générer un NotImplementedError
alors 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 le multitraitement
et, si elles é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 déclenche NotImplementedError
si os.cpu_count ()
renvoie Aucun
("Impossible de déterminer le nombre de processeurs").
import os
print(os.cpu_count())
indépendant de la plateforme:
psutil.cpu_count (logical = False)
multiprocessing.cpu_count ()
renverra le nombre de processeurs logiques. Ainsi, si vous avez un processeur quad-core avec hyperthreading, il renverra 8
. Si vous souhaitez connaître le nombre de processeurs physiques, utilisez les liaisons python à 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, compte tenu du sched_setaffinity
appel système Linux , qui limite les processeurs et leurs processus les enfants peuvent courir.
0
signifie obtenir la valeur du processus en cours. La fonction renvoie un set ()
des processeurs autorisés, d'où la nécessité de len ()
.
multiprocessing.cpu_count ()
, en revanche, renvoie simplement le nombre total de processeurs physiques.
La différence est particulièrement importante car certains systèmes de gestion de grappes, tels que les Platform LSF , limitent le nombre de processeurs. utilisation 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 noyaux:
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 le résultat est:
16
1
nproc
respecte l'affinité par défaut:
taskset -c 0 nproc
sorties:
1
et man nproc
rendent 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 qu’il ne s’agit que d’UNIX. Je suppose que Windows doit disposer d'une API d'affinité similaire, éventuellement SetProcessAffinityMask
, je me demande donc pourquoi il n'a pas été porté. Mais je ne connais rien de Windows.
Testé sous Ubuntu 16.04, Python 3.5.2.
Vous ne savez pas comment ajouter du code ou 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 " dans ce but.
import joblib
print joblib.cpu_count()
Cette méthode vous donnera le nombre de processeurs du système. joblib doit cependant être installé. Pour plus d'informations sur joblib, cliquez ici https://pythonhosted.org/joblib/parallel.html .
Vous pouvez également utiliser le package numexpr de python. Il contient de nombreuses fonctions simples utiles pour obtenir des informations sur le processeur système.
import numexpr as ne
print ne.detect_number_of_cores()
Ils vous donnent le nombre de processeurs hyperthreaded
-
multiprocessing.cpu_count ()
-
os.cpu_count ()
Ils vous donnent le nombre de processeurs de la machine virtuelle
-
psutil.cpu_count ()
-
numexpr.detect_number_of_cores ()
Ne compte que si vous travaillez sur des ordinateurs virtuels.
Une autre option si vous n'avez pas Python 2.6:
import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")