अजगर का उपयोग करके सीपीयू की संख्या कैसे पता करें


536

मैं पायथन का उपयोग करके स्थानीय मशीन पर सीपीयू की संख्या जानना चाहता हूं। परिणाम के user/realरूप में उत्पादन किया जाना चाहिए time(1)जब एक अनुकूलन स्केलिंग उपयोगकर्ता-केवल प्रोग्राम के साथ कहा जाता है।


3
आपको cpusets (लिनक्स में) को ध्यान में रखना चाहिए। यदि आप cpuset में हैं, तो नीचे दिए गए समाधान सिस्टम में वास्तविक CPU की संख्या देंगे, न कि आपकी प्रक्रिया के लिए उपलब्ध नंबर। /proc/<PID>/statusकुछ पंक्तियाँ हैं जो आपको वर्तमान सीपीयू में सीपीयू की संख्या बताती हैं: तलाश करें Cpus_allowed_list
wpoely86

जवाबों:


854

यदि आपके पास एक संस्करण> = 2.6 के साथ अजगर है तो आप बस उपयोग कर सकते हैं

import multiprocessing

multiprocessing.cpu_count()

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


4
मल्टीप्रोसेसिंग भी 3.x
LittleByBlue

3
मैं जोड़ना चाहता हूं कि यह IronPython में काम नहीं करता है जो NotImplementedError बढ़ाता है।
मथियास

1
यह उपलब्ध पर CPU की संख्या देता है ... प्रोग्राम द्वारा उपयोग में नहीं!
एएमसी

25
अजगर 3.6.2 पर मैं सिर्फ इस्तेमाल कर सकते हैंos.cpu_count()
Achilles

4
इसके अलावा, जैसा कि नीचे उल्लेख किया गया है, इस गिनती में "वर्चुअल" हाइपरथ्रेडेड सीपीस शामिल हो सकता है, जो कि आप क्या नहीं चाहते हैं यदि आप सीपीयू-गहन कार्यों को शेड्यूल कर रहे हैं।
क्रिस्टोफर बार्बर

185

यदि आप अपनी वर्तमान प्रक्रिया के लिए उपलब्ध प्रोसेसर की संख्या में रुचि रखते हैं , तो आपको पहले cpuset को जांचना होगा । अन्यथा (या अगर cpuset उपयोग में नहीं है), multiprocessing.cpu_count()Python 2.6 और नए में जाने का तरीका है। निम्नलिखित विधि अजगर के पुराने संस्करणों में वैकल्पिक तरीकों के एक जोड़े के लिए वापस आती है:

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')

MacPro 1,0 पर नवीनतम Ubuntu को चलाने वाला, HP लैपटॉप पर हाल ही में डेबियन चल रहा है, और पुराने Ubuntu पर एक पुराने Ubuntu पर चल रहा है, cpus_allowed परिणाम /proc/self/statusक्रमशः ff, f और f --- हैं जो 8, 4 के अनुरूप है। 4 आपके (सही) गणित द्वारा। हालाँकि सीपीयू की वास्तविक संख्या क्रमशः 4, 2 और 1. है। मुझे लगता है कि "प्रोसेसर" शब्द की संख्या की गिनती /proc/cpuinfoकरना बेहतर तरीका हो सकता है। (या क्या मेरा प्रश्न गलत है?)
माइक ओ'कॉनर

1
कुछ और शोधों के साथ --- यदि वह "Googling" कहा जा सकता है --- तो मुझे इस बात का उपयोग है /proc/cpuinfoकि यदि किसी भी "प्रोसेसर" के लिए किसी एक लिस्टिंग के लिए आप "भाई-बहनों" को "सीपीयू कोर" से गुणा करें। आपको अपना "Cpus_allowed" नंबर मिलता है। और मैं इकट्ठा करता हूं कि भाई-बहन हाइपर-थ्रेडिंग का संदर्भ देते हैं, इसलिए आपका "वर्चुअल" संदर्भ है। लेकिन तथ्य यह है कि आपका "Cpus_allowed" नंबर मेरे MacPro पर 8 है जबकि आपका multiprocessing.cpu_count()उत्तर 4 है। मेरा खुद का open('/proc/cpuinfo').read().count('processor')भी 4, भौतिक कोर की संख्या (दो दोहरे कोर प्रोसेसर) है।
माइक ओ'कॉनर

