如何用同一参数并行运行多函数?遇Process/Pool困境求解决方案
解决并行运行不可修改函数并获取返回值的问题
下面是几种可行的解决方案,完全不需要修改原有算法函数:
方法1:用multiprocessing.Manager共享字典存结果(适配Process)
如果倾向于用Process手动管理进程,可以通过Manager创建跨进程共享的字典,配合顶层包装函数来转发调用并保存结果:
from multiprocessing import Process, Manager # 示例:无法修改的原有算法函数 def algo1(a, b): return a + b def algo2(x): return x * 2 # 顶层包装函数(必须放在模块全局作用域,避免pickle序列化失败) def run_algo(func, args, result_dict, key): result_dict[key] = func(*args) if __name__ == "__main__": with Manager() as manager: results = manager.dict() processes = [] # 启动进程执行算法1 p1 = Process(target=run_algo, args=(algo1, (1, 2), results, "algo1")) processes.append(p1) p1.start() # 启动进程执行算法2 p2 = Process(target=run_algo, args=(algo2, (3,), results, "algo2")) processes.append(p2) p2.start() # 等待所有进程完成 for p in processes: p.join() # 读取结果 print(results["algo1"]) # 输出3 print(results["algo2"]) # 输出6
方法2:用concurrent.futures.ProcessPoolExecutor替代标准Pool
ProcessPoolExecutor的API更简洁,直接提交原函数和参数就能避免本地对象pickle问题;如果需要绑定部分参数,用functools.partial而不是本地嵌套包装函数:
from concurrent.futures import ProcessPoolExecutor import functools # 无法修改的原有算法 def algo1(a, b): return a + b def algo2(x, y): return x * y if __name__ == "__main__": with ProcessPoolExecutor() as executor: # 直接提交原函数和参数 future1 = executor.submit(algo1, 1, 2) # 用partial固定部分参数,无需写本地包装函数 bound_algo2 = functools.partial(algo2, y=3) future2 = executor.submit(bound_algo2, x=4) # 获取返回值 res1 = future1.result() res2 = future2.result() print(res1) # 3 print(res2) # 12
如果必须写包装函数,一定要把它放在模块顶层(不要嵌套在其他函数或if __name__块内),这样标准pickle就能正常序列化。
方法3:用pathos.multiprocessing绕过pickle限制
如果你的场景必须使用本地嵌套的包装函数(比如需要引用外部作用域的变量),标准库的pickle无法处理这类对象。这时可以用pathos库——它用dill替代pickle,支持序列化更多类型的对象:
先安装依赖:
pip install pathos
使用示例:
from pathos.multiprocessing import Pool # 无法修改的原有算法 def algo1(a, b): return a + b if __name__ == "__main__": # 嵌套包装函数,标准Pool会报错,但pathos支持 def wrapper(args): return algo1(*args) with Pool() as pool: tasks = [(1,2), (3,4), (5,6)] results = pool.map(wrapper, tasks) print(results) # [3,7,11]
内容的提问来源于stack exchange,提问作者Constantin Höing
相关产品推荐
相关产品推荐

