Como descobrir o número de CPUs usando python
-
06-07-2019 - |
Pergunta
Eu quero saber o número de CPUs na máquina local usando Python. O resultado deve ser user/real
como saída por time(1)
quando chamado com um programa só de espaço do usuário otimizada escala.
Solução 2
Se você está interessado no número de processadores disponível para o seu processo atual, você tem que verificar cpuset primeiro. Caso contrário (ou se cpuset não está em uso), multiprocessing.cpu_count()
é a maneira para ir em Python 2.6 e mais recentes. O método a seguir cai de volta para um par de métodos alternativos em versões 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')
Outras dicas
Se você tiver python com uma versão> = 2.6 você pode simplesmente usar
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html# multiprocessing.cpu_count
Outra opção é usar a biblioteca psutil
, que sempre acabam útil nestas situações:
>>> import psutil
>>> psutil.cpu_count()
2
Isso deve funcionar em qualquer plataforma suportada pelo psutil
(Unix e Windows).
Note que em algumas ocasiões multiprocessing.cpu_count
pode levantar uma NotImplementedError
enquanto psutil
será capaz de obter o número de CPUs. Isto é simplesmente porque psutil
primeiras tentativas de usar as mesmas técnicas usadas por multiprocessing
e, se aqueles falharem, ele também usa outras técnicas.
Em Python 3.4+:. os.cpu_count ()
multiprocessing.cpu_count()
é implementado em termos de esta função, mas levanta NotImplementedError
se os.cpu_count()
retornos None
( "não pode determinar o número de CPUs").
import os
print(os.cpu_count())
independente de plataforma:
psutil.cpu_count (= lógicas False)
multiprocessing.cpu_count()
irá retornar o número de CPUs lógicas, por isso, se você tem um CPU quad-core com hyperthreading, ele retornará 8
. Se quiser que o número de CPUs físicas, use os vínculos python para hwloc:
#!/usr/bin/env python
import hwloc
topology = hwloc.Topology()
topology.load()
print topology.get_nbobjs_by_type(hwloc.OBJ_CORE)
hwloc é projetado para ser portátil através de sistemas operacionais e arquiteturas.
len(os.sched_getaffinity(0))
é o que você normalmente querem
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 o sched_setaffinity
chamada de sistema Linux, o que limita quais CPUs um processo e seus filhos podem correr.
meios 0
para obter o valor para o processo atual. A função retorna um set()
de CPUs permitidos, assim a necessidade de len()
.
multiprocessing.cpu_count()
por outro lado, apenas retorna o número total de CPUs físicas.
A diferença é especialmente importante porque alguns sistemas de gerenciamento de cluster, como Platform LSF CPU emprego limite uso com sched_getaffinity
.
Portanto, se você usar multiprocessing.cpu_count()
, seu script pode tentar usar a maneira mais núcleos do que tem disponível, o que pode levar à sobrecarga e tempos de espera.
Podemos ver a diferença concretamente, restringindo a afinidade com o utilitário taskset
.
Por exemplo, se eu restringir Python para apenas 1 núcleo (core 0) no meu sistema de 16 core:
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
aspectos nproc
afinidade por padrão:
taskset -c 0 nproc
saídas:
1
e man nproc
marcas que bastante explícito:
imprimir o número de unidades de processamento disponível
nproc
tem a bandeira --all
para o caso menos comum que você deseja obter a contagem de CPU física:
taskset -c 0 nproc --all
A única desvantagem deste método é que este parece ser apenas UNIX. Eu deveria Windows deve ter um API afinidade semelhante, possivelmente, SetProcessAffinityMask
, então eu me pergunto por que ele não foi portado. Mas eu não sei nada sobre o Windows.
Testado no Ubuntu 16.04, Python 3.5.2.
Não é possível descobrir como adicionar o código ou responder à mensagem, mas o apoio de aqui para jython que você pode alinhavar em 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 esta finalidade.
import joblib
print joblib.cpu_count()
Este método vai dar-lhe o número de CPUs no sistema. joblib precisa ser instalado embora. Mais informações sobre joblib pode ser encontrada aqui https://pythonhosted.org/joblib/parallel.html
Como alternativa, você pode usar numexpr pacote de python. Tem muitas funções simples útil para obter informações sobre a CPU do sistema.
import numexpr as ne
print ne.detect_number_of_cores()
Estes dão-lhe a CPU hyperthreaded count
-
multiprocessing.cpu_count()
-
os.cpu_count()
Estes dão-lhe a CPU da máquina virtual count
-
psutil.cpu_count()
-
numexpr.detect_number_of_cores()
Só importa se você trabalha em VMs.
Outra opção se você não tem Python 2.6:
import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")