Python kullanarak CPU sayısı nasıl bulunur?


537

Python kullanarak yerel makinedeki CPU sayısını bilmek istiyorum. Sonuç, en iyi şekilde ölçeklendirilen bir kullanıcı-alanı programı ile çağrıldığında user/realçıktı olarak alınmalıdır time(1).


3
Cpusets'i (Linux'ta) aklınızda bulundurmalısınız. Bir cpuset'deyseniz, aşağıdaki çözümler, işleminiz için mevcut olan sayıyı değil, sistemdeki gerçek CPU'ların sayısını vermeye devam edecektir. /proc/<PID>/statusmevcut cpuset'teki CPU sayısını söyleyen bazı satırlara sahiptir: arayın Cpus_allowed_list.
wpoely86

Yanıtlar:


854

> = 2.6 sürümüne sahip bir pitonunuz varsa,

import multiprocessing

multiprocessing.cpu_count()

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


4
çoklu işlem ayrıca 3.x'te desteklenir
LittleByBlue

3
Bu bir NotImplementedError yükseltir IronPython işe yaramaz eklemek istiyorum.
Matthias

1
Bu, kullanılabilir CPU sayısını verir ... program tarafından kullanılmıyor!
amc

25
Python 3.6.2'de sadece kullanabilirimos.cpu_count()
Aşil

4
Ayrıca, aşağıda belirtildiği gibi, bu sayı "yoğun" hiper iş parçacıklı cpus içerebilir, cpu yoğun görevler planlıyorsanız istediğiniz şey olmayabilir.
Christopher Barber

186

Mevcut işleminizde kullanabileceğiniz işlemci sayısı ile ilgileniyorsanız , önce cpuset'i kontrol etmeniz gerekir . Aksi takdirde (veya cpuset kullanılmıyorsa), multiprocessing.cpu_count()Python 2.6 ve daha yenisine gitmenin yoludur. Aşağıdaki yöntem, Python'un eski sürümlerinde birkaç alternatif yönteme geri döner:

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

En yeni Ubuntu'yu çalıştıran bir MacPro 1,0'da, yeni bir Debian çalıştıran bir HP Dizüstü Bilgisayarda ve eski bir Ubuntu çalıştıran eski bir eMachine'de cpus_allowed sonuçları /proc/self/statussırasıyla ff, f ve f --- sırasıyla 8, 4 ve 4 (doğru) matematiğinizle. Ancak gerçek CPU sayısı sırasıyla 4, 2 ve 1'dir. "İşlemci" kelimesinin geçtiği yerlerin sayılmasının /proc/cpuinfodaha iyi bir yol olabileceğini düşünüyorum. (Ya da sorum yanlış mı?)
Mike O'Connor

1
Biraz daha fazla araştırma ile --- bu "Google" denilebiliyorsa --- /proc/cpuinfoher "işlemci" için listelerden herhangi biri için "kardeşler" ile "cpu çekirdekleri" "Cpus_allowed" numaranızı alırsınız. Ve kardeşlerin hiper iş parçacığına atıfta bulunduklarını, dolayısıyla "sanal" referansınızı topladım. Ancak gerçek şu ki, "Cpus_allowed" numaranız MacPro'mda 8 iken, multiprocessing.cpu_count()cevabınız 4'tür. Benim open('/proc/cpuinfo').read().count('processor')de fiziksel çekirdekler (4 adet çift çekirdekli işlemci) sayısı olan 4 üretir.
Mike O'Connor

1
open('/proc/self/status').read()dosyayı kapatmayı unutur. with open('/proc/self/status') as f: f.read()Bunun yerine kullanın
timdiels

4
os.cpu_count()
Ocak 17'de goetzc

1
@amcgregor Bu durumda kabul edilebilir, kabul edilmiş, sadece dosya tanıtıcıları açık bırakılıyor, ki uzun süredir çalışan bir daemon / süreç yazmıyorsanız sorun değil; korkarım ki işletim sisteminin maksimum açık dosya tutamaçlarına çarpabilirim. İşlem sona ermeden önce tekrar okunması gereken bir dosyaya yazarken daha kötü, ancak burada durum böyle değil, bu yüzden tartışmalı bir nokta. withİhtiyacınız olan bir durumla karşılaştığınızda kullanma alışkanlığına sahip olmak için hala iyi bir fikir .
timdiels

91

