3 Multiprocessing.Pool

На вопрос, как использовать потоки в Python, ответ прост: «Не используйте вместо этого процессы». Модуль многопроцессорной обработки позволяет создавать процессы с синтаксисом, аналогичным синтаксису создания потоков, но я предпочитаю использовать их удобный объект Pool.

Используя код , который Дэвид Бизли первым используется , чтобы показать опасность нитей против GIL , мы перепишем его с помощью multiprocessing.Pool :

Код Дэвида Бизли, который показал проблемы с GIL-потоками

 from threading import Thread
import time
def countdown(n):
    while n > 0:
        n -= 1

COUNT = 10000000

t1 = Thread(target=countdown,args=(COUNT/2,))
t2 = Thread(target=countdown,args=(COUNT/2,))
start = time.time()
t1.start();t2.start()
t1.join();t2.join()
end = time.time()
print end-start

 

Переписано с использованием мультипроцессинга.
 import multiprocessing
import time
def countdown(n):
    while n > 0:
        n -= 1

COUNT = 10000000

start = time.time()
with multiprocessing.Pool as pool:
    pool.map(countdown, [COUNT/2, COUNT/2])

    pool.close()
    pool.join()

end = time.time()
print(end-start)

 

Вместо создания потоков это создает новые процессы. Поскольку каждый процесс имеет свой собственный интерпретатор, коллизии GIL отсутствуют. multiprocessing.Pool откроет столько процессов, сколько имеется ядер на машине, хотя в приведенном выше примере потребуется только два. В реальном сценарии вы хотите, чтобы ваш список был как минимум такой же длины, как и процессоры на вашей машине. Пул будет запускать функцию, которую вы скажете ему запускать с каждым аргументом, вплоть до числа процессов, которые он создает. Когда функция завершится, все остальные функции в списке будут запущены в этом процессе.

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