multiprocessing.Pool maxtasksperchild 产生相等的 PID
multiprocessing.Pool with maxtasksperchild produces equal PIDs
我需要 运行 进程中的一个函数,它与所有其他内存完全隔离,多次。我想为此使用 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 的自动方法(即无需为每组进程启动新池)?
您还需要在调用 pool.map
时指定 chunksize=1
。否则,从工作进程的角度来看,您的可迭代对象中的多个项目会捆绑在一起成为一个 "task":
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
观察在 Pool
映射中使用 chunksize=1
时池会等待一个完整的进程完成以启动一个新进程。
with Pool(3, maxtasksperchild=1) as p:
p.map(do_job, args_list, chunksize=1)
例如上面的pool会等到所有的前3个进程(eg 1000,1001,1002
)完成后才开始新一轮(1003,1004,1005
)
我需要 运行 进程中的一个函数,它与所有其他内存完全隔离,多次。我想为此使用 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 的自动方法(即无需为每组进程启动新池)?
您还需要在调用 pool.map
时指定 chunksize=1
。否则,从工作进程的角度来看,您的可迭代对象中的多个项目会捆绑在一起成为一个 "task":
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
观察在 Pool
映射中使用 chunksize=1
时池会等待一个完整的进程完成以启动一个新进程。
with Pool(3, maxtasksperchild=1) as p:
p.map(do_job, args_list, chunksize=1)
例如上面的pool会等到所有的前3个进程(eg 1000,1001,1002
)完成后才开始新一轮(1003,1004,1005
)