Как сделать эффективную многопроцессорность?

Я использую multiprocessing.Pool.map для параллельного запуска кода на моей рабочей станции, которая имеет 10 физических ядер (20 ядер, если я также включу логические).

Подводя итог моему коду, мне нужно провести некоторые вычисления с 2080 матрицами. Итак, я делю 2080 матриц на 130 групп, каждая из которых содержит 16 матриц.

Затем расчет этих 16 матриц распределяется по 16 ядрам (следует ли использовать только 10, поскольку у меня только 10 физических ядер?) С использованием multiprocessing.Pool.map.

Мои вопросы:

(1) Когда я отслеживаю использование ЦП в «системном мониторе» в Ubuntu, я часто обнаруживаю, что только 1 загрузка ЦП показывает 100% вместо 16 ЦП, показывающих 100% использования. 16 CPU показывают 100% использование только на короткое время. Почему это происходит? Как это улучшить?

(2) Смогу ли я сократить время вычислений, разделив 2080 матриц на 104 группы по 20 матриц в каждой, а затем распределив вычисление этих 20 матриц по 10 или 16 ядрам?

Мой фрагмент кода выглядит следующим образом:

def f(k):
    adj=np.zeros((9045,9045),dtype='bool')
    # Calculate the elements of the  matrices
    return adj

n_CPU=16
n_networks_window=16
window=int(2080/n_networks_window) #Dividing 2080 matrices into 130 segments having 16 matrices each  
for i in range(window):
    range_window=range(int(i*2080/window),int((i+1)*2080/window))
    p=Pool(processes=n_CPU)
    adj=p.map(f,range_window)
    p.close()
    p.join()
    for k in range_window:
    # Some calculations using adj
np.savetxt(') # saving the output as a txt file

Любая помощь будет действительно полезна, поскольку я впервые распараллеливаю код Python.

Спасибо.

Обновлено: Я попробовал следующие изменения в коде, и теперь он работает нормально: pool.imap_unordered (f, диапазон (2080), chunksize = 260)

2) - просто попробуйте и убедитесь.
wwii 02.05.2018 16:14

Я сделаю это. На всякий случай, если есть другая альтернатива, это сэкономит время!

user30 02.05.2018 16:16

Какая версия Python? Соответствует ли ваш процесс какому-либо из примеров в документации?

wwii 02.05.2018 16:17

Я использую 2.7.12

user30 02.05.2018 16:20

Поддержка многопроцессорности Python, вероятно, не очень сильно нарушена, но я всегда обнаруживал, что легче управлять распараллеливанием на уровне оболочек оболочки вокруг моих сценариев Python.

Grisha 02.05.2018 16:23

Я не думаю, что есть лучший способ, чем провести эксперимент. Повышение производительности за счет рабочих пулов - непростая задача. Несколько процессов действительно позволяют выйти из GIL и по-настоящему параллельное выполнение, но ваш пул будет использовать очереди для передачи входных и выходных данных между процессами, и это может замедлить работу, если вы передаете много данных. Так что универсального ответа не существует, это зависит от вашего конкретного случая.

Hannu 02.05.2018 16:24

Вы искали python multiprocessing not using all cores? Подходит ли какой-либо из вопросов и ответов вашему варианту использования или объясняет / решает вашу проблему?

wwii 02.05.2018 16:41

@wii: Две вещи, которые я узнал после прочтения других сообщений: (1) Всегда лучше запускать многопроцессорность с N-1 физическими ядрами. (2) Было предложение поместить p.join () вне цикла for ... Я должен это проверить.

user30 03.05.2018 05:13
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
8
155
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваша проблема здесь:

for i in range(window):
    # [snip]
    p=Pool(processes=n_CPU)
    adj=p.map(f,range_window)
    p.close()
    p.join()
    # [snip]

Вы создаете новый пул в каждом цикле и отправляете в него только несколько заданий. Чтобы цикл продолжался, нужно завершить несколько заданий, прежде чем можно будет выполнить больше заданий. Другими словами, вы не используете весь потенциал параллелизма.

Что вам нужно сделать, так это создать единый пул, отправить все задания, а затем, вне цикла, присоединиться:

p=Pool(processes=n_CPU)

for i in range(window):
    # [snip]
    p.map_async(f,range_window)
    # [snip]

p.close()
p.join()

Обратите внимание на использование map_async вместо map: это опять же, чтобы избежать ожидания завершения небольшой части заданий перед отправкой новых заданий.

Еще лучший подход - вызвать map / map_async только один раз, создав один объект диапазона и избегая цикла for:

with Pool(processes=n_CPU) as p:
    p.map(f, range(2080))  # This will block, but it's okay: we are
                           # submitting all the jobs at once

Что касается вашего вопроса о количестве используемых процессоров, прежде всего обратите внимание, что Pool будет использовать все доступные процессоры (по умолчанию возвращается os.cpu_count(), если вы не укажете аргумент processes - попробуйте.

Мне непонятно, что вы имеете в виду под 10 физическими ядрами и 20 логическими. Если вы говорите о гиперпоточности, тогда ничего страшного: используйте их все. Если вместо этого вы говорите, что используете виртуальную машину с большим количеством виртуальных процессоров, чем хост-процессоры, то использование 20 вместо 10 не будет иметь большого значения.

Большое спасибо. Я попробую ваши предложения и дам вам знать через несколько дней.

user30 10.05.2018 07:13

Другие вопросы по теме