使用Python multiprocessing并行计算函数时结果列表为空如何解决?
问题
我正在学习Python的multiprocessing模块,写了一段并行计算的代码,但运行后所有结果列表都是空的,求修正方法:
import multiprocessing as mp import time starttime = time.time() Result_1 = [] Result_2 = [] Result_3 = [] def Calculation_1(): numbers = list(range(0, 10000000)) for num in numbers: Result_1.append(num ** 0.5) def Calculation_2(): numbers = list(range(0, 10000000)) for num in numbers: Result_2.append(num ** 2) def Calculation_3(): numbers = list(range(0, 10000000)) for num in numbers: Result_3.append(num ** 3) if __name__ == "__main__": p1 = mp.Process(target = Calculation_1) p2 = mp.Process(target = Calculation_2) p3 = mp.Process(target = Calculation_3) p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() endtime = time.time() print("Time =", "{:.2f}".format((endtime - starttime) * (10 ** 3)), "ms")
原因
Python多进程的子进程拥有独立的内存空间,主进程中定义的Result_1、Result_2、Result_3列表不会被共享。子进程里的append操作只是修改了自己内存里的列表副本,主进程的原列表根本没变化,所以最终是空的。
修正方案
方案1:用Queue传递结果
Queue是多进程安全的通信工具,子进程把计算结果存入队列,主进程再取出:
import multiprocessing as mp import time starttime = time.time() def Calculation_1(queue): numbers = list(range(0, 10000000)) result = [] for num in numbers: result.append(num ** 0.5) queue.put(result) def Calculation_2(queue): numbers = list(range(0, 10000000)) result = [] for num in numbers: result.append(num ** 2) queue.put(result) def Calculation_3(queue): numbers = list(range(0, 10000000)) result = [] for num in numbers: result.append(num ** 3) queue.put(result) if __name__ == "__main__": queue1 = mp.Queue() queue2 = mp.Queue() queue3 = mp.Queue() p1 = mp.Process(target=Calculation_1, args=(queue1,)) p2 = mp.Process(target=Calculation_2, args=(queue2,)) p3 = mp.Process(target=Calculation_3, args=(queue3,)) p1.start() p2.start() p3.start() # 从队列获取结果 Result_1 = queue1.get() Result_2 = queue2.get() Result_3 = queue3.get() p1.join() p2.join() p3.join() endtime = time.time() print("Time =", "{:.2f}".format((endtime - starttime) * (10 ** 3)), "ms") print("Result_1长度:", len(Result_1))
方案2:用Manager创建共享列表
Manager可以生成跨进程共享的列表对象,子进程修改的是共享列表本身:
import multiprocessing as mp import time starttime = time.time() def Calculation_1(result_list): numbers = list(range(0, 10000000)) for num in numbers: result_list.append(num ** 0.5) def Calculation_2(result_list): numbers = list(range(0, 10000000)) for num in numbers: result_list.append(num ** 2) def Calculation_3(result_list): numbers = list(range(0, 10000000)) for num in numbers: result_list.append(num ** 3) if __name__ == "__main__": with mp.Manager() as manager: Result_1 = manager.list() Result_2 = manager.list() Result_3 = manager.list() p1 = mp.Process(target=Calculation_1, args=(Result_1,)) p2 = mp.Process(target=Calculation_2, args=(Result_2,)) p3 = mp.Process(target=Calculation_3, args=(Result_3,)) p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() endtime = time.time() print("Time =", "{:.2f}".format((endtime - starttime) * (10 ** 3)), "ms") print("Result_2长度:", len(Result_2))
方案3:用Pool简化代码(推荐)
如果任务逻辑类似,用Pool可以更简洁地管理进程和获取结果:
import multiprocessing as mp import time starttime = time.time() def calculation_task(func, start, end): numbers = list(range(start, end)) return [func(num) for num in numbers] if __name__ == "__main__": # 定义三个计算逻辑 funcs = [lambda x: x**0.5, lambda x: x**2, lambda x: x**3] range_start, range_end = 0, 10000000 with mp.Pool(processes=3) as pool: # 异步提交任务 tasks = [pool.apply_async(calculation_task, args=(func, range_start, range_end)) for func in funcs] # 收集所有结果 Result_1, Result_2, Result_3 = [task.get() for task in tasks] endtime = time.time() print("Time =", "{:.2f}".format((endtime - starttime) * (10 ** 3)), "ms") print("Result_3长度:", len(Result_3))
内容的提问来源于stack exchange,提问作者vnc89
相关产品推荐
相关产品推荐