1
open('/proc/self/status').read()फ़ाइल बंद करना भूल जाता है। with open('/proc/self/status') as f: f.read()इसके बजाय का उपयोग करें
timdiels

4
os.cpu_count()
गोएत्ज़क

1
@amcgregor इस मामले में यह स्वीकार्य है, सहमत है, बस फ़ाइल हैंडल को खुला छोड़ दिया जा रहा है जो मुझे लगता है कि यदि आप लंबे समय तक चलने वाले डेमन / प्रक्रिया नहीं लिख रहे हैं तो ठीक है; मुझे डर है कि ओएस के एक अधिकतम खुले फ़ाइल हैंडल को खत्म करने का डर हो सकता है। किसी फ़ाइल को लिखते समय यह बदतर होता है जिसे प्रक्रिया समाप्त होने से पहले फिर से पढ़ने की आवश्यकता होती है, लेकिन यहां ऐसा नहीं है, इसलिए यह एक लूट बिंदु है। फिर भी एक अच्छा विचार है कि withजब आप किसी ऐसे मामले का सामना करते हैं, जहां आपको इसकी आवश्यकता होती है, तब उपयोग करने की आदत होती है।
समयदिवस

91

एक अन्य विकल्प psutilपुस्तकालय का उपयोग करना है, जो हमेशा इन स्थितियों में उपयोगी होता है:

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

यह psutil(यूनिक्स और विंडोज) द्वारा समर्थित किसी भी मंच पर काम करना चाहिए ।

ध्यान दें कि कुछ अवसरों में multiprocessing.cpu_countएक उठा सकती है NotImplementedError, जबकि psutilCPU की संख्या प्राप्त करने में सक्षम हो जाएगा। यह केवल इसलिए है क्योंकि psutilपहले उसी तकनीक का उपयोग करने की कोशिश करता है multiprocessingऔर यदि वे विफल होते हैं, तो यह अन्य तकनीकों का भी उपयोग करता है।


4
यह वास्तव में अच्छा है, यह देखते हुए कि इस्तेमाल की गई विधि यह पता लगाने की अनुमति देती है कि सीपीयू कोर तार्किक अयस्क भौतिक हैं। psutil.cpu_count(logical = True)
डेविलहंटर

हाय @ बकुरीउ, क्या कोई तरीका है कि एक विशिष्ट प्रक्रिया द्वारा उपयोग किए जा रहे सीपीयू कोर की संख्या को Psutil का उपयोग किया जाए?
साचंद

मेरे इंटेल पर विंडोज पर @Devilhunter i7-8700 psutil.cpu_count()12 देता है (यह हाइपरथ्रेडिंग वाला 6-कोर सीपीयू है)। इसका कारण यह है कि डिफ़ॉल्ट तर्क logicalसत्य है, इसलिए आपको psutil.cpu_count(logical = False)भौतिक कोर की संख्या प्राप्त करने के लिए स्पष्ट रूप से लिखने की आवश्यकता है ।
OscarVanL

52

पायथन में 3.4+ : os.cpu_count ()

multiprocessing.cpu_count()इस फ़ंक्शन के संदर्भ में कार्यान्वित किया जाता है लेकिन NotImplementedErrorअगर os.cpu_count()रिटर्न None("सीपीयू की संख्या निर्धारित नहीं कर सकता है")।


4
का प्रलेखन भी देखें cpu_countlen(os.sched_getaffinity(0))उद्देश्य के आधार पर बेहतर हो सकता है।
अल्बर्ट

1
@ अल्बर्ट हाँ, सिस्टम में सीपीयू की संख्या ( os.cpu_count()-ओपी ओपी पूछती है) वर्तमान प्रक्रिया ( os.sched_getaffinity(0)) के लिए उपलब्ध सीपीयू की संख्या से भिन्न हो सकती है ।
jfs

मुझे पता है। मैं सिर्फ अन्य पाठकों के लिए इसे जोड़ना चाहता था, जो इस अंतर को याद कर सकते हैं, उनसे अधिक संपूर्ण चित्र प्राप्त करने के लिए।
अल्बर्ट

