Это просто до времени. Windows должна порождать 4 процесса в Pool
, которые затем нужно запускать, инициализировать и готовить к потреблению с Queue
. В Windows это требует, чтобы каждый дочерний процесс повторно импортировал модуль __main__
, а для экземпляров Queue
, используемых внутри, Pool
, чтобы быть незакрашенным в каждом дочернем элементе. Это занимает нетривиальное количество времени. На самом деле, достаточно долго, когда вы оба из ваших вызовов map_async()
выполняются до того, как все процессы в Pool
будут запущены и запущены. Вы можете увидеть это, если вы добавите прослеживающую функцию запуска каждым работником в Pool
:
while maxtasks is None or (maxtasks and completed < maxtasks):
try:
print("getting {}".format(current_process()))
task = get() # This is getting the task from the parent process
print("got {}".format(current_process()))
Выход:
getting <ForkServerProcess(ForkServerPoolWorker-1, started daemon)>
got <ForkServerProcess(ForkServerPoolWorker-1, started daemon)>
process id = 5145
getting <ForkServerProcess(ForkServerPoolWorker-1, started daemon)>
got <ForkServerProcess(ForkServerPoolWorker-1, started daemon)>
process id = 5145
getting <ForkServerProcess(ForkServerPoolWorker-1, started daemon)>
result = [121]
result1 = [100]
getting <ForkServerProcess(ForkServerPoolWorker-2, started daemon)>
getting <ForkServerProcess(ForkServerPoolWorker-3, started daemon)>
getting <ForkServerProcess(ForkServerPoolWorker-4, started daemon)>
got <ForkServerProcess(ForkServerPoolWorker-1, started daemon)>
Как вы можете видеть, Worker-1
запускается и потребляет обе задачи, стоящие перед работниками 2-4 когда-либо пытались потреблять с Queue
. Если добавить sleep
вызов после создания экземпляра Pool
в основном процессе, но перед вызовом map_async
, вы увидите различные процессы обработки каждого запроса:
getting <ForkServerProcess(ForkServerPoolWorker-1, started daemon)>
getting <ForkServerProcess(ForkServerPoolWorker-2, started daemon)>
getting <ForkServerProcess(ForkServerPoolWorker-3, started daemon)>
getting <ForkServerProcess(ForkServerPoolWorker-4, started daemon)>
# <sleeping here>
got <ForkServerProcess(ForkServerPoolWorker-1, started daemon)>
process id = 5183
got <ForkServerProcess(ForkServerPoolWorker-2, started daemon)>
process id = 5184
getting <ForkServerProcess(ForkServerPoolWorker-1, started daemon)>
getting <ForkServerProcess(ForkServerPoolWorker-2, started daemon)>
result = [121]
result1 = [100]
got <ForkServerProcess(ForkServerPoolWorker-3, started daemon)>
got <ForkServerProcess(ForkServerPoolWorker-4, started daemon)>
got <ForkServerProcess(ForkServerPoolWorker-1, started daemon)>
got <ForkServerProcess(ForkServerPoolWorker-2, started daemon)>
(Обратите внимание, что дополнительные "getting
/"got"
заявления вы видите дозорные отправляются каждому процессу, чтобы изящно закрыть их).
Использование Python 3.x в Linux, я могу воспроизвести это поведение, используя контексты 'spawn'
и 'forkserver'
, но не 'fork'
. Предположительно, потому что разветвление дочерних процессов происходит намного быстрее, чем их размножение, и делает повторный импорт __main__
.
Вы используете Windows? – dano
@ dano-yes ....., – user1050619