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

Python multiprocessing Pool搭配shared_memory使用的相关问题咨询

Python multiprocessing Pool结合shared_memory使用问题解答

基础概念解答

memory view是不是指针?

不是C语言层面的原生指针,它是Python对缓冲区协议的封装,作用是允许你直接访问对象的底层内存数据,不需要做全量内存拷贝。SharedMemory的buf属性就是指向共享内存块的memory view,直接作为numpy数组的buffer参数传入,就能让numpy数组直接使用共享内存作为数据存储,没有额外拷贝开销。

关于Python对象跨进程共享的猜想是否正确?

你的猜想基本成立:numpy数组c是进程内的Python对象,本身无法跨进程直接使用。不过这和GIL无关,GIL是单个进程内多线程的全局解释器锁,跨进程时每个进程有完全独立的地址空间,不管有没有GIL,进程内的Python对象都不能直接被其他进程访问。只有共享内存块本身是跨所有进程可见的,你需要在每个进程中单独创建numpy数组来包装同一块共享内存。

你代码报错的核心原因

  1. 你使用了全局变量existing_shm、a,在Windows、macOS默认的spawn进程启动模式下,子进程不会继承主进程的全局变量,运行时会直接报NameError。
  2. 没有把共享内存的名称、数组形状、数据类型等必要参数传递给子进程的工作函数,子进程无法自行打开共享内存。
  3. 主进程没有把原始数组的数据拷贝到共享内存中,初始状态下共享内存是无意义的随机值。
  4. 没有做共享内存的释放操作,会造成系统内存泄漏。

修正后的可运行代码

首先导入依赖:

import os
import numpy as np
from multiprocessing import Pool, shared_memory

工作函数不能依赖全局变量,所有必要参数通过传参获取:

def test_function(args):
    shm_name, arr_shape, arr_dtype = args
    # 子进程内单独打开共享内存
    current_shm = shared_memory.SharedMemory(name=shm_name)
    # 子进程内单独创建numpy数组包装共享内存,无额外内存拷贝
    c = np.ndarray(arr_shape, dtype=arr_dtype, buffer=current_shm.buf)
    c[1] = 100
    print(c)
    # 关闭当前进程的共享内存连接
    current_shm.close()

主逻辑必须放在if __name__ == '__main__'块中,这是multiprocessing模块的强制要求,避免spawn模式下无限递归创建子进程:

if __name__ == '__main__':
    # 原始数组,明确指定dtype避免后续类型不匹配
    original_arr = np.array([1, 1, 2, 3, 5, 8], dtype=np.int64)
    # 创建共享内存
    shm = shared_memory.SharedMemory(create=True, size=original_arr.nbytes)
    # 主进程先把原始数组数据拷贝到共享内存中
    main_shm_arr = np.ndarray(original_arr.shape, dtype=original_arr.dtype, buffer=shm.buf)
    main_shm_arr[:] = original_arr[:]
    
    # 构造传给每个子进程的参数
    task_params = [(shm.name, original_arr.shape, original_arr.dtype) for _ in range(12)]
    
    with Pool(os.cpu_count()) as pool:
        pool.map(test_function, task_params)
    
    # 所有任务执行完成后,主进程关闭并销毁共享内存
    shm.close()
    shm.unlink()

常见疑问明确

  • 主进程创建shm后不需要额外创建existing_shm实例,直接使用shm即可。
  • 每个进程必须单独创建自己的numpy数组对象包装共享内存,这个操作开销极低,不会额外复制数据,只是创建了一个指向共享内存的Python包装对象。
  • 所有多进程相关的主逻辑必须放在if __name__ == '__main__'块中,否则在非fork模式的系统上会直接报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 11:42:03