Pregunta

Quiero saber la cantidad de CPU en la máquina local que usa Python. El resultado debería ser user / real como resultado de time (1) cuando se llama con un programa de espacio de usuario de escala óptima.

¿Fue útil?

Solución 2

Si está interesado en la cantidad de procesadores disponibles para su proceso actual, debe verificar cpuset primero. De lo contrario (o si cpuset no está en uso), multiprocessing.cpu_count () es el camino a seguir en Python 2.6 y versiones posteriores. El siguiente método recurre a un par de métodos alternativos en versiones anteriores de 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')

Otros consejos

Si tiene Python con una versión > = 2.6, simplemente puede usar

import multiprocessing

multiprocessing.cpu_count()

http://docs.python.org/library/multiprocessing.html# multiprocessing.cpu_count

Otra opción es usar la psutil , que siempre resulta útil en estas situaciones:

>>> import psutil
>>> psutil.cpu_count()
2

Esto debería funcionar en cualquier plataforma compatible con psutil (Unix y Windows).

Tenga en cuenta que en algunas ocasiones multiprocessing.cpu_count puede generar un NotImplementedError mientras que psutil podrá obtener el número de CPU. Esto se debe simplemente a que psutil primero intenta usar las mismas técnicas utilizadas por multiprocesamiento y, si fallan, también usa otras técnicas.

En Python 3.4+: os.cpu_count () .

multiprocessing.cpu_count () se implementa en términos de esta función pero aumenta NotImplementedError si os.cpu_count () devuelve Ninguno (" no se puede determinar el número de CPU ").

import os

print(os.cpu_count())

plataforma independiente:

  

psutil.cpu_count (logical = False)

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

multiprocessing.cpu_count () devolverá el número de CPU lógicas, por lo que si tiene una CPU de cuatro núcleos con hyperthreading, devolverá 8 . Si desea la cantidad de CPU físicas, use los enlaces de python para hwloc:

#!/usr/bin/env python
import hwloc
topology = hwloc.Topology()
topology.load()
print topology.get_nbobjs_by_type(hwloc.OBJ_CORE)

hwloc está diseñado para ser portátil en sistemas operativos y arquitecturas.

len (os.sched_getaffinity (0)) es lo que generalmente quieres

https://docs.python.org/3/library /os.html#os.sched_getaffinity

os.sched_getaffinity (0) (agregado en Python 3) devuelve el conjunto de CPU disponibles teniendo en cuenta sched_setaffinity llamada al sistema Linux , que limita las CPU de un proceso y sus los niños pueden correr.

0 significa obtener el valor para el proceso actual. La función devuelve un set () de CPU permitidas, por lo tanto, la necesidad de len () .

multiprocessing.cpu_count () por otro lado solo devuelve el número total de CPU físicas.

La diferencia es especialmente importante porque ciertos sistemas de administración de clúster como Platform LSF limitan la CPU del trabajo uso con sched_getaffinity .

Por lo tanto, si usa multiprocessing.cpu_count () , su script podría intentar usar muchos más núcleos de los que tiene disponibles, lo que puede provocar sobrecarga y tiempos de espera.

Podemos ver la diferencia concretamente restringiendo la afinidad con la utilidad taskset .

Por ejemplo, si restrinjo Python a solo 1 núcleo (núcleo 0) en mi sistema de 16 núcleos:

taskset -c 0 ./main.py

con el script de prueba:

main.py

#!/usr/bin/env python3

import multiprocessing
import os

print(multiprocessing.cpu_count())
print(len(os.sched_getaffinity(0)))

entonces el resultado es:

16
1

nproc respeta la afinidad por defecto:

taskset -c 0 nproc

salidas:

1

y man nproc lo hace bastante explícito:

  

imprime el número de unidades de procesamiento disponibles

nproc tiene el indicador --all para el caso menos común en el que desea obtener el conteo físico de CPU:

taskset -c 0 nproc --all

El único inconveniente de este método es que parece ser solo UNIX. Supuse que Windows debe tener una API de afinidad similar, posiblemente SetProcessAffinityMask , así que me pregunto por qué no se ha portado. Pero no sé nada sobre Windows.

Probado en Ubuntu 16.04, Python 3.5.2.

No se puede encontrar la forma de agregar al código o responder al mensaje, pero aquí hay soporte para jython que puede agregar antes de darse por vencido:

# jython
try:
    from java.lang import Runtime
    runtime = Runtime.getRuntime()
    res = runtime.availableProcessors()
    if res > 0:
        return res
except ImportError:
    pass

También puede usar " joblib " para este propósito.

import joblib
print joblib.cpu_count()

Este método le dará la cantidad de cpus en el sistema. Sin embargo, debe instalarse JobLib. Puede encontrar más información sobre joblib aquí https://pythonhosted.org/joblib/parallel.html

Alternativamente, puede usar el paquete numexpr de python. Tiene muchas funciones simples útiles para obtener información sobre la CPU del sistema.

import numexpr as ne
print ne.detect_number_of_cores()

Estos le dan el conteo de CPU hiperprocesado

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

Estos le dan el conteo de CPU de la máquina virtual

  1. psutil.cpu_count()
  2. numexpr.detect_number_of_cores()

Solo importa si trabaja en máquinas virtuales.

Otra opción si no tiene Python 2.6:

import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top