Python多进程处理大数组时的内存问题解决方案咨询
我有10个长数组arr1, arr2, ..., arr10,每个数组需传入函数foo处理。每个arr是包含约1亿个浮点数的列表。我希望使用多进程实现,示例代码如下:
import multiprocessing as mp def foo(arr): # ...调用外部模块处理arr... # 返回一个浮点数 myarrays = [arr1, ..., arr10] with mp.Pool(8) as pool: result = pool.map(foo, ((arr,) for arr in myarrays)) # 我不再需要myarrays了 for res in result: # ...后续处理...
我遇到的问题(可能有误)是:8个进程的内存占用量都很高,且foo调用完成后程序似乎出现挂起。请问有没有更优的处理方式?
减少进程间数据拷贝:Python多进程在Unix/Linux下默认用
fork,会复制父进程的全部内存(包括所有10个数组),导致每个子进程都持有数组副本,内存暴增。可以改用numpy数组替代Python列表,借助multiprocessing.Array或numpy的共享内存机制传递数据,避免全量拷贝;也可以给mp.Pool设置maxtasksperchild=1,让每个进程处理完一个任务就销毁,防止内存累积。调整进程池大小:单个数组约800MB(1亿个浮点数,每个占8字节),8个进程同时运行会占用约6.4GB内存,远超很多机器的内存上限,触发频繁swap导致程序卡顿挂起。建议将进程池大小设置为和CPU核心数一致(比如4核设为4),甚至更低,避免内存过载。
提前释放父进程内存:提交任务后立即删除
myarrays并强制垃圾回收,减少父进程内存占用,避免和子进程争抢内存:
with mp.Pool(4) as pool: result = pool.map(foo, ((arr,) for arr in myarrays)) del myarrays import gc gc.collect()
改用
imap_unordered替代map:pool.map会等待所有任务完成才返回结果,若单个任务异常卡住会导致整个程序挂起。imap_unordered可以逐个返回已完成的任务结果,方便排查问题,同时内存占用更低,不会一次性加载所有输入数据。排查
foo函数的内存泄漏:如果foo调用的外部模块未正确释放内存,会导致子进程内存持续增长。可以在foo末尾手动删除arr引用,或用tracemalloc工具排查内存使用情况。
内容的提问来源于stack exchange,提问作者theQman

