Какая разница между ThreadPool и Pool в модуле многопроцессорности Python
В чем разница между ThreadPool
и Pool
в модуле multiprocessing
. Когда я пытаюсь выполнить код, это основное различие, которое я вижу:
from multiprocessing import Pool
import os, time
print("hi outside of main()")
def hello(x):
print("inside hello()")
print("Proccess id: ", os.getpid())
time.sleep(3)
return x*x
if __name__ == "__main__":
p = Pool(5)
pool_output = p.map(hello, range(3))
print(pool_output)
Я вижу следующий вывод:
hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
inside hello()
Proccess id: 13268
inside hello()
Proccess id: 11104
inside hello()
Proccess id: 13064
[0, 1, 4]
С "ThreadPool":
from multiprocessing.pool import ThreadPool
import os, time
print("hi outside of main()")
def hello(x):
print("inside hello()")
print("Proccess id: ", os.getpid())
time.sleep(3)
return x*x
if __name__ == "__main__":
p = ThreadPool(5)
pool_output = p.map(hello, range(3))
print(pool_output)
Я вижу следующий вывод:
hi outside of main()
inside hello()
inside hello()
Proccess id: 15204
Proccess id: 15204
inside hello()
Proccess id: 15204
[0, 1, 4]
Мои вопросы:
-
почему "внешний __main __()" запускается каждый раз в Pool
?
-
multiprocessing.pool.ThreadPool
не порождает новые процессы? Он просто создает новые потоки?
-
Если да, то в чем разница между использованием multiprocessing.pool.ThreadPool
, а не только с модулем threading
?
Я не вижу никакой официальной документации для ThreadPool
в любом месте, может кто-нибудь помочь мне, где я могу ее найти?
Ответы
Ответ 1
multiprocessing.pool.ThreadPool
ведет себя так же, как multiprocessing.Pool
, с той лишь разницей, что для выполнения рабочей логики используются потоки, а не процессы.
Причина, по которой вы видите
hi outside of main()
печатается несколько раз с multiprocessing.Pool
из-за того, что пул порождает 5 независимых процессов. Каждый процесс инициализирует свой собственный интерпретатор Python и загружает модуль, в результате чего верхний уровень print
выполняется снова.
Обратите внимание, что это происходит, только если используется метод создания процесса spawn
(только метод, доступный в Windows). Если вы используете fork
(Unix), вы увидите сообщение, напечатанное только один раз, как для потоков.
multiprocessing.pool.ThreadPool
не задокументирован, так как его реализация никогда не была завершена. Не хватает тестов и документации. Вы можете увидеть его реализацию в исходном коде.
Я считаю, что следующий естественный вопрос: когда использовать пул, основанный на потоках, а когда пул, основанный на процессах?
Основное правило:
- IO связанные задания →
multiprocessing.pool.ThreadPool
- Связанные с CPU задания →
multiprocessing.Pool
- Гибридные задания → зависит от рабочей нагрузки, я обычно предпочитаю
multiprocessing.Pool
из-за преимущества, которое дает изоляция процесса
В Python 3 вы можете взглянуть на реализации пула concurrent.future.Executor
.