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/statussã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/cpuinfopode ser o melhor caminho a percorrer. (Ou eu tenho o errado pergunta?)
/proc/cpuinfodisso, 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 psutilbiblioteca, 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_countpode demorar um NotImplementedErrorpouco psutilpara conseguir o número de CPUs. Isso ocorre simplesmente porque psutilprimeiro tenta usar as mesmas técnicas usadas multiprocessinge, 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 NotImplementedErrorse 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_setaffinitychamada do sistema Linux , que limita em quais CPUs um processo e seus filhos podem executar.
0significa 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 tasksetutilidade.
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 nprocdeixa isso bem explícito:
imprimir o número de unidades de processamento disponíveis
nprocpossui o --allsinalizador 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 logicalargumento de palavra - chave.
psutil.cpu_count(logical=False) #4 psutil.cpu_count(logical=True) #8emultiprocessing.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>/statuspossui algumas linhas que informam o número de CPUs no cpuset atual: procureCpus_allowed_list.