Відповіді:
Якщо у вас python з версією> = 2.6, ви можете просто використовувати
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html#multiprocessing.cpu_count
os.cpu_count()
Якщо вас цікавить кількість процесорів, доступних для вашого поточного процесу, вам слід спочатку перевірити cpuset . В іншому випадку (або якщо cpuset не використовується), multiprocessing.cpu_count()
це шлях перейти в Python 2.6 і новіші. Наступний метод повертається до пари альтернативних методів у старих версіях 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')
/proc/self/status
відповідно є ff, f і f ---, що відповідають 8, 4 і 4 вашою (правильною) математикою. Однак фактична кількість процесорів відповідно 4, 2 і 1. Я вважаю, що підрахунок кількості зустрічей слова "процесор" /proc/cpuinfo
може бути кращим способом. (Або у мене питання неправильне?)
/proc/cpuinfo
, якщо для будь-якого з списків кожного "процесора" ви помножите "братів і сестер" на "ядра процесора" ви отримуєте свій номер "Cpus_allowed". І я вважаю, що побратими відносяться до гіперточок, звідси ваше посилання на "віртуальне". Але факт залишається фактом, що у вашому MacPro число "Cpus_allowed" - 8, тоді як ваша multiprocessing.cpu_count()
відповідь - 4. Моя власна open('/proc/cpuinfo').read().count('processor')
також виробляє 4, кількість фізичних ядер (два двоядерні процесори).
open('/proc/self/status').read()
забуває закрити файл. Використовуйте with open('/proc/self/status') as f: f.read()
замість цього
os.cpu_count()
with
коли ви стикаєтеся з випадком, коли це вам потрібно.
Іншим варіантом є використання psutil
бібліотеки, яка завжди виявляється корисною в таких ситуаціях:
>>> import psutil
>>> psutil.cpu_count()
2
Це має працювати на будь-якій платформі, підтримуваній psutil
(Unix та Windows).
Зауважте, що в деяких випадках multiprocessing.cpu_count
може збільшитись NotImplementedError
час psutil
, зможете отримати кількість процесорів. Це просто тому, що psutil
спочатку намагаються використовувати ті самі методи, якими вони користуються, multiprocessing
а якщо вони не вдаються, вони також використовують інші методи.
psutil.cpu_count(logical = True)
psutil.cpu_count()
дає 12 (це 6-ядерний процесор з гіперточенням). Це тому, що аргумент за замовчуванням logical
- True, тому вам явно потрібно написати, psutil.cpu_count(logical = False)
щоб отримати кількість фізичних ядер.
У Python 3.4+ : os.cpu_count () .
multiprocessing.cpu_count()
реалізується з точки зору цієї функції, але збільшується, NotImplementedError
якщо os.cpu_count()
повертається None
("не вдається визначити кількість процесорів").
cpu_count
. len(os.sched_getaffinity(0))
може бути краще, залежно від мети.
os.cpu_count()
що запитує ОП) може відрізнятися від кількості ЦП, доступних для поточного процесу ( os.sched_getaffinity(0)
).
os.sched_getaffinity(0)
це НЕ є на BSD, тому використання os.cpu_count()
не потрібно (без інших зовнішніх бібліотек, тобто).
len(os.sched_getaffinity(0))
це те, що ти зазвичай хочеш
https://docs.python.org/3/library/os.html#os.sched_getaffinity
os.sched_getaffinity(0)
(додано в Python 3) повертає набір доступних процесорів з урахуванням sched_setaffinity
системного виклику Linux , який обмежує, який процесор може працювати і його діти.
0
означає отримати значення для поточного процесу. Функція повертає set()
дозволені процесори, таким чином, необхідність у len()
.
multiprocessing.cpu_count()
з іншого боку, просто повертає загальну кількість фізичних процесорів.
Різниця особливо важлива, оскільки деякі системи управління кластерами, такі як платформа LSF, обмежують використання CPU у роботіsched_getaffinity
.
Тому, якщо ви використовуєте multiprocessing.cpu_count()
, ваш скрипт може спробувати використати набагато більше ядер, ніж є в наявності, що може призвести до перевантаження та затримки часу.
Ми можемо бачити різницю конкретно, обмежуючи спорідненість із taskset
утилітою.
Наприклад, якщо я обмежую Python лише 1 ядром (core 0) в моїй 16-ядерній системі:
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. Я вважав, що Windows повинен мати подібний API спорідненості, можливо SetProcessAffinityMask
, тому мені цікаво, чому він не був перенесений. Але я нічого не знаю про Windows.
Тестовано в Ubuntu 16.04, Python 3.5.2.
платформа незалежна:
psutil.cpu_count (логічно = помилково)
psutil.cpu_count(logical=False) #4
psutil.cpu_count(logical=True) #8
таmultiprocessing.cpu_count() #8
Вони дають вам підрахунок процесора
multiprocessing.cpu_count()
os.cpu_count()
Вони дають вам кількість процесорів віртуальної машини
psutil.cpu_count()
numexpr.detect_number_of_cores()
Має значення лише те, якщо ви працюєте на віртуальних машинах.
os.cpu_count()
і multiprocessing.cpu_count()
повертаються гіпертрезовані підрахунки процесора, а не фактичні фізичні підрахунки процесора.
multiprocessing.cpu_count()
поверне кількість логічних процесорів, тому якщо у вас чотириядерний процесор з гіперточенням, він повернеться 8
. Якщо вам потрібно кількість фізичних процесорів, використовуйте зв'язки python для hwloc:
#!/usr/bin/env python
import hwloc
topology = hwloc.Topology()
topology.load()
print topology.get_nbobjs_by_type(hwloc.OBJ_CORE)
hwloc розроблений так, щоб він був портативним в ОС та архітектурах.
psutil.cpu_count(logical=False)
Неможливо зрозуміти, як додати до коду чи відповісти на повідомлення, але ось підтримка jython, яку ви можете застосувати перед тим, як відмовитися:
# jython
try:
from java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass
Для цього також можна використовувати "joblib".
import joblib
print joblib.cpu_count()
Цей метод дасть вам кількість cpus в системі. joblib потрібно встановити. Більше інформації про joblib можна знайти тут https://pythonhosted.org/joblib/parallel.html
Крім того, ви можете використовувати numexpr пакет python. У ньому багато простих функцій, корисних для отримання інформації про системний процесор.
import numexpr as ne
print ne.detect_number_of_cores()
Ще один варіант, якщо у вас немає Python 2.6:
import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")
/proc/<PID>/status
містить рядки, які повідомляють вам кількість процесорів у поточному процесорі: шукайтеCpus_allowed_list
.