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/statussono 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/cpuinfopotrebbe essere il modo migliore di procedere. (O ho la domanda sbagliata?)
/proc/cpuinfoche 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()
withper quando incontri un caso in cui ne hai bisogno.
Un'altra opzione è quella di utilizzare la psutillibreria, 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_countpotrebbe aumentare un NotImplementedErrorpo ' psutilsarà possibile ottenere il numero di CPU. Questo semplicemente perché psutilprima cerca di usare le stesse tecniche usate multiprocessinge, 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 NotImplementedErrorse 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_setaffinitychiamata di sistema Linux , che limita le CPU su cui è possibile eseguire un processo e i suoi figli.
0significa 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 nprocrende abbastanza esplicito:
stampa il numero di unità di elaborazione disponibili
nprocha il --allflag 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' logicalargomento keyword.
psutil.cpu_count(logical=False) #4 psutil.cpu_count(logical=True) #8emultiprocessing.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>/statusha alcune righe che indicano il numero di CPU nell'attuale cpuset: cercaCpus_allowed_list.