Ответы:
Если у вас есть 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". И я понимаю, что братья и сестры относятся к гиперпоточности, отсюда ваша ссылка на «виртуальную». Но факт остается фактом: ваше число «Cpus_allowed» равно 8 на моем MacPro, а ваш 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()
что запрашивает OP) может отличаться от количества процессоров, доступных текущему процессу ( 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()
с другой стороны, просто возвращает общее количество физических процессоров.
Разница особенно важна, потому что некоторые системы управления кластером, такие как Platform LSF, ограничивают использование ЦП заданием sched_getaffinity
.
Поэтому, если вы используете multiprocessing.cpu_count()
, ваш скрипт может попытаться использовать больше ядер, чем у него есть, что может привести к перегрузке и тайм-аутам.
Мы можем увидеть разницу конкретно, ограничив сродство с taskset
утилитой.
Например, если я ограничу Python только одним ядром (ядро 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(logical=False)
https://github.com/giampaolo/psutil/blob/master/INSTALL.rst
Обратите внимание, что значением по умолчанию logical
является True
, поэтому, если вы хотите включить многопоточные ядра, вы можете использовать:
psutil.cpu_count()
Это даст тот же номер, что os.cpu_count()
и multiprocessing.cpu_count()
, и ни один из которых не имеет logical
ключевое слово аргумент.
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()
Этот метод даст вам количество процессоров в системе. joblib должен быть установлен, хотя. Более подробную информацию о joblib можно найти здесь https://pythonhosted.org/joblib/parallel.html
В качестве альтернативы вы можете использовать Numberxpr пакет 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
.