Многопроцессорная обработка не имеет смысла в контексте, который вы здесь представляете.Вы создаете пять подпроцессов (и три потока, принадлежащих пулу, управляющих рабочими, задачами и результатами) для выполнения одна функция один раз .Все это обходится дорого, как в системных ресурсах, так и во времени выполнения, в то время как четыре ваших рабочих процесса вообще ничего не делают.Многопроцессорная обработка не ускоряет выполнение функции.Код в вашем конкретном примере всегда будет медленнее, чем просто выполнение Main_Residence(20, 50, 50)
в основном процессе.
Чтобы многопроцессорная обработка имела смысл в таком контексте, ваша работа под рукой должна быть разбитак набору однородных задач, которые могут быть обработаны параллельно с их результатами, которые впоследствии могут быть объединены.
В качестве примера (не обязательно хорошего), если вы хотите вычислить наибольшие простые факторы для последовательностичисла, вы можете делегировать задачу расчета этого фактора для любого конкретного числа работнику в пуле.Затем несколько рабочих будут выполнять эти отдельные вычисления параллельно:
def largest_prime_factor(n):
p = n
i = 2
while i * i <= n:
if n % i:
i += 1
else:
n //= i
return p, n
if __name__ == '__main__':
pool = Pool(processes=3)
start = datetime.now()
# this delegates half a million individual tasks to the pool, i.e.
# largest_prime_factor(0), largest_prime_factor(1), ..., largest_prime_factor(499999)
pool.map(largest_prime_factor, range(500000))
pool.close()
pool.join()
print "pool elapsed", datetime.now() - start
start = datetime.now()
# same work just in the main process
[largest_prime_factor(i) for i in range(500000)]
print "single elapsed", datetime.now() - start
Вывод:
pool elapsed 0:00:04.664000
single elapsed 0:00:08.939000
(функция largest_prime_factor
взята из @ Stefan in этот ответ )
Как видите, пул всего лишь примерно в два раза быстрее, чем выполнение одного процесса с одинаковым объемом работы, при одновременном выполнении трех процессов параллельно.Это связано с накладными расходами, вызванными многопроцессорностью / пулом.
Итак, вы заявили, что код в вашем примере был упрощен.Вам придется проанализировать исходный код, чтобы выяснить, можно ли его разбить на однородные задачи, которые можно передать в пул для обработки.Если это возможно, использование многопроцессорной обработки может помочь вам ускорить вашу программу.В противном случае многопроцессорная обработка, скорее всего, будет стоить вам времени, а не сэкономит.
Редактировать:
Поскольку вы запросили предложения по коду.Я едва могу сказать что-нибудь о твоей функции.Вы сами сказали, что это просто упрощенный пример предоставления MCVE (кстати, это высоко ценится! Большинство людей не тратят время, чтобы сократить свой код до минимума).Запросы на проверку кода в любом случае лучше подходят для Codereview .
Немного поэкспериментируйте с доступными методами делегирования задач.В моем главном примере фактора использование apply_async
сопровождалось массивным штрафомВремя выполнения увеличилось в девять раз по сравнению с использованием map
.Но мой пример использует простую итерацию, для вашей задачи требуется три аргумента.Это может иметь место для starmap
, но это доступно только в Python 3.3.
В любом случае, структура / характер данных вашей задачи в основном определяет правильный метод для использования.
Я провел некоторое тестирование вопросов и ответов смногопроцессорность вашего примера функции.Входные данные были определены следующим образом:
inp = [(20, 50, 50)] * 5000 # that makes 5000 tasks against your Main_Residence
Я запустил это в Python 3.6 в трех подпроцессах с неизменной вашей функцией, за исключением удаления print
статута (ввод-вывод является дорогостоящим).Я использовал starmap
, apply
, starmap_async
и apply_async
, а также просматривал результаты каждый раздля учета блокировки get()
в асинхронных результатах.
Вот вывод:
starmap elapsed 0:01:14.506600
apply elapsed 0:02:11.290600
starmap async elapsed 0:01:27.718800
apply async elapsed 0:01:12.571200
# btw: 5k calls to Main_Residence in the main process looks as bad
# as using apply for delegation
single elapsed 0:02:12.476800
Как видите, время выполнения различается, хотя все четыре метода выполняют одинаковую работу;apply_async
выбранный вами, кажется, самый быстрый метод.
Стиль кодирования.Ваш код выглядит довольно ... нетрадиционно :) Вы используете Capitalized_Words_With_Underscore для своих имен (как для имен функций, так и для переменных), что в Python практически невозможно.Кроме того, присвоение имени Previous_List
словарю ... сомнительно.Посмотрите PEP 8 , особенно раздел Соглашения об именах , чтобы увидеть общепринятый стиль кодирования для Python.
Судя по тому, как выглядит print
, вы все еще используете Python 2. Я знаю, что в корпоративной или институциональной среде это иногда все, что у вас есть.Тем не менее, имейте в виду, что часы для Python 2 тикают