Cách tìm ra số lượng CPU sử dụng python


537

Tôi muốn biết số lượng CPU trên máy cục bộ bằng Python. Kết quả phải user/reallà đầu ra time(1)khi được gọi với chương trình chỉ dành cho không gian người dùng.


3
Bạn nên ghi nhớ cpusets (trong Linux). Nếu bạn đang ở trong một cpuset, các giải pháp bên dưới vẫn sẽ cung cấp số lượng CPU thực trong hệ thống, chứ không phải số lượng có sẵn cho quy trình của bạn. /proc/<PID>/statuscó một số dòng cho bạn biết số lượng CPU trong cpuset hiện tại: tìm kiếm Cpus_allowed_list.
wpoely86

Câu trả lời:


854

Nếu bạn có python với phiên bản> = 2.6, bạn chỉ cần sử dụng

import multiprocessing

multiprocessing.cpu_count()

http://docs.python.org/l Library / multiprocessing.html # multiprocessing.cpu_count


4
đa xử lý cũng được hỗ trợ trong 3.x
LittleByBlue

3
Tôi muốn thêm rằng điều này không hoạt động trong IronPython, điều này làm tăng NotIm HiệnedError.
Matthias

1
Điều này cung cấp số lượng CPU có sẵn ... không được chương trình sử dụng!
amc

25
Trên Python 3.6.2 tôi chỉ có thể sử dụngos.cpu_count()
Achilles

4
Ngoài ra, như được lưu ý dưới đây, số lượng này có thể bao gồm cpus siêu ảo "ảo", có thể không phải là những gì bạn muốn nếu bạn đang lên lịch cho các nhiệm vụ chuyên sâu về cpu.
Christopher Barber

186

Nếu bạn quan tâm đến số lượng bộ xử lý có sẵn cho quy trình hiện tại của mình, trước tiên bạn phải kiểm tra cpuset . Mặt khác (hoặc nếu cpuset không được sử dụng), multiprocessing.cpu_count()là cách để đi trong Python 2.6 và mới hơn. Phương thức sau đây quay lại một vài phương thức thay thế trong các phiên bản cũ hơn của 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')

Trên MacPro 1.0 chạy Ubuntu mới nhất, trên Máy tính xách tay HP chạy Debian gần đây và trên eMachine cũ chạy Ubuntu cũ, các kết quả cpus_allowed /proc/self/statustương ứng là ff, f và f --- tương ứng với 8, 4 và 4 bằng toán học (chính xác) của bạn. Tuy nhiên, số lượng CPU thực tế tương ứng là 4, 2 và 1. Tôi thấy rằng việc đếm số lần xuất hiện của từ "bộ xử lý" /proc/cpuinfocó thể là cách tốt hơn để đi. (Hay tôi có câu hỏi sai?)
Mike O'Connor

1
Với một số nghiên cứu tiếp theo --- nếu có thể nói về "Googling" --- tôi tìm thấy từ việc sử dụng /proc/cpuinfonó nếu với bất kỳ một danh sách nào cho mỗi "bộ xử lý", bạn nhân "anh chị em" với "lõi cpu" bạn nhận được số "Cpus_allowed" của mình. Và tôi tập hợp rằng các anh chị em đề cập đến siêu phân luồng, do đó bạn tham khảo "ảo". Nhưng sự thật vẫn là số "Cpus_allowed" của bạn là 8 trên MacPro của tôi trong khi multiprocessing.cpu_count()câu trả lời của bạn là 4. Riêng tôi open('/proc/cpuinfo').read().count('processor')cũng tạo ra 4, số lõi vật lý (hai bộ xử lý lõi kép).
Mike O'Connor

1
open('/proc/self/status').read()quên đóng tập tin Sử dụng with open('/proc/self/status') as f: f.read()thay thế
timdiels

4
os.cpu_count()
goetzc

1
@amcgregor Trong trường hợp này, có thể chấp nhận, đồng ý, chỉ cần xử lý tệp được mở mà tôi đoán là ổn nếu bạn không viết một trình nền / quy trình chạy dài; mà tôi sợ có thể kết thúc việc xử lý tệp mở tối đa của HĐH. Tệ hơn khi ghi vào một tệp cần được đọc lại trước khi quá trình kết thúc, nhưng đó không phải là trường hợp ở đây vì vậy đó là một điểm cần thiết. Vẫn là một ý tưởng tốt để có thói quen sử dụng withkhi bạn gặp phải trường hợp bạn cần.
timdiels