Başka bir seçenek de psutil, bu durumlarda her zaman yararlı olan kütüphaneyi kullanmaktır :

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

Bu, psutil(Unix ve Windows) tarafından desteklenen tüm platformlarda çalışmalıdır .

Not Bazı durumlarda bu multiprocessing.cpu_countbir zam olabilir NotImplementedErrorsüre psutilCPU sayısını elde etmek mümkün olacaktır. Bunun nedeni, psutililk olarak kullanılan tekniklerin aynısını kullanmaya çalışmaktır multiprocessingve eğer başarısız olursa başka teknikler de kullanır.


4
Bu, kullanılan yöntemin CPU çekirdeklerinin mantıksal cevher fiziksel olanları olduğunu öğrenmesine izin verdiği için gerçekten iyidir. psutil.cpu_count(logical = True)
Devilhunter

Merhaba @ Bakuriu, psutil kullanarak belirli bir işlem tarafından kullanılan cpu çekirdek sayısını almak için herhangi bir yolu var mı?
saichand

@Devilhunter Intel i7-8700 üzerinde Windows'ta psutil.cpu_count()12 (hiper iş parçacıklı 6 çekirdekli bir CPU) veriyor. Bunun nedeni, varsayılan bağımsız değişkeninin logicalTrue olması nedeniyle, psutil.cpu_count(logical = False)fiziksel Çekirdeklerin sayısını almak için açıkça yazmanız gerekir .
OscarVanL

52

Python 3.4+ sürümünde: os.cpu_count () .

multiprocessing.cpu_count()Bu fonksiyon açısından uygulanan ancak yükseltir edilir NotImplementedErroreğer os.cpu_count()döner None( "CPU sayısını belirleyemiyor").


4
Ayrıca belgelerine bakın cpu_count. len(os.sched_getaffinity(0))amaca bağlı olarak daha iyi olabilir.
Albert

