828 votes

Comment déterminer le nombre de CPU en utilisant python ?

Je souhaite connaître le nombre de CPU sur la machine locale en utilisant Python. Le résultat doit être user/real tel qu'il est produit par time(1) lorsqu'il est appelé avec un programme de dimensionnement optimal de l'espace utilisateur uniquement.

7 votes

Vous devez garder à l'esprit les cpusets (dans Linux). Si vous êtes dans un cpuset, les solutions ci-dessous donneront toujours le nombre de CPU réels dans le système, et non le nombre disponible pour votre processus. /proc/<PID>/status contient quelques lignes qui vous indiquent le nombre de CPUs dans le cpuset actuel : cherchez Cpus_allowed_list .

0 votes

Si vous utilisez une torche, vous pouvez faire import torch.multiprocessing; mp.cpu_count()

1275voto

Nadia Alramli Points 40381

Si vous avez une version de python >= 2.6, vous pouvez simplement utiliser

import multiprocessing

multiprocessing.cpu_count()

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

6 votes

Le multiprocessus est également pris en charge dans la version 3.x

3 votes

Je voudrais ajouter que cela ne fonctionne pas avec IronPython qui soulève une erreur de type NotImplementedError.

6 votes

Cela donne le nombre d'unités centrales disponibles... non utilisées par le programme !

237voto

phihag Points 89765

Si vous êtes intéressé par le nombre de processeurs disponible à votre processus actuel, vous devez vérifier cpuset d'abord. Sinon (ou si cpuset n'est pas utilisé), multiprocessing.cpu_count() est la voie à suivre dans Python 2.6 et les versions plus récentes. La méthode suivante s'appuie sur quelques méthodes alternatives dans les versions plus anciennes 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')

0 votes

Sur un MacPro 1,0 fonctionnant sous la dernière version d'Ubuntu, sur un ordinateur portable HP fonctionnant sous une Debian récente, et sur une vieille eMachine fonctionnant sous une ancienne Ubuntu, les résultats de cpus_allowed sont les suivants /proc/self/status sont respectivement ff, f et f--- correspondant à 8, 4 et 4 selon vos calculs (corrects). Cependant, le nombre réel de processeurs est respectivement de 4, 2 et 1. Je trouve qu'en comptant le nombre d'occurrences du mot "processeur" en /proc/cpuinfo peut être la meilleure solution. (Ou est-ce que je me trompe de question ?)

1 votes

En faisant des recherches plus approfondies - si l'on peut dire de "Googler" -, j'ai découvert que l'utilisation de /proc/cpuinfo que si, pour n'importe quelle liste de chaque "processeur", vous multipliez la "fratrie" par les "cpu cores", vous obtenez votre nombre de "Cpus_allowed". J'en déduis que les frères et sœurs font référence à l'hyperthreading, d'où votre référence au terme "virtuel". Mais il n'en reste pas moins que votre nombre de "Cpus_allowed" est de 8 sur mon MacPro alors que votre nombre de multiprocessing.cpu_count() La réponse est 4. Mon propre open('/proc/cpuinfo').read().count('processor') produit également 4, le nombre de cœurs physiques (deux processeurs à double cœur).

2 votes

open('/proc/self/status').read() oublie de fermer le dossier. Utiliser with open('/proc/self/status') as f: f.read() au lieu de

136voto

Bakuriu Points 22607

Une autre option consiste à utiliser la fonction psutil qui s'avèrent toujours utiles dans ces situations :

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

Cela devrait fonctionner sur toutes les plates-formes prises en charge par psutil (Unix et Windows).

Notez que dans certains cas multiprocessing.cpu_count peut soulever une NotImplementedError alors que psutil pourra obtenir le nombre de CPU. Cela s'explique simplement par le fait que psutil tente d'abord d'utiliser les mêmes techniques que celles utilisées par multiprocessing et, en cas d'échec, il utilise également d'autres techniques.

17 votes

Cette méthode est vraiment bonne, car elle permet de déterminer si les cœurs du processeur sont logiques ou physiques. psutil.cpu_count(logical = True)

0 votes

Bonjour @Bakuriu, Existe-t-il un moyen d'obtenir le nombre de cœurs de processeur utilisés par un processus spécifique à l'aide de psutil ?

5 votes

@Devilhunter Sous Windows sur mon Intel i7-8700 psutil.cpu_count() donne 12 (c'est un CPU à 6 cœurs avec hyperthreading). Ceci est dû au fait que l'argument par défaut de logical est True, vous devez donc explicitement écrire psutil.cpu_count(logical = False) pour obtenir le nombre de cœurs physiques.

22voto

Douglas B. Staple Points 1748

multiprocessing.cpu_count() renverra le nombre de CPU logiques, donc si vous avez un CPU à quatre cœurs avec hyperthreading, il renverra 8 . Si vous souhaitez connaître le nombre de processeurs physiques, utilisez les liens python vers hwloc :

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

hwloc est conçu pour être portable à travers les systèmes d'exploitation et les architectures.

0 votes

Dans ce cas, je souhaite connaître le nombre d'unités centrales logiques (c'est-à-dire le nombre de threads que je devrais lancer si ce programme s'adapte vraiment bien), mais la réponse peut néanmoins être utile.

9 votes

O psutil.cpu_count(logical=False)

10voto

Ben Scherrey Points 67

Je ne sais pas comment ajouter au code ou répondre au message, mais voici un support pour jython que vous pouvez ajouter avant d'abandonner :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X