You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python使用multiprocessing.Pool处理大字符串时如何降低内存占用

内存占用过高的核心原因

你通过pool.map传递大字符串作为参数时,multiprocessing会将每个参数序列化(pickle)后分发到子进程,子进程反序列化后会生成独立的字符串副本。按你的参数写法,32个进程每个持有3GB副本,仅字符串就占用96GB,再加上处理过程的临时内存、主进程开销,很容易占满128GB内存,无规律OOM是因为Python垃圾回收时机不固定导致的内存峰值波动。

降低内存开销的可行方案
  • 不要把大字符串作为任务参数传递
    你通过任务队列传参必然会产生多份拷贝,最优方案是避免传参:
    1. Linux系统可以利用默认fork启动模式的写时复制特性,直接把大字符串设为主进程的全局变量,子进程直接读取全局变量即可,只要不修改字符串就不会产生额外内存拷贝,实现成本最低。
    2. 跨平台场景可以把大字符串放到只读共享内存中,所有子进程直接读取同一块内存,不会产生额外拷贝。Python 3.8+可以用multiprocessing.shared_memory实现,更低版本可以用mmap映射只读文件实现类似效果。
  • 调整Pool的使用逻辑
    1. 进程数不要直接拉满32核,建议设置为20~24,预留足够内存空间承载处理过程中的临时变量
    2. 不要用pool.map,换成pool.imap或者pool.imap_unordered,设置chunksize=1,避免一次性把所有参数加载到任务队列中占用额外内存
    3. 每轮任务执行完成后,立刻调用pool.close() + pool.join()销毁所有子进程,子进程占用的所有内存会直接释放给系统,避免多轮任务的内存堆积
  • 手动释放无用内存是有效的
    子进程的处理函数中,完成字符串操作后,立刻用del a_string删除大对象,再显式调用gc.collect()触发垃圾回收。对于3GB这种级别的大对象,删除后内存会立刻归还给系统,能大幅降低峰值内存占用。
优化后代码参考(Linux fork模式最简版)
import gc
from multiprocessing import Pool

# 大字符串直接设为主进程全局变量,子进程fork后共享,只读无额外拷贝
the_string = 'ababba' #实际场景中为超长字符串

def doSomethingToString(_):
    # 直接读取全局的the_string即可,不需要通过参数传递
    # 加载字符串并执行相关操作 
    res = 1
    # 处理完手动释放
    global the_string
    del the_string
    gc.collect()
    return res

if __name__ == '__main__':
    # 用上下文管理器自动管理pool生命周期
    with Pool(processes=24) as pool:
        # 传占位符即可,不需要传递大字符串
        input_list = [None]*24
        for result in pool.imap(doSomethingToString, input_list, chunksize=1):
            # 处理返回结果
            pass

内容的提问来源于stack exchange,提问作者GTOgod

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 13:45:05