1
इसके अलावा: os.sched_getaffinity(0)है नहीं बीएसडी पर उपलब्ध इसलिए का उपयोग, os.cpu_count()आवश्यक है (अन्य बाहरी पुस्तकालय के बिना यह है कि,)।
धूमकेतु

1
यह नोट किया जाना चाहिए os.sched_getaffinity विंडोज पर उपलब्ध नहीं लगता है।
manu3d

47

len(os.sched_getaffinity(0)) वह है जो आप आमतौर पर चाहते हैं

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

os.sched_getaffinity(0)(पायथन 3 में जोड़ा गया) sched_setaffinityलिनक्स सिस्टम कॉल को देखते हुए उपलब्ध सीपीयू का सेट लौटाता है , जो सीपीयू की एक प्रक्रिया को सीमित करता है और इसके बच्चे चल सकते हैं।

0वर्तमान प्रक्रिया के लिए मूल्य प्राप्त करने का मतलब है। फ़ंक्शन एक set()अनुमत सीपीयू देता है, इस प्रकार इसकी आवश्यकता है len()

multiprocessing.cpu_count() दूसरी ओर सिर्फ भौतिक सीपीयू की कुल संख्या लौटाता है।

यह अंतर विशेष रूप से महत्वपूर्ण है क्योंकि कुछ निश्चित प्रबंधन प्रणालियां जैसे कि प्लेटफ़ॉर्म एलएसएफ, नौकरी सीपीयू उपयोग के साथ सीमित है sched_getaffinity

इसलिए, यदि आप उपयोग करते हैं multiprocessing.cpu_count(), तो आपकी स्क्रिप्ट उपलब्ध होने की तुलना में अधिक कोर का उपयोग करने का प्रयास कर सकती है, जिससे ओवरलोड और टाइमआउट हो सकता है।

tasksetउपयोगिता के साथ आत्मीयता को सीमित करके हम अंतर को स्पष्ट रूप से देख सकते हैं ।

उदाहरण के लिए, यदि मैं अपने 16 कोर सिस्टम में पायथन को सिर्फ 1 कोर (कोर 0) तक सीमित करता हूं:

taskset -c 0 ./main.py

परीक्षण स्क्रिप्ट के साथ:

main.py

#!/usr/bin/env python3

import multiprocessing
import os

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

फिर आउटपुट है:

16
1

nproc हालाँकि, डिफ़ॉल्ट रूप से आत्मीयता का सम्मान करता है और:

taskset -c 0 nproc

आउटपुट:

1

और man nprocयह काफी स्पष्ट करता है:

उपलब्ध प्रसंस्करण इकाइयों की संख्या प्रिंट करें

nprocहै --allकम आम मामला है कि आप शारीरिक सीपीयू गिनती प्राप्त करना चाहते हैं के लिए झंडा:

taskset -c 0 nproc --all

इस पद्धति का एकमात्र नकारात्मक पहलू यह है कि यह केवल UNIX प्रतीत होता है। मुझे लगता है कि विंडोज में संभवतः समान समानता वाला एपीआई होना चाहिए SetProcessAffinityMask, इसलिए मुझे आश्चर्य है कि इसे पोर्ट क्यों नहीं किया गया है। लेकिन मुझे विंडोज के बारे में कुछ नहीं पता है।

उबंटू 16.04, पायथन 3.5.2 में परीक्षण किया गया।


3
केवल यूनिक्स पर उपलब्ध है।
क्रिस्टोफर बार्बर

@ChristopherBarber जानकारी के लिए धन्यवाद, उत्तर में जोड़ा गया।
सिरो सेंटिल्ली 郝海东 冠状 i i

33

स्वतंत्र मंच:

psutil.cpu_count (तार्किक = false)

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


4
तार्किक सीपीयू में क्या अंतर है और तार्किक तार्किक नहीं है? मेरे लैपटॉप पर: psutil.cpu_count(logical=False) #4 psutil.cpu_count(logical=True) #8औरmultiprocessing.cpu_count() #8
उपयोगकर्ता305883

