Python多进程运行异常:耗时超串行或无限运行,疑涉VSCode/Jupyter环境
Python多进程代码异常问题分析与修复
示例1:多进程耗时异常问题
问题根源
- 计时逻辑错误:启动进程后直接结束计时,未等待子进程执行完成。
p1.start()和p2.start()仅完成进程启动操作,此时子进程仍在后台运行,记录的只是进程启动开销,而非任务执行的总耗时。 - 任务量过小:
range(20)的计算量极小,多进程的启动、调度开销远大于并行计算节省的时间,即使修正计时逻辑,也可能出现多进程耗时高于串行的情况。 - 全局变量无效:子进程会复制主进程的全局变量,
results_a和results_b在子进程中的修改不会同步到主进程,这部分结果实际无效。
修复后的代码
import multiprocessing as mp import time import math def calc_one(numbers, result_queue): results = [] for number in numbers: results.append(math.sqrt(number **4)) result_queue.put(results) def calc_two(numbers, result_queue): results = [] for number in numbers: results.append(math.sqrt(number**5)) result_queue.put(results) if __name__ == '__main__': number_list = list(range(200000)) # 增大任务量体现并行优势 # 串行计时 start = time.time() res_a = [] for num in number_list: res_a.append(math.sqrt(num**4)) res_b = [] for num in number_list: res_b.append(math.sqrt(num**5)) end = time.time() print(f"串行处理耗时: {end - start:.4f}秒") # 多进程计时 start = time.time() result_queue = mp.Queue() p1 = mp.Process(target=calc_one, args=(number_list, result_queue)) p2 = mp.Process(target=calc_two, args=(number_list, result_queue)) p1.start() p2.start() p1.join() # 等待进程执行完成 p2.join() # 获取结果 results_a = result_queue.get() results_b = result_queue.get() end = time.time() print(f"多进程处理耗时: {end - start:.4f}秒")
示例2:无限运行问题
问题根源
- 缺少必要导入:代码直接使用
Pool(),但未导入multiprocessing.Pool,需显式导入或通过mp.Pool()调用。 - 交互式环境特性:Jupyter Notebook/VSCode交互式窗口中,
__name__ == '__main__'的执行逻辑与普通脚本不同,子进程启动时会重新执行整个脚本,导致无限创建子进程(类似fork炸弹),进而出现无限运行的情况。
修复后的代码
import multiprocessing as mp import time def f(n): sum_val = 0 for x in range(10000): # 增大任务量 sum_val += x*x return sum_val if __name__ == "__main__": array = [1, 2, 3, 4, 5] # 串行计时 start = time.time() result = [f(n) for n in array] print(f"串行结果: {result}") end = time.time() print(f"串行处理耗时: {end - start:.4f}秒") # 多进程计时(适配交互式环境) start = time.time() # 使用spawn启动方式避免fork导致的重复执行问题 with mp.get_context('spawn').Pool() as p: result = p.map(f, array) print(f"多进程结果: {result}") end = time.time() print(f"多进程处理耗时: {end - start:.4f}秒")
环境注意事项
在Jupyter Notebook或VSCode交互式窗口中使用多进程时:
- 优先使用
spawn启动方式(mp.get_context('spawn')),避免fork方式导致的脚本重复执行问题。 - 建议将多进程逻辑封装成独立函数,仅在
if __name__ == '__main__'代码块中调用。
内容的提问来源于stack exchange,提问作者Anders Zhou
相关产品推荐
相关产品推荐

