API-интерфейс многопроцессорного пула Python не работает эффективно при увеличении числа процессов и числа рабочих - PullRequest
0 голосов
/ 15 марта 2019

Я пытаюсь применить многопроцессорность для распараллеливания моего кода.У меня есть около 2000 работ , чтобы сделать.Поскольку создание 2000 одновременных процессов нецелесообразно, я использую API python multiprocessing.pool для параллелизации работы при управлении очередью задач.Я пытался создать 100 рабочих.Но потребовались часы, чтобы закончить, что не является большим преимуществом по сравнению с последовательной реализацией.У моего ноутбука 12 логических ядер.Затем я экспериментировал , увеличивая как рабочих, так и работающих одновременно .Технически, тогда на выполнение каждой работы должно уйти одно и то же время, потому что я назначаю только одну работу одному работнику каждый раз.Но я почувствовал, что время для полного процесса увеличивается, даже если рабочая нагрузка на обработанную не изменяется .Это что-то не так с API?Или я делаю это неправильно?Может ли кто-нибудь предоставить мне возможное решение для моих работ 2000 года для параллельной обработки за минимальное время с использованием Python?

PS: я не могу использовать многопоточность из-за проблемы с реализацией кода.

Мой код

inputListLen = 13
workerCount = 13
regressList = regressList[:inputListLen] # regressList has 2000 items
with Pool(processes=workerCount) as pool:
    print(pool.map(runRegressWriteStatus, regressList))

Результаты

Input List Len  | workers   | Time(seconds) 
1               | 1         | 4.5  
2               | 2         | 4.9  
3               | 3         | 5.4  
4               | 4         | 5.6  
5               | 5         | 6.3  
6               | 6         | 7.2  
7               | 7         | 8.3  
8               | 8         | 9.6  
9               | 9         | 10.0 
10              | 10        | 10.7 
11              | 11        | 11.6 
12              | 12        | 11.8 
13              | 13        | 13.3 

1 Ответ

1 голос
/ 15 марта 2019

Я думаю, что вы неправильно понимаете некоторые вещи, а предположения о нескольких вещах не совсем точны.Как я упомянул здесь Многопроцессорность Python: имея дело с 2000 процессами , количество процессов, которые вы можете фактически выполнять параллельно с multiprocessing, зависит и контролируется количеством ядер ЦП, имеющихся в вашей системе.И именно физические ядра, а не логические ядра, которые вы видите с включенной гиперпоточностью.

Таким образом, 12 логических ядер означают 6 физических ядер и 2 потока на ядро, что дает вам 12 логических ядер.Таким образом, в любой момент времени ваше ядро ​​видит 12 логических ядер и пытается запланировать 12 процессов, но система имеет только 6 физических ядер, так что происходит много переключений контекста, что приводит к тому, что это выглядит как 12 ядер, но в любой момент временив реальном времени не может быть более 6 процессов, потому что помните, что у вас есть только 6 ядер.

Во-вторых, Pool работает иначе, чем Process, тогда как с Process вы можете запускать параллельные процессывыполнять задачи, которые могут быть независимы друг от друга.

Pool имеет другое назначение: с объектом Pool вы создаете pool процессов, а затем передаете ему большую задачу / ввода затем pool делит эту большую задачу / вход на более мелкую и распределяет ее среди processes, которые могут одновременно работать с меньшим входом.

Вот очень простой пример того, как вы можете использовать pool.

import multiprocessing as mp
import time


def f(x):
    res = 0
    for i in range(x):
        res += i ** 6


if __name__ == '__main__':
    t1 = time.time()
    # MP Pool creates 4 concurrent processes and run the same function with diffrent args, to achieve the parallel computation
    po = mp.Pool(processes=4)
    res = po.map(f, range(5000))
    po.close()
    po.join()
    print('Parallel execution time taken = {}'.format(time.time() - t1))

    t2 = time.time()
    seq_res = list(map(f, range(5000)))
    print('Sequential execution time taken = {}'.format(time.time() - t2))

(py37) rbhanot@rbhanotlinux ~/home » python 7-1.mppool.py
Parallel execution time taken = 0.91422438621521
Sequential execution time taken = 2.9315543174743652
(py37) rbhanot@rbhanotlinux ~/home » 

Как видите, параллельное выполнение с pool заняло в 3 раза меньше времени, чем последовательное выполнение,

Теперь у меня есть 8 логических ядер, но только 4 физических на моей машине, и максимум мое ядро ​​может планировать только 4 процесса одновременно, поэтому создание пула из более чем 4 процессов не будет иметь никакого значения, иВот подтверждение тому.

При запуске с пулом из 7 процессов

Parallel execution time taken = 0.9177846908569336

При запуске спул из 12 процессов

Parallel execution time taken =  0.9213907718658447

при запуске с пулом из 2 процессов

Parallel execution time taken = 1.712911605834961
...