Многопроцессорность Python становится медленнее с дополнительным процессоромPython

Программы на Python
Ответить
Anonymous
 Многопроцессорность Python становится медленнее с дополнительным процессором

Сообщение Anonymous »

Я пытаюсь распараллелить код, который должен быть до неприличия параллельным, но кажется, что чем больше процессов я использую, тем медленнее он становится. Вот минимально (dys)функциональный пример:

Код: Выделить всё

import os
import time
import random
import multiprocessing
from multiprocessing import Pool, Manager, Process

import numpy as np
import pandas as pd

def pool_func(
number: int,
max_number: int
) -> dict:

pid = str(multiprocessing.current_process().pid)

print('[{:2d}/{:2d} {:s}] Starting ...'.format(number, max_number, pid))
t0 = time.time()
# # the following takes ~10 seconds on a separate node
# for i in range(2):
#     print('[{:d}] Passed loop {:d}/2...'.format(number, i+1))
#     time.sleep(5)

# the following takes ~3.3 seconds on a separate node
n = 1000
for _ in range(50):
u = np.random.randn(n, n)
v = np.linalg.inv(u)

t1 = time.time()
print('[{:2d}/{:2d} {:s}] Finished in {:.1f} seconds.'.format(number, max_number, pid, t1 - t0))
return {}

if __name__ == "__main__":
runs = []
count = 0
while count < 50:
runs.append(
(count, 50)
)
count += 1

print(f"Number of runs to perform: {len(runs):d}")

num_cpus = 4
print(f"Running job with {num_cpus:d} CPUs in parallel ...")

# with Pool(processes=num_cpus) as pool:
with multiprocessing.get_context("spawn").Pool(processes=num_cpus) as pool:
results = pool.starmap(pool_func, runs)

print('Main process done.')
Я хочу отметить три особенности. Во-первых, можно изменить num_cpus, чтобы увеличить количество воркеров в пуле. Во-вторых, я могу перейти от пула «вилки» по умолчанию к методу «spawn», похоже, это ничего не меняет. Наконец, внутри Pool_func запущенный процесс может представлять собой либо инверсию матрицы с интенсивным использованием ЦП, либо функцию ожидания при отсутствии ЦП.
Когда я использую функцию ожидания, процессы выполняются примерно за правильное время, около 10 секунд на процесс. Когда я использую инверсию матрицы, время процесса увеличивается с увеличением количества процессов следующим приблизительным образом:

Код: Выделить всё

1 CPU :  3 seconds
2 CPUs:  4 seconds
4 CPUs: 30 seconds
8 CPUs: 95 seconds
Вот частичный вывод приведенного выше сценария, запущенного как есть:

Код: Выделить всё

Number of runs to perform: 50
Running job with 4 CPUs in parallel ...
[ 0/50 581194] Starting ...
[ 4/50 581193] Starting ...
[ 8/50 581192] Starting ...
[12/50 581191] Starting ...
[ 0/50 581194] Finished in 24.7 seconds.
[ 1/50 581194] Starting ...
[ 4/50 581193] Finished in 29.3 seconds.
[ 5/50 581193] Starting ...
[12/50 581191] Finished in 30.3 seconds.
[13/50 581191] Starting ...
[ 8/50 581192] Finished in 32.2 seconds.
[ 9/50 581192] Starting ...
[ 1/50 581194] Finished in 26.9 seconds.
[ 2/50 581194] Starting ...
[ 5/50 581193] Finished in 30.3 seconds.
[ 6/50 581193] Starting ...
[13/50 581191] Finished in 30.8 seconds.
[14/50 581191] Starting ...
[ 9/50 581192] Finished in 32.8 seconds.
[10/50 581192] Starting ...
...
Идентификаторы процессов кажутся мне уникальными.
Очевидно, что существует некоторая проблема с масштабированием, поскольку добавление большего количества процессоров приводит к замедлению работы процессов. В синхронизируемых процессах вообще нет ввода-вывода. Это рутинные процессы, которые, как я ожидал, будут работать прямо из коробки. Я понятия не имею, почему это не работает так, как я думаю. Почему в этом сценарии есть отдельные процессы, которые занимают больше времени, когда я использую больше процессоров?
Когда я запускаю его на своем ноутбуке Macos, он работает как положено. Но у меня есть аналогичные проблемы с масштабированием на другом удаленном компьютере с Linux, к которому у меня есть доступ. Возможно, это проблема конкретной платформы, но я оставлю ее в стороне на случай, если кто-то видел ее раньше и знает, как ее исправить.

Подробнее здесь: https://stackoverflow.com/questions/792 ... ional-cpus
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»