Python Multiprocessing耗时更长及重复打印问题技术问询
Python多进程Pool的两个常见问题解答
问题1:为何Multiprocessing Pool处理任务耗时比串行更长?
这是因为多进程模式存在固定开销,当单个任务的计算量不足以抵消这些开销时,总耗时就会比串行更长,具体原因包括:
- Windows进程启动机制:Windows下Python多进程采用
spawn模式,启动子进程时需要重新加载整个脚本、初始化Python解释器环境,这个过程本身就会消耗额外时间。 - 进程间通信开销:Pool的
map方法需要将任务数据序列化后传递给子进程,子进程计算完成后还要将结果序列化回主进程,数据的序列化、传输过程会产生额外耗时。 - 任务粒度问题:你的测试任务(计算平方、平方根)都是极轻量的计算,并行执行节省的时间远小于进程启动和通信的开销。只有当单个任务的计算量足够大(比如复杂的数学运算、批量数据处理),或者任务是IO密集型(等待磁盘/网络响应)时,多进程的并行优势才能体现出来。
问题2:为何elapsed_time函数会产生多条重复的打印输出?
这是Windows多进程spawn模式的特性导致的:
- 当启动子进程时,系统会重新执行整个脚本代码,只有
if __name__ == '__main__'块内的代码会被子进程跳过,其他全局作用域的代码会被每个子进程重复执行。 - 你的测试代码中,
square()和serial_cube()都是直接在全局作用域调用的,没有放在if __name__ == '__main__'块内。因此每个子进程启动时,都会重新执行这些串行计算函数,进而多次调用elapsed_time打印相同内容。
修正后的示例代码片段(以补充测试为例)
from multiprocessing import Pool import time import math def elapsed_time(start_time, calling_func): delta = (time.time() - start_time) print(f"Took {round(delta/60,3)} mins {calling_func}") N = 5000000 serial_result = [] def cube(x): return math.sqrt(x) def serial_cube(): start_time = time.time() for i in range(N): serial_result.append(math.sqrt(i)) elapsed_time(start_time,"to CUBE using SERIAL method") if __name__ == "__main__": # 串行测试只在主进程执行 serial_cube() start_time = time.time() with Pool() as pool: result = pool.map(cube, range(10,N)) elapsed_time(start_time,"to CUBE using POOL")
内容的提问来源于stack exchange,提问作者The Owl
相关产品推荐
相关产品推荐