1
@ user305883 मान लें कि आपके पास एक x86 CPU है, तो आपके पास इस मशीन पर हाइपरथ्रेडिंग है , यानी प्रत्येक भौतिक कोर दो हाइपरथ्रेड्स ('तार्किक' कोर) से मेल खाती है। हाइपरथ्रेडिंग थ्रेड बी से निर्देशों को निष्पादित करने के लिए भौतिक कोर का उपयोग करने की अनुमति देता है जब इसके कुछ भाग थ्रेड ए के लिए निष्क्रिय होते हैं (जैसे कि कैश या मेमोरी से प्राप्त होने वाले डेटा की प्रतीक्षा करना)। आपके कोड के आधार पर, एक या कुछ दसियों अतिरिक्त मूल उपयोग के प्रतिशत मिल सकते हैं, लेकिन यह वास्तविक भौतिक कोर के प्रदर्शन से काफी नीचे है।
आंद्रे होल्जनर

23

ये आपको हाइपरथ्रेडेड सीपीयू काउंट देते हैं

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

ये आपको वर्चुअल मशीन CPU काउंट प्रदान करते हैं

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

केवल तब ही मायने रखता है जब आप VMs पर काम करते हैं।


ज़रुरी नहीं। जैसा कि उल्लेख किया गया है, os.cpu_count()और multiprocessing.cpu_count()हाइपरथ्रेडेड सीपीयू काउंट्स को लौटाएगा, वास्तविक भौतिक सीपीयू काउंट को नहीं।
क्रिस्टोफर बार्बर

2
हाँ। मैंने फिर से हामी भरी। यह आमतौर पर # कोर का है x 2. मेरा क्या मतलब है कि यदि आप एक आभासी मशीन पर हैं, तो 8 कोर को उकेरा गया है, लेकिन आपकी मेजबान मशीन शारीरिक रूप से 20 कोर है, पहले कमांड का सेट आपको 20 देता है, दूसरा सेट आपको देता है। 8.
यंगलु 2

21

multiprocessing.cpu_count()तार्किक CPU की संख्या लौटाएगा, इसलिए यदि आपके पास हाइपरथ्रेडिंग वाला क्वाड-कोर CPU है, तो यह वापस आ जाएगा 8। यदि आप भौतिक CPU की संख्या चाहते हैं, तो hwloc के लिए अजगर बाइंडिंग का उपयोग करें:

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

hwloc को OSes और आर्किटेक्चर के पार पोर्टेबल बनाया गया है।


इस मामले में, मैं तार्किक सीपीयू की संख्या चाहता हूं (यानी अगर यह कार्यक्रम वास्तव में अच्छी तरह से शुरू होता है, तो मुझे कितने धागे शुरू करने चाहिए), लेकिन फिर भी उत्तर उपयोगी हो सकता है।
फ़िहग

7
याpsutil.cpu_count(logical=False)
टिमजमान

8

कोड को जोड़ने या संदेश का जवाब देने के लिए पता नहीं लगा सकते हैं, लेकिन यहां इस बात का समर्थन है कि आप इससे पहले कि आप इसे उठा सकते हैं, jython का समर्थन:

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

7

यह हम में से उन लोगों के लिए काम कर सकता है जो विभिन्न ओएस / सिस्टम का उपयोग करते हैं, लेकिन सभी दुनिया में सबसे अच्छा प्राप्त करना चाहते हैं:

import os
workers = os.cpu_count()
if 'sched_getaffinity' in dir(os):
    workers = len(os.sched_getaffinity(0))

5

आप इस उद्देश्य के लिए "जॉबलिब" का भी उपयोग कर सकते हैं।

import joblib
print joblib.cpu_count()

यह विधि आपको सिस्टम में cpus की संख्या देगी। जॉबलिब को हालांकि स्थापित करने की आवश्यकता है। जॉबलिब के बारे में अधिक जानकारी https://pythonhosted.org/joblib/parallel.html पर देखी जा सकती है

वैकल्पिक रूप से आप अजगर के सुन्न पैकेज का उपयोग कर सकते हैं। सिस्टम सीपीयू के बारे में जानकारी प्राप्त करने के लिए इसमें बहुत सारे सरल कार्य सहायक हैं।

import numexpr as ne
print ne.detect_number_of_cores()

joblib अंतर्निहित मल्टीप्रोसेसिंग मॉड्यूल का उपयोग करता है। इसके लिए सीधे सीधे मल्टीप्रोसेसिंग में कॉल करना सबसे अच्छा है।
ओग्रेसिल

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.