91

Một tùy chọn khác là sử dụng psutilthư viện, vốn luôn hữu ích trong các tình huống sau:

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

Điều này sẽ hoạt động trên mọi nền tảng được hỗ trợ bởi psutil(Unix và Windows).

Lưu ý rằng trong một số trường hợp multiprocessing.cpu_countcó thể tăng một NotImplementedErrorthời gian psutilsẽ có thể có được số lượng CPU. Điều này đơn giản là vì psutillần đầu tiên cố gắng sử dụng các kỹ thuật tương tự được sử dụng bởi multiprocessingvà nếu thất bại, nó cũng sử dụng các kỹ thuật khác.


4
Điều này là thực sự tốt, xem xét rằng phương pháp được sử dụng cho phép tìm ra là lõi CPU là những lõi vật lý logic. psutil.cpu_count(logical = True)
Devilhunter

Xin chào @Bakuriu, Có cách nào để lấy số lõi cpu đang được sử dụng bởi một quy trình cụ thể bằng psutil không?
saichand

@Devilhunter Trên Windows trên Intel i7-8700 của tôi psutil.cpu_count()cho 12 (đó là CPU 6 lõi với khả năng siêu phân luồng). Điều này là do đối số mặc định logicallà True, do đó bạn cần phải viết rõ ràng psutil.cpu_count(logical = False)để có được số lượng Cores vật lý.
OscarVanL

52

Trong Python 3,4+ : os.cpu_count () .

multiprocessing.cpu_count()được triển khai theo chức năng này nhưng tăng NotImplementedErrornếu os.cpu_count()trả về None("không thể xác định số lượng CPU").


4
Xem thêm các tài liệu của cpu_count. len(os.sched_getaffinity(0))có thể tốt hơn, tùy thuộc vào mục đích.
Albert

1
@Albert vâng, số lượng CPU trong hệ thống ( os.cpu_count()Yêu cầu OP yêu cầu) có thể khác với số lượng CPU có sẵn cho quy trình hiện tại ( os.sched_getaffinity(0)).
JFS

Tôi biết. Tôi chỉ muốn thêm rằng cho những độc giả khác, những người có thể bỏ lỡ sự khác biệt này, để có được một bức tranh hoàn chỉnh hơn từ họ.
Albert

1
Đồng thời: os.sched_getaffinity(0)không có sẵn trên BSD, vì vậy việc sử dụng các os.cpu_count()yêu cầu (không có thư viện bên ngoài khác, đó là).
Cometsong

1
Cần lưu ý os.sched_getaffinity dường như không có sẵn trên Windows.
manu3d

47

len(os.sched_getaffinity(0)) là những gì bạn thường muốn

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

os.sched_getaffinity(0)(được thêm vào trong Python 3) trả về bộ CPU có sẵn khi xem xét sched_setaffinitycuộc gọi hệ thống Linux , giới hạn CPU mà một quá trình và con của nó có thể chạy.

0có nghĩa là để có được giá trị cho quá trình hiện tại. Hàm trả về một set()CPU được phép, do đó cần phải có len().

multiprocessing.cpu_count() mặt khác chỉ trả về tổng số CPU vật lý.

Sự khác biệt đặc biệt quan trọng vì các hệ thống quản lý cụm nhất định như Nền tảng LSF giới hạn việc sử dụng CPU công việc sched_getaffinity.

Do đó, nếu bạn sử dụng multiprocessing.cpu_count(), tập lệnh của bạn có thể cố gắng sử dụng nhiều lõi hơn mức có sẵn, điều này có thể dẫn đến quá tải và hết thời gian.

Chúng ta có thể thấy sự khác biệt một cách cụ thể bằng cách hạn chế mối quan hệ với tasksettiện ích.

Ví dụ: nếu tôi giới hạn Python chỉ 1 lõi (lõi 0) trong hệ thống 16 lõi của mình:

taskset -c 0 ./main.py

với kịch bản thử nghiệm:

chính

#!/usr/bin/env python3

import multiprocessing
import os

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

thì đầu ra là:

16
1

nproc tuy nhiên, tôn trọng mối quan hệ theo mặc định và:

taskset -c 0 nproc

đầu ra:

1

man nproclàm cho điều đó khá rõ ràng:

in số lượng đơn vị xử lý có sẵn

nproc--allcờ cho trường hợp ít phổ biến hơn mà bạn muốn lấy số lượng CPU vật lý:

taskset -c 0 nproc --all