1
@ Albert evet, sistemdeki CPU sayısı (- os.cpu_count()OP'nin istediği) mevcut işlem için kullanılabilir CPU sayısından farklı olabilir ( os.sched_getaffinity(0)).
jfs

Biliyorum. Sadece bu farkı kaçırabilecek diğer okuyucular için, onlardan daha eksiksiz bir resim elde etmek istedim.
Albert

1
Ayrıca: os.sched_getaffinity(0)bir değil kullanımı bu yüzden, BSD geçerli os.cpu_count()(olduğunu, diğer dış kütüphaneye olmadan) gereklidir.
Cometsong

1
Dikkat edilmelidir ki os.sched_getaffinity Windows'ta mevcut görünmüyor.
manu3d

47

len(os.sched_getaffinity(0)) genellikle istediğin şey

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

os.sched_getaffinity(0)(Python 3'e eklenmiştir), sched_setaffinityLinux sistem çağrısı göz önüne alındığında mevcut bir işlemci setini döndürür .

0mevcut işlem için değer elde etmek anlamına gelir. İşlev set(), izin verilen CPU'lardan birini döndürür , bu nedenle buna ihtiyaç duyulur len().

multiprocessing.cpu_count() Öte yandan, toplam fiziksel CPU sayısını döndürür.

Fark özellikle önemlidir çünkü Platform LSF gibi bazı küme yönetim sistemleri ile iş CPU kullanımını sınırlar sched_getaffinity.

Bu nedenle, kullanırsanız multiprocessing.cpu_count(), komut dosyanız kullanılabilir olandan daha fazla çekirdek kullanmaya çalışabilir ve bu da aşırı yüklenmeye ve zaman aşımlarına neden olabilir.

Farkı, tasksetfayda ile olan yakınlığı kısıtlayarak somut olarak görebiliriz .

Örneğin, Python'u 16 çekirdek sistemimde sadece 1 çekirdek (çekirdek 0) ile kısıtlarsam:

taskset -c 0 ./main.py

test komut dosyası ile:

main.py

#!/usr/bin/env python3

import multiprocessing
import os

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

o zaman çıktı:

16
1

nproc ancak, varsayılan olarak yakınlığa saygı duyar ve:

taskset -c 0 nproc

çıktılar:

1

ve man nprocbunu açıkça ortaya koyuyor:

kullanılabilir işlem birimi sayısını yazdırın

nprocvardır --allFiziksel CPU sayısı almak istiyorum daha az yaygın durum için bayrak:

taskset -c 0 nproc --all

Bu yöntemin tek dezavantajı, bunun yalnızca UNIX gibi görünmesidir. Windows'un benzer bir benzeşim API'sına sahip olması gerekiyordu SetProcessAffinityMask, bu yüzden neden taşınmamış olduğunu merak ediyorum. Ama Windows hakkında hiçbir şey bilmiyorum.

Ubuntu 16.04, Python 3.5.2'de test edilmiştir.


3
Yalnızca Unix'te bulunur.
Christopher Barber

@ChristopherBarber cevaba eklenen bilgi için teşekkürler.
Ciro Santilli 法轮功 15 病 六四 事件 法轮功

33

platform bağımsız:

psutil.cpu_count (mantıksal = False)

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


4
Mantıksal olmayan bir mantıksal CPU arasındaki fark nedir? dizüstü bilgisayarımda: psutil.cpu_count(logical=False) #4 psutil.cpu_count(logical=True) #8vemultiprocessing.cpu_count() #8
user305883

1
@ user305883 x86 CPU'nuz olduğunu varsayarsak , bu makinede hiper iş parçacığınız vardır , yani her fiziksel çekirdek iki hiper iş parçacığına ('mantıksal' çekirdek) karşılık gelir. Hiper iş parçacığı, fiziksel çekirdeğin bir kısmı A iş parçacığı için boşta kaldığında B iş parçacığındaki yönergeleri yürütmek için kullanılmasına izin verir (örneğin, önbellekten veya bellekten alınan verilerin beklenmesi). Kodunuza bağlı olarak, ek çekirdek kullanımının bir ya da birkaç yüzdesi olabilir, ancak gerçek bir fiziksel çekirdeğin performansının çok altındadır.
Andre Holzner

23

Bunlar hiper iş parçacıklı CPU sayısını verir

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

Bunlar size sanal makine CPU sayısını verir

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

Yalnızca VM'lerde çalışıyorsanız önemlidir.


Pek sayılmaz. As kaydetti os.cpu_count()ve multiprocessing.cpu_count()hiper cpu sayısını değil, gerçek fiziksel işlemci sayısını döndürür.
Christopher Barber

2
Evet. Yeniden yazdım. Tipik olarak çekirdek x 2'dir. Demek istediğim, sanal bir makinedeyseniz, 8 çekirdek oyulmuşsa, ancak ana makineniz fiziksel olarak 20 çekirdektir, ilk komut seti size 20, ikinci komut seti verir 8.
yangliu2

21

multiprocessing.cpu_count()mantıksal CPU sayısını döndürür, bu nedenle hiper iş parçacıklı dört çekirdekli bir CPU'nuz varsa, geri döner 8. Fiziksel CPU sayısını istiyorsanız, hwloc için python bağlarını kullanın:

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

hwloc, işletim sistemleri ve mimariler arasında taşınabilir olacak şekilde tasarlanmıştır.


Bu durumda, mantıksal CPU sayısını istiyorum (yani, bu program gerçekten iyi ölçeklenirse kaç tane iş parçacığı başlatmalıyım), ancak yine de cevap yararlı olabilir.
phihag

7
veyapsutil.cpu_count(logical=False)
TimZaman

8

Kodu nasıl ekleyeceğinizi veya mesajı nasıl yanıtlayacağınızı anlayamıyorum, ancak vazgeçmeden önce takabileceğiniz jython desteği:

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

7

Bu, farklı işletim sistemleri / sistemler kullanan, ancak tüm dünyalardan en iyi şekilde yararlanmak isteyenler için işe yarayabilir:

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

5

Bu amaçla "joblib" kullanabilirsiniz.

import joblib
print joblib.cpu_count()

Bu yöntem size sistemdeki cpus sayısını verecektir. joblib olsa kurulmalıdır. Joblib hakkında daha fazla bilgiyi burada bulabilirsiniz https://pythonhosted.org/joblib/parallel.html

Alternatif olarak, numexpr python paketini kullanabilirsiniz. Sistem cpu hakkında bilgi almak için yararlı birçok basit işlevi vardır.

import numexpr as ne
print ne.detect_number_of_cores()

joblib, temeldeki çoklu işlem modülünü kullanır. Bunun için doğrudan çok işlemcili çağırmak en iyisidir.
ogrisel

1

Python 2.6'nız yoksa başka bir seçenek:

import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")

2
Teşekkürler! Bu Linux olsa sadece mevcut ve zaten dahil olduğu cevabım .
phihag
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.