IO связанные задания -> multiprocessing.pool.ThreadPool?

разница между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]

Мои вопросы:

почему «external __main __ ()» запускается каждый раз вPool?

multiprocessing.pool.ThreadPool не порождает новые процессы? Это просто создает новые темы?

Если так, то какая разница между использованиемmultiprocessing.pool.ThreadPool в отличие от простоthreading модуль?

Я не вижу официальной документации дляThreadPool где-нибудь, может кто-нибудь помочь мне, где я могу найти это?

 Arthur Tacca05 сент. 2017 г., 09:31
Создание потока может иметь такую ​​же стоимость, что и процесс, но обмен данными между потоками очень отличается от обмена данными между процессами (если, возможно, вы не использовали общую память). Кроме того, ваш комментарий о GIL верен лишь частично: он публикуется во время операций ввода-вывода и некоторыми библиотеками (например, numpy) даже во время операций с привязкой к процессору. Тем не менее, GIL в конечном итоге является причиной использования отдельных процессов в Python.
 Basic16 апр. 2018 г., 11:59
@ Yves Это может быть правдой на * nix, с помощьюfork, но это не так в Windows и не учитывает дополнительные издержки, ограничения и сложность взаимодействия между процессами в отличие от потоков (на всех платформах).
 typelogic11 июл. 2018 г., 21:15
Ответить на вопросthreading противThreadPool, вthreading не имеет простого прямого способа получить возвращаемое значение (я) рабочих функций. Принимая во внимание, что вThreadPool Вы можете легко получить возвращаемое значение (я) рабочих функций.
 Yves05 сент. 2017 г., 05:53
Как я знаю, из-за GIL в Python многопоточность Python выглядит как многопоточность, но это не реально. Если вы хотите использовать преимущества многоядерности с python, вам нужно использовать мультипроцессорность. В современном компьютере создание процесса и создание потока имеют почти одинаковую стоимость.

Ответы на вопрос(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 реализации пула.

 noxdafox07 янв. 2019 г., 18:01
Да, это. Как видно из ссылки на источник и отсутствие документации.
 noxdafox06 сент. 2017 г., 08:59
Объяснение в ссылке, которую я дал вам выше при упоминаниипорождать метод запуска. Вы можете управлять им, но доступность методов запуска зависит от платформы ОС. Я предполагаю, что вы используете Windows в качестве стратегии запуска по умолчаниюspawn один. Если так, то мало что можно сделать, так как Windows поддерживает толькоspawn.
 YongHao Hu04 мар. 2019 г., 10:20
Почему IO связанные задания -> multiprocessing.pool.ThreadPool?
 Cedric H.07 янв. 2019 г., 11:31
Является ли комментарий о незаконченной реализацииThreadPool все еще действует в 2019 году с Python 3.7?
 ozn06 сент. 2017 г., 00:05
Спасибо за ответ. Я просто хочу понять это утверждение: обратите внимание, что это происходит, только если используется метод создания процесса порождения (единственный метод, доступный в Windows). Если вы используете разветвленную вилку (Unix), вы увидите сообщение, напечатанное только один раз, как для потоков. Я предполагаю, что "spawn" и "fork" неявны, когда я вызываю "map ()" или "Pool ()"? Или это то, что я могу контролировать?

Ваш ответ на вопрос