Nhược điểm duy nhất của phương pháp này là nó dường như chỉ là UNIX. Tôi nghĩ rằng Windows phải có API mối quan hệ tương tự, có thể SetProcessAffinityMask, vì vậy tôi tự hỏi tại sao nó không được chuyển. Nhưng tôi không biết gì về Windows.

Đã thử nghiệm trong Ubuntu 16.04, Python 3.5.2.


3
Chỉ có sẵn trên Unix.
Christopher Barber

@ChristopherBarber cảm ơn vì thông tin, đã thêm vào câu trả lời.
Ciro Santilli 郝海东 冠状 病 事件

33

nền tảng độc lập:

psutil.cpu_count (logic = Sai)

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


4
Sự khác biệt giữa CPU logic và không phải là logic là gì? trên máy tính xách tay của tôi: psutil.cpu_count(logical=False) #4 psutil.cpu_count(logical=True) #8multiprocessing.cpu_count() #8
user305883

1
@ user305883 giả sử bạn có CPU x86, bạn có siêu phân luồng trên máy này, tức là mỗi lõi vật lý tương ứng với hai siêu phân luồng (lõi 'logic'). Siêu phân luồng cho phép lõi vật lý được sử dụng để thực hiện các lệnh từ luồng B khi các phần của nó không hoạt động đối với luồng A (ví dụ như chờ dữ liệu được tìm nạp từ bộ đệm hoặc bộ nhớ). Tùy thuộc vào mã của bạn, người ta có thể nhận được một hoặc vài chục phần trăm sử dụng lõi bổ sung nhưng nó thấp hơn nhiều so với hiệu suất của lõi vật lý thực sự.
Andre Holzner

23

Chúng cung cấp cho bạn số lượng CPU siêu phân luồng

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

Chúng cung cấp cho bạn số lượng CPU máy ảo

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

Chỉ quan trọng nếu bạn làm việc trên máy ảo.


Không hẳn vậy. Như đã lưu ý, os.cpu_count()multiprocessing.cpu_count()sẽ trả về số lượng cpu siêu phân luồng, chứ không phải số lượng cpu vật lý thực tế.
Christopher Barber

2
Đúng. Tôi viết lại. Đó thường là số lõi x 2. Ý tôi là nếu bạn đang ở trên một máy ảo, thì đã khắc được 8 lõi, nhưng máy chủ của bạn là 20 lõi, bộ lệnh đầu tiên cung cấp cho bạn 20, bộ lệnh thứ hai cung cấp cho bạn 8.
yangliu2

21

multiprocessing.cpu_count()sẽ trả về số lượng CPU logic, vì vậy nếu bạn có CPU lõi tứ với siêu phân luồng, nó sẽ trả về 8. Nếu bạn muốn số lượng CPU vật lý, hãy sử dụng các liên kết python để hwloc:

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

hwloc được thiết kế để có thể di động trên các hệ điều hành và kiến ​​trúc.


Trong trường hợp này, tôi muốn số lượng CPU logic (nghĩa là tôi nên bắt đầu bao nhiêu luồng nếu chương trình này thực sự có quy mô tốt), nhưng dù sao câu trả lời có thể hữu ích.
phihag

7
hoặcpsutil.cpu_count(logical=False)
TimZaman

8

Không thể tìm ra cách thêm mã hoặc trả lời tin nhắn nhưng đây là hỗ trợ cho jython mà bạn có thể giải quyết trước khi bạn từ bỏ:

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

7

Điều này có thể làm việc cho những người trong chúng ta sử dụng các hệ thống / hệ điều hành khác nhau, nhưng muốn có được điều tốt nhất trong tất cả các thế giới:

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

5

Bạn cũng có thể sử dụng "joblib" cho mục đích này.

import joblib
print joblib.cpu_count()

Phương pháp này sẽ cung cấp cho bạn số lượng cpus trong hệ thống. joblib cần phải được cài đặt mặc dù. Thông tin thêm về joblib có thể được tìm thấy ở đây https://pythonhosted.org/joblib/abul.html

Ngoài ra, bạn có thể sử dụng gói numexpr của python. Nó có rất nhiều chức năng đơn giản hữu ích để lấy thông tin về cpu hệ thống.

import numexpr as ne
print ne.detect_number_of_cores()

joblib sử dụng mô đun đa xử lý cơ bản. Có lẽ tốt nhất là gọi trực tiếp vào đa xử lý cho việc này.
ogrisel

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.