这是一个使用 multiprocessing 调用 2 个或更多函数并返回最快结果的示例。但是,有一些重要的事情需要注意。
- 在 IDLE 中运行
multiprocessing 代码有时会导致问题。此示例有效,但我在尝试解决此问题时确实遇到了该问题。
- 多处理代码应该从
if __name__ == '__main__' 子句内部开始,否则如果主模块被另一个进程重新导入,它将再次运行。阅读多处理文档页面了解更多信息。
- 结果队列直接传递给使用它的每个进程。当您通过引用模块中的全局名称来使用队列时,代码在 Windows 上会失败,因为每个进程都使用队列的新实例。在此处阅读更多信息Multiprocessing Queue.get() hangs
我还在这里添加了一点功能,可以知道实际使用了哪个进程的结果。
import multiprocessing as mp
import time
import random
def task(value):
# our dummy task is to sleep for a random amount of time and
# return the given arg value
time.sleep(random.random())
return value
def process(q, idx, fn, args):
# simply call function fn with args, and push its result in the queue with its index
q.put([fn(*args), idx])
def fastest(calls):
queue = mp.Queue()
# we must pass the queue directly to each process that may use it
# or else on Windows, each process will have its own copy of the queue
# making it useless
procs = []
# create a 'mp.Process' that calls our 'process' for each call and start it
for idx, call in enumerate(calls):
fn = call[0]
args = call[1:]
p = mp.Process(target=process, args=(queue, idx, fn, args))
procs.append(p)
p.start()
# wait for the queue to have something
result, idx = queue.get()
for proc in procs: # kill all processes that may still be running
proc.terminate()
# proc may be using queue, so queue may be corrupted.
# https://docs.python.org/3.8/library/multiprocessing.html?highlight=queue#multiprocessing.Process.terminate
# we no longer need queue though so this is fine
return result, idx
if __name__ == '__main__':
from datetime import datetime
start = datetime.now()
print(start)
# to be compatible with 'fastest', each call is a list with the first
# element being callable, followed by args to be passed
calls = [
[task, 1],
[task, 'hello'],
[task, [1,2,3]]
]
val, idx = fastest(calls)
end = datetime.now()
print(end)
print('elapsed time:', end-start)
print('returned value:', val)
print('from call at index', idx)
示例输出:
2019-12-21 04:01:09.525575
2019-12-21 04:01:10.171891
elapsed time: 0:00:00.646316
returned value: hello
from call at index 1