multiprocessing.Pool with maxtasksperchild产生相等的PID

时间:2015-06-19 16:40:41

标签: python python-3.x multiprocessing pid

我需要在一个进程中运行一个函数,该函数与所有其他内存完全隔离几次。我想使用multiprocessing(因为我需要序列化来自函数的复杂输出)。我将start_method设置为'spawn'并使用带maxtasksperchild=1的池。我期望为每个任务获得不同的过程,因此看到不同的PID:

import multiprocessing
import time
import os

def f(x):
    print("PID: %d" % os.getpid())
    time.sleep(x)
    complex_obj = 5 #more complex axtually
    return complex_obj

if __name__ == '__main__':
    multiprocessing.set_start_method('spawn')
    pool = multiprocessing.Pool(4, maxtasksperchild=1)
    pool.map(f, [5]*30)
    pool.close()

然而我得到的输出是:

$ python untitled1.py 
PID: 30010
PID: 30009
PID: 30012
PID: 30011
PID: 30010
PID: 30009
PID: 30012
PID: 30011
PID: 30018
PID: 30017
PID: 30019
PID: 30020
PID: 30018
PID: 30019
PID: 30017
PID: 30020
...

因此,在每项任务之后都没有重新生成进程。是否有自动获取新PID的方法(即不为每组进程启动新池)?

2 个答案:

答案 0 :(得分:14)

您还需要在chunksize=1的调用中指定pool.map。否则,您的iterable中的多个项目将从工作进程的感知中捆绑到一个“任务”中:

import multiprocessing
import time
import os

def f(x):
    print("PID: %d" % os.getpid())
    time.sleep(x)
    complex_obj = 5 #more complex axtually
    return complex_obj

if __name__ == '__main__':
    multiprocessing.set_start_method('spawn')
    pool = multiprocessing.Pool(4, maxtasksperchild=1)
    pool.map(f, [5]*30, chunksize=1)
    pool.close()

输出现在没有重复的PID:

PID: 4912
PID: 4913
PID: 4914
PID: 4915
PID: 4938
PID: 4937
PID: 4940
PID: 4939
PID: 4966
PID: 4965
PID: 4970
PID: 4971
PID: 4991
PID: 4990
PID: 4992
PID: 4993
PID: 5013
PID: 5014
PID: 5012

答案 1 :(得分:0)

观察到在chunksize=1映射中使用Pool将使池等待完整的一轮过程结束,以开始新的过程。

with Pool(3, maxtasksperchild=1) as p:
    p.map(do_job, args_list, chunksize=1)

例如,池上方将等待所有前三个进程(例如1000,1001,1002)完成,然后开始新的回合(1003,1004,1005