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

如何将Python高内存占用包置于共享内存供其他程序导入以降低多进程内存消耗?

在多进程场景下共享Python高内存包以降低内存占用的方法

在多进程环境中,重复导入高内存占用的Python包会导致内存冗余,以下是几种实用的解决方案:

1. 利用Unix/Linux的写时复制(COW)特性

Unix类系统(Linux/macOS)的进程fork机制自带写时复制特性:父进程先导入大模块,再创建子进程,子进程会共享父进程的内存页,只有当内存页被修改时才会复制。这是最简单的共享方式,无需额外代码改造。

示例代码:

import multiprocessing
import numpy as np  # 高内存包在父进程提前导入

def worker():
    # 子进程直接使用已导入的模块,无需重复加载
    print(np.mean(np.random.rand(1000, 1000)))

if __name__ == "__main__":
    # 创建4个子进程,共享父进程中已加载的np模块内存
    processes = [multiprocessing.Process(target=worker) for _ in range(4)]
    for p in processes:
        p.start()
    for p in processes:
        p.join()

注意事项:

  • Windows系统不支持COW,该方法无效
  • 不要修改模块的全局属性(如np.some_attr = value),否则会触发内存页复制,失去共享效果

2. 使用Python内置的multiprocessing.shared_memory(3.8+)

对于需要跨进程主动共享特定数据的场景,可以利用shared_memory将模块的核心数据(如预训练模型权重、大型数组)存入共享内存区域,让子进程直接读取,避免重复加载整个包。

示例代码:

import multiprocessing
from multiprocessing import shared_memory
import pickle
import numpy as np

def init_shared_data():
    # 父进程加载大数据并序列化
    large_array = np.random.rand(2000, 2000)
    serialized_data = pickle.dumps(large_array)
    
    # 创建共享内存并写入数据
    shm = shared_memory.SharedMemory(create=True, size=len(serialized_data))
    shm.buf[:len(serialized_data)] = serialized_data
    return shm.name, len(serialized_data)

def worker(shm_name, data_size):
    # 子进程通过共享内存名称获取数据
    existing_shm = shared_memory.SharedMemory(name=shm_name)
    serialized_data = existing_shm.buf[:data_size]
    large_array = pickle.loads(serialized_data)
    
    print(f"子进程获取到的数据形状:{large_array.shape}")
    existing_shm.close()

if __name__ == "__main__":
    shm_name, data_size = init_shared_data()
    
    processes = [
        multiprocessing.Process(target=worker, args=(shm_name, data_size)) 
        for _ in range(4)
    ]
    for p in processes:
        p.start()
    for p in processes:
        p.join()
    
    # 清理共享内存
    shm = shared_memory.SharedMemory(name=shm_name)
    shm.close()
    shm.unlink()

注意事项:

  • 仅适合提取可序列化的核心数据,不适合状态复杂的模块
  • 需要自行处理序列化/反序列化的性能开销

3. 基于内存映射文件(mmap)的共享

将模块的核心数据写入磁盘文件,再通过mmap让多个进程映射该文件到内存,实现内存共享。这种方式无需占用额外的进程内存,适合超大规模数据。

示例代码:

import multiprocessing
import mmap
import pickle
import numpy as np
import os

def write_mmap_file():
    # 将大数据序列化后写入文件
    large_data = np.random.rand(3000, 3000)
    serialized_data = pickle.dumps(large_data)
    
    with open("shared_data.bin", "wb") as f:
        f.write(serialized_data)
    return len(serialized_data)

def worker(file_size):
    # 子进程映射文件到内存并读取数据
    with open("shared_data.bin", "rb") as f:
        with mmap.mmap(f.fileno(), length=file_size, access=mmap.ACCESS_READ) as mm:
            large_data = pickle.loads(mm[:file_size])
            print(f"子进程计算数据总和:{large_data.sum():.2f}")

if __name__ == "__main__":
    file_size = write_mmap_file()
    
    processes = [
        multiprocessing.Process(target=worker, args=(file_size,)) 
        for _ in range(4)
    ]
    for p in processes:
        p.start()
    for p in processes:
        p.join()
    
    # 清理临时文件
    os.unlink("shared_data.bin")

注意事项:

  • 适合数据不频繁修改的场景,修改数据会同步到磁盘
  • 首次加载存在磁盘IO开销,但后续访问直接从内存映射读取

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 15:25:13