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.

Foi útil?

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)

https://github.com/giampaolo/psutil/blob/master/INSTALL.rst

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

  1. multiprocessing.cpu_count()
  2. os.cpu_count()

Estes dão-lhe a CPU da máquina virtual count

  1. psutil.cpu_count()
  2. 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")
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top