Risposte:
Se hai Python con una versione> = 2.6 puoi semplicemente usare
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html#multiprocessing.cpu_count
os.cpu_count()
Se sei interessato al numero di processori disponibili per il tuo processo attuale, devi prima controllare cpuset . Altrimenti (o se cpuset non è in uso), multiprocessing.cpu_count()
è la strada da percorrere in Python 2.6 e successive. Il seguente metodo ricade su un paio di metodi alternativi nelle versioni precedenti di 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')
/proc/self/status
sono rispettivamente ff, f e f --- corrispondenti a 8, 4 e 4 secondo la tua (corretta) matematica. Tuttavia, i numeri effettivi di CPU sono rispettivamente 4, 2 e 1. Trovo che contare il numero di occorrenze della parola "processore" /proc/cpuinfo
potrebbe essere il modo migliore di procedere. (O ho la domanda sbagliata?)
/proc/cpuinfo
che se per uno degli elenchi per ogni "processore" moltiplichi i "fratelli" per i "core della CPU" ottieni il tuo numero "Cpus_allowed". E capisco che i fratelli si riferiscono all'hyper-threading, da cui il tuo riferimento a "virtuale". Ma resta il fatto che il tuo numero "Cpus_allowed" è 8 sul mio MacPro mentre la tua multiprocessing.cpu_count()
risposta è 4. Il mio open('/proc/cpuinfo').read().count('processor')
produce anche 4, il numero di core fisici (due processori dual-core).
open('/proc/self/status').read()
dimentica di chiudere il file. Usa with open('/proc/self/status') as f: f.read()
invece
os.cpu_count()
with
per quando incontri un caso in cui ne hai bisogno.
Un'altra opzione è quella di utilizzare la psutil
libreria, che risulta sempre utile in queste situazioni:
>>> import psutil
>>> psutil.cpu_count()
2
Questo dovrebbe funzionare su qualsiasi piattaforma supportata da psutil
(Unix e Windows).
Si noti che in alcune occasioni multiprocessing.cpu_count
potrebbe aumentare un NotImplementedError
po ' psutil
sarà possibile ottenere il numero di CPU. Questo semplicemente perché psutil
prima cerca di usare le stesse tecniche usate multiprocessing
e, se falliscono, usa anche altre tecniche.
psutil.cpu_count(logical = True)
psutil.cpu_count()
dà 12 (è una CPU a 6 core con hyperthreading). Questo perché l'argomento predefinito di logical
è True, quindi è necessario scrivere esplicitamente psutil.cpu_count(logical = False)
per ottenere il numero di core fisici.
In Python 3.4+: os.cpu_count () .
multiprocessing.cpu_count()
è implementato in termini di questa funzione ma genera NotImplementedError
se os.cpu_count()
restituisce None
("impossibile determinare il numero di CPU").
cpu_count
. len(os.sched_getaffinity(0))
potrebbe essere migliore, a seconda dello scopo.
os.cpu_count()
—che cosa chiede OP) può differire dal numero di CPU disponibili per il processo corrente ( os.sched_getaffinity(0)
).
os.sched_getaffinity(0)
è disponibile su BSD, quindi è necessario l'uso di (senza altra libreria esterna, cioè). os.cpu_count()
len(os.sched_getaffinity(0))
è quello che di solito vuoi
https://docs.python.org/3/library/os.html#os.sched_getaffinity
os.sched_getaffinity(0)
(aggiunto in Python 3) restituisce il set di CPU disponibili considerando la sched_setaffinity
chiamata di sistema Linux , che limita le CPU su cui è possibile eseguire un processo e i suoi figli.
0
significa ottenere il valore per il processo corrente. La funzione restituisce una set()
delle CPU consentite, quindi la necessità dilen()
.
multiprocessing.cpu_count()
d'altra parte restituisce solo il numero totale di CPU fisiche.
La differenza è particolarmente importante perché alcuni sistemi di gestione dei cluster come Platform LSF limitano l'utilizzo della CPU del lavoro sched_getaffinity
.
Pertanto, se si utilizza multiprocessing.cpu_count()
, lo script potrebbe tentare di utilizzare un numero di core maggiore rispetto a quello disponibile, il che potrebbe causare sovraccarichi e timeout.
Possiamo vedere concretamente la differenza limitando l'affinità con il taskset
utilità.
Ad esempio, se restringo Python a un solo core (core 0) nel mio sistema a 16 core:
taskset -c 0 ./main.py
con lo script di test:
main.py
#!/usr/bin/env python3
import multiprocessing
import os
print(multiprocessing.cpu_count())
print(len(os.sched_getaffinity(0)))
quindi l'output è:
16
1
nproc
tuttavia rispetta l'affinità di default e:
taskset -c 0 nproc
uscite:
1
e lo man nproc
rende abbastanza esplicito:
stampa il numero di unità di elaborazione disponibili
nproc
ha il --all
flag per il caso meno comune in cui si desidera ottenere il conteggio fisico della CPU:
taskset -c 0 nproc --all
L'unico aspetto negativo di questo metodo è che questo sembra essere solo UNIX. Suppongo che Windows debba avere un'API di affinità simile, possibilmente SetProcessAffinityMask
, quindi mi chiedo perché non sia stato portato. Ma non so nulla di Windows.
Testato in Ubuntu 16.04, Python 3.5.2.
Se vuoi conoscere il numero di core fisici (non core hyperthreaded virtuali), ecco una soluzione indipendente dalla piattaforma:
psutil.cpu_count(logical=False)
https://github.com/giampaolo/psutil/blob/master/INSTALL.rst
Si noti che il valore predefinito per logical
è True
, quindi se si desidera includere core hyperthreaded è possibile utilizzare:
psutil.cpu_count()
Questo darà lo stesso numero di os.cpu_count()
e multiprocessing.cpu_count()
, nessuno dei quali ha l' logical
argomento keyword.
psutil.cpu_count(logical=False) #4
psutil.cpu_count(logical=True) #8
emultiprocessing.cpu_count() #8
Questi ti danno il conteggio della CPU hyperthreaded
multiprocessing.cpu_count()
os.cpu_count()
Questi ti danno il conteggio della CPU della macchina virtuale
psutil.cpu_count()
numexpr.detect_number_of_cores()
Importa solo se lavori su VM.
os.cpu_count()
e multiprocessing.cpu_count()
restituirà i conteggi della CPU hyperthreaded, non il conteggio effettivo della CPU fisica.
multiprocessing.cpu_count()
restituirà il numero di CPU logiche, quindi se si dispone di una CPU quad-core con hyperthreading, verrà restituito 8
. Se vuoi il numero di CPU fisiche, usa i collegamenti python per hwloc:
#!/usr/bin/env python
import hwloc
topology = hwloc.Topology()
topology.load()
print topology.get_nbobjs_by_type(hwloc.OBJ_CORE)
hwloc è progettato per essere portatile su sistemi operativi e architetture.
psutil.cpu_count(logical=False)
Non riesco a capire come aggiungere al codice o rispondere al messaggio, ma ecco il supporto per jython che puoi seguire prima di rinunciare:
# jython
try:
from java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass
A tale scopo è anche possibile utilizzare "joblib".
import joblib
print joblib.cpu_count()
Questo metodo ti darà il numero di cpus nel sistema. joblib deve essere installato però. Maggiori informazioni su joblib sono disponibili qui https://pythonhosted.org/joblib/parallel.html
In alternativa puoi usare il pacchetto numexpr di python. Ha molte funzioni semplici utili per ottenere informazioni sulla cpu di sistema.
import numexpr as ne
print ne.detect_number_of_cores()
Un'altra opzione se non hai Python 2.6:
import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")
/proc/<PID>/status
ha alcune righe che indicano il numero di CPU nell'attuale cpuset: cercaCpus_allowed_list
.