len(os.sched_getaffinity(0))
это то, что вы обычно хотите
https://docs.python.org/3/library/os.html#os.sched_getaffinity
os.sched_getaffinity(0)
(добавлено в Python 3) возвращает набор доступных процессоров, учитывая системный вызов Linux sched_setaffinity
, который ограничивает, на каких процессорах процесс и его дочерние элементы могут работать.
0
означает получить значение для текущего процесса. Функция возвращает set()
разрешенных процессоров, поэтому требуется len()
.
multiprocessing.cpu_count()
, с другой стороны, просто возвращает общее количество физических процессоров.
Разница особенно важна, потому что некоторые системы управления кластером, такие как Платформа 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.