[英]Python multiprocessing: how to limit the number of waiting processes?
使用Pool.apply_async运行大量任务(大参数)时,进程被分配并进入等待状态,等待进程数没有限制。 这最终可能会耗尽所有内存,如下例所示:
import multiprocessing
import numpy as np
def f(a,b):
return np.linalg.solve(a,b)
def test():
p = multiprocessing.Pool()
for _ in range(1000):
p.apply_async(f, (np.random.rand(1000,1000),np.random.rand(1000)))
p.close()
p.join()
if __name__ == '__main__':
test()
我正在寻找一种限制等待队列的方法,这种方式只有有限数量的等待进程,并且 Pool.apply_async 在等待队列已满时被阻塞。
multiprocessing.Pool
具有_taskqueue
类型的构件multiprocessing.Queue
,这需要一个可选maxsize
参数; 不幸的是,它在没有maxsize
参数集的情况下构建它。
我建议你继承multiprocessing.Pool
用的复制粘贴multiprocessing.Pool.__init__
是传球maxsize
到_taskqueue
构造。
猴子修补对象(池或队列)也可以,但您必须对pool._taskqueue._maxsize
和pool._taskqueue._sem
进行猴子pool._taskqueue._maxsize
,因此它会非常脆弱:
pool._taskqueue._maxsize = maxsize
pool._taskqueue._sem = BoundedSemaphore(maxsize)
如果pool._taskqueue
超过所需大小,请等待:
import multiprocessing
import time
import numpy as np
def f(a,b):
return np.linalg.solve(a,b)
def test(max_apply_size=100):
p = multiprocessing.Pool()
for _ in range(1000):
p.apply_async(f, (np.random.rand(1000,1000),np.random.rand(1000)))
while p._taskqueue.qsize() > max_apply_size:
time.sleep(1)
p.close()
p.join()
if __name__ == '__main__':
test()
这是最佳答案的猴子修补替代方案:
import queue
from multiprocessing.pool import ThreadPool as Pool
class PatchedQueue():
"""
Wrap stdlib queue and return a Queue(maxsize=...)
when queue.SimpleQueue is accessed
"""
def __init__(self, simple_queue_max_size=5000):
self.simple_max = simple_queue_max_size
def __getattr__(self, attr):
if attr == "SimpleQueue":
return lambda: queue.Queue(maxsize=self.simple_max)
return getattr(queue, attr)
class BoundedPool(Pool):
# Override queue in this scope to use the patcher above
queue = PatchedQueue()
pool = BoundedPool()
pool.apply_async(print, ("something",))
这在 Python 3.8 中按预期工作,其中多处理池使用queue.SimpleQueue
来设置任务队列。 听起来multiprocessing.Pool
的实现可能自 2.7 以来发生了变化
在这种情况下,您可以使用 maxsize 参数添加显式 Queue 并使用queue.put()
而不是pool.apply_async()
。 然后工作进程可以:
for a, b in iter(queue.get, sentinel):
# process it
如果要将内存中创建的输入参数/结果的数量限制为大约活动工作进程的数量,则可以使用pool.imap*()
方法:
#!/usr/bin/env python
import multiprocessing
import numpy as np
def f(a_b):
return np.linalg.solve(*a_b)
def main():
args = ((np.random.rand(1000,1000), np.random.rand(1000))
for _ in range(1000))
p = multiprocessing.Pool()
for result in p.imap_unordered(f, args, chunksize=1):
pass
p.close()
p.join()
if __name__ == '__main__':
main()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.