Respostas:
Se você tem python com uma versão> = 2.6, pode simplesmente usar
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html#multiprocessing.cpu_count
os.cpu_count()
Se você estiver interessado no número de processadores disponíveis para o seu processo atual, verifique primeiro o cpuset . Caso contrário (ou se o cpuset não estiver em uso), multiprocessing.cpu_count()
é o caminho a seguir no Python 2.6 e mais recente. O método a seguir recai em alguns métodos alternativos nas versões mais antigas do 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
são respectivamente ff, ef ef --- correspondentes a 8, 4 e 4 pela sua matemática (correta). No entanto, os números reais de CPUs são respectivamente 4, 2 e 1. Acho que contar o número de ocorrências da palavra "processador" /proc/cpuinfo
pode ser o melhor caminho a percorrer. (Ou eu tenho o errado pergunta?)
/proc/cpuinfo
disso, se para qualquer uma das listagens de cada "processador" você multiplica os "irmãos" pelos "núcleos da CPU" você obtém seu número "Cpus_allowed". E entendo que os irmãos se referem à hiper-segmentação, daí a sua referência a "virtual". Mas o fato é que seu número "permitido por Cpus" é 8 no meu MacPro, enquanto sua multiprocessing.cpu_count()
resposta é 4. A minha open('/proc/cpuinfo').read().count('processor')
também produz 4, o número de núcleos físicos (dois processadores de núcleo duplo).
open('/proc/self/status').read()
esquece de fechar o arquivo. Use em with open('/proc/self/status') as f: f.read()
vez disso
os.cpu_count()
with
-lo quando encontrar um caso em que você precise.
Outra opção é usar a psutil
biblioteca, que sempre é útil nessas situações:
>>> import psutil
>>> psutil.cpu_count()
2
Isso deve funcionar em qualquer plataforma suportada por psutil
(Unix e Windows).
Observe que, em algumas ocasiões, multiprocessing.cpu_count
pode demorar um NotImplementedError
pouco psutil
para conseguir o número de CPUs. Isso ocorre simplesmente porque psutil
primeiro tenta usar as mesmas técnicas usadas multiprocessing
e, se elas falharem, também usa outras técnicas.
psutil.cpu_count(logical = True)
psutil.cpu_count()
obtém 12 (é uma CPU de 6 núcleos com hyperthreading). Isso ocorre porque o argumento padrão de logical
é True, então você precisa escrever explicitamente psutil.cpu_count(logical = False)
para obter o número de núcleos físicos.
No Python 3.4 ou superior : os.cpu_count () .
multiprocessing.cpu_count()
é implementado em termos dessa função, mas aumenta NotImplementedError
se os.cpu_count()
retorna None
("não é possível determinar o número de CPUs").
cpu_count
. len(os.sched_getaffinity(0))
pode ser melhor, dependendo da finalidade.
os.cpu_count()
OP solicita) pode diferir do número de CPUs disponíveis para o processo atual ( os.sched_getaffinity(0)
).
os.sched_getaffinity(0)
está disponível no BSD, portanto é necessário o uso de (sem outra biblioteca externa). os.cpu_count()
len(os.sched_getaffinity(0))
é o que você geralmente quer
https://docs.python.org/3/library/os.html#os.sched_getaffinity
os.sched_getaffinity(0)
(adicionado em Python 3) retorna o conjunto de CPUs disponíveis, considerando a sched_setaffinity
chamada do sistema Linux , que limita em quais CPUs um processo e seus filhos podem executar.
0
significa obter o valor para o processo atual. A função retorna uma set()
das CPUs permitidas, portanto, a necessidade len()
.
multiprocessing.cpu_count()
por outro lado, apenas retorna o número total de CPUs físicas.
A diferença é especialmente importante porque certos sistemas de gerenciamento de cluster, como o Platform LSF, limitam o uso da CPU do trabalho sched_getaffinity
.
Portanto, se você usar multiprocessing.cpu_count()
, seu script pode tentar usar muito mais núcleos do que os disponíveis, o que pode levar a sobrecarga e tempo limite.
Podemos ver a diferença concretamente restringindo a afinidade com a taskset
utilidade.
Por exemplo, se eu restringir o Python a apenas 1 núcleo (núcleo 0) no meu sistema de 16 núcleos:
taskset -c 0 ./main.py
com o script de teste:
main.py
#!/usr/bin/env python3
import multiprocessing
import os
print(multiprocessing.cpu_count())
print(len(os.sched_getaffinity(0)))
então a saída é:
16
1
nproc
no entanto, respeita a afinidade por padrão e:
taskset -c 0 nproc
saídas:
1
e man nproc
deixa isso bem explícito:
imprimir o número de unidades de processamento disponíveis
nproc
possui o --all
sinalizador para o caso menos comum em que você deseja obter a contagem física de CPU:
taskset -c 0 nproc --all
A única desvantagem desse método é que ele parece ser apenas UNIX. Suponho que o Windows deve ter uma API de afinidade semelhante, possivelmente SetProcessAffinityMask
, então me pergunto por que não foi portada. Mas não sei nada sobre o Windows.
Testado no Ubuntu 16.04, Python 3.5.2.
Se você deseja saber o número de núcleos físicos (não núcleos virtuais com hyperthread), aqui está uma solução independente de plataforma:
psutil.cpu_count(logical=False)
https://github.com/giampaolo/psutil/blob/master/INSTALL.rst
Observe que o valor padrão para logical
é True
, portanto, se você deseja incluir núcleos com hyperthread, pode usar:
psutil.cpu_count()
Isso fornecerá o mesmo número que os.cpu_count()
e multiprocessing.cpu_count()
, nenhum dos quais possui o logical
argumento de palavra - chave.
psutil.cpu_count(logical=False) #4
psutil.cpu_count(logical=True) #8
emultiprocessing.cpu_count() #8
Isso fornece a contagem de CPU com hyperthread
multiprocessing.cpu_count()
os.cpu_count()
Isso fornece a contagem de CPU da máquina virtual
psutil.cpu_count()
numexpr.detect_number_of_cores()
Só importa se você trabalha em VMs.
os.cpu_count()
e multiprocessing.cpu_count()
retornará as contagens de CPU com hyperthread, e não a contagem física real da CPU.
multiprocessing.cpu_count()
retornará o número de CPUs lógicas; portanto, se você tiver uma CPU quad-core com hyperthreading, ela retornará 8
. Se você deseja o número de CPUs físicas, use as ligações python para hwloc:
#!/usr/bin/env python
import hwloc
topology = hwloc.Topology()
topology.load()
print topology.get_nbobjs_by_type(hwloc.OBJ_CORE)
O hwloc foi projetado para ser portátil em sistemas operacionais e arquiteturas.
psutil.cpu_count(logical=False)
Não é possível descobrir como adicionar ao código ou responder à mensagem, mas aqui está o suporte ao jython que você pode aderir antes de desistir:
# jython
try:
from java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass
Você também pode usar "joblib" para esse fim.
import joblib
print joblib.cpu_count()
Este método fornece o número de cpus no sistema. O joblib precisa ser instalado. Mais informações sobre joblib podem ser encontradas aqui https://pythonhosted.org/joblib/parallel.html
Como alternativa, você pode usar o pacote numexpr de python. Possui muitas funções simples úteis para obter informações sobre a CPU do sistema.
import numexpr as ne
print ne.detect_number_of_cores()
Outra opção se você não possui o Python 2.6:
import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")
/proc/<PID>/status
possui algumas linhas que informam o número de CPUs no cpuset atual: procureCpus_allowed_list
.