Domanda

Voglio sapere il numero di CPU sul computer locale usando Python. Il risultato dovrebbe essere user / real come output entro time (1) quando chiamato con un programma solo per lo spazio utente in scala ottimale.

È stato utile?

Soluzione 2

Se sei interessato al numero di processori disponibili al tuo attuale processo, devi controllare cpuset per primo. Altrimenti (o se cpuset non è in uso), multiprocessing.cpu_count () è la strada da percorrere in Python 2.6 e successive. Il seguente metodo ritorna a un paio di metodi alternativi nelle versioni precedenti di 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')

Altri suggerimenti

Se hai Python con una versione > = 2.6 puoi semplicemente usare

import multiprocessing

multiprocessing.cpu_count()

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

Un'altra opzione è quella di utilizzare la libreria psutil , che risulta sempre utile in queste situazioni:

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

Questo dovrebbe funzionare su qualsiasi piattaforma supportata da psutil (Unix e Windows).

Nota che in alcune occasioni multiprocessing.cpu_count può generare un NotImplementedError mentre psutil sarà in grado di ottenere il numero di CPU. Questo semplicemente perché psutil tenta innanzitutto di utilizzare le stesse tecniche utilizzate da multiprocessing e, se falliscono, utilizza anche altre tecniche.

In Python 3.4+: os.cpu_count () .

multiprocessing.cpu_count () è implementato in termini di questa funzione ma genera NotImplementedError se os.cpu_count () restituisce Nessuno (" impossibile determinare il numero di CPU ").

import os

print(os.cpu_count())

indipendente dalla piattaforma:

  

psutil.cpu_count (logico = False)

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

multiprocessing.cpu_count () restituirà il numero di CPU logiche, quindi se si dispone di una CPU quad-core con hyperthreading, verrà restituito 8 . Se vuoi il numero di CPU fisiche, usa i collegamenti python per hwloc:

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

hwloc è progettato per essere portatile su sistemi operativi e architetture.

len (os.sched_getaffinity (0)) è ciò che di solito vuoi

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

os.sched_getaffinity (0) (aggiunto in Python 3) restituisce il set di CPU disponibili considerando sched_setaffinity chiamata di sistema Linux , che limita quali CPU un processo e i suoi i bambini possono correre.

0 significa ottenere il valore per il processo corrente. La funzione restituisce un set () di CPU consentite, quindi la necessità di len () .

multiprocessing.cpu_count () invece restituisce solo il numero totale di CPU fisiche.

La differenza è particolarmente importante perché alcuni sistemi di gestione dei cluster come Platform LSF limit job CPU utilizzo con sched_getaffinity .

Pertanto, se si utilizza multiprocessing.cpu_count () , lo script potrebbe tentare di utilizzare un numero di core maggiore di quello disponibile, il che potrebbe causare sovraccarichi e timeout.

Possiamo vedere concretamente la differenza limitando l'affinità con l'utilità tasket .

Ad esempio, se restringo Python a un solo core (core 0) nel mio sistema a 16 core:

taskset -c 0 ./main.py

con lo script di test:

main.py

#!/usr/bin/env python3

import multiprocessing
import os

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

quindi l'output è:

16
1

nproc rispetta l'affinità di default:

taskset -c 0 nproc

uscite:

1

e man nproc lo rendono abbastanza esplicito:

  

stampa il numero di unità di elaborazione disponibili

nproc ha il flag --all per il caso meno comune in cui si desidera ottenere il conteggio fisico della CPU:

taskset -c 0 nproc --all

L'unico aspetto negativo di questo metodo è che questo sembra essere solo UNIX. Suppongo che Windows debba avere un'API di affinità simile, possibilmente SetProcessAffinityMask , quindi mi chiedo perché non sia stato portato. Ma non so nulla di Windows.

Testato in Ubuntu 16.04, Python 3.5.2.

Non riesco a capire come aggiungere al codice o rispondere al messaggio, ma ecco il supporto per jython che puoi seguire prima di rinunciare:

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

Puoi anche utilizzare " joblib " per questo scopo.

import joblib
print joblib.cpu_count()

Questo metodo ti darà il numero di cpus nel sistema. joblib deve essere installato però. Maggiori informazioni su joblib sono disponibili qui https://pythonhosted.org/joblib/parallel.html

In alternativa puoi usare il pacchetto numexpr di python. Ha molte semplici funzioni utili per ottenere informazioni sul sistema cpu.

import numexpr as ne
print ne.detect_number_of_cores()

Questi ti danno il conteggio della CPU hyperthreaded

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

Questi ti danno il conteggio CPU della macchina virtuale

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

È importante solo se lavori su macchine virtuali.

Un'altra opzione se non hai Python 2.6:

import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top