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

为何Python多进程队列会因返回值差异产生死锁?

进程间Queue传递大数据导致死锁的解决方案

问题原因分析

你遇到的死锁确实是因为f函数生成的数据量过大导致的:
每个元素是一个包含50000维numpy数组和浮点数的元组,10000个这样的元素总数据量远超multiprocessing.Queue的内部缓冲区上限。子进程执行q.put()时,缓冲区被占满后会进入阻塞状态,而主进程在q.get()时只能拿到部分数据,剩下的数据因为子进程阻塞无法继续写入,最终双方互相等待形成死锁。之前尝试交换get()和join()顺序或移除join()没用,是因为子进程根本没完成put()操作,一直卡在那里。

进程间传递大数据的标准方案

1. 使用Manager.Queue替代原生Queue

multiprocessing.Manager()创建的Queue由独立的管理进程托管,缓冲区限制更小,能处理更大规模的数据传输:

import time
from multiprocessing import Process, Manager
import numpy as np

def f(q):
    q.put([(np.random.rand(50000), 0.993) for _ in range(10000)])

def g(q):
    time.sleep(3)
    q.put('X' * 100000)

if __name__ == '__main__':
    # 使用Manager的Queue
    with Manager() as manager:
        queue = manager.Queue()
        p = Process(target=g, args=(queue,))
        p.start()
        obj = queue.get()
        p.join()
        print("Done g")
        print(obj[:10])  # 只打印前10个字符避免刷屏

        queue = manager.Queue()
        p = Process(target=f, args=(queue,))
        p.start()
        obj = queue.get()
        p.join()
        print("Done f")
        print(f"数据长度: {len(obj)}, 第一个数组形状: {obj[0][0].shape}")

2. 用共享内存传递numpy数组(推荐)

对于numpy这类数值型数据,使用共享内存可以避免序列化/反序列化的开销,直接在进程间共享内存区域,效率更高:

import time
from multiprocessing import Process
import numpy as np
from multiprocessing import shared_memory

def f(shm_name, shape, dtype):
    # 连接到已创建的共享内存
    existing_shm = shared_memory.SharedMemory(name=shm_name)
    # 创建共享内存对应的numpy数组
    arr = np.ndarray(shape, dtype=dtype, buffer=existing_shm.buf)
    # 填充数据
    arr[:] = np.random.rand(*shape)
    # 关闭共享内存连接
    existing_shm.close()

if __name__ == '__main__':
    # 定义数据形状和类型
    shape = (10000, 50000)
    dtype = np.float64
    # 创建共享内存
    shm = shared_memory.SharedMemory(create=True, size=np.prod(shape)*dtype.itemsize)
    # 创建主进程侧的numpy数组
    main_arr = np.ndarray(shape, dtype=dtype, buffer=shm.buf)
    
    p = Process(target=f, args=(shm.name, shape, dtype))
    p.start()
    p.join()
    
    # 使用数据
    print(f"共享内存数组形状: {main_arr.shape}")
    print(f"第一个元素值: {main_arr[0][0]}")
    
    # 释放共享内存
    shm.close()
    shm.unlink()

注:如果需要传递元组(数组+浮点数),可以额外用一个小Queue传递浮点数,或者再创建一块共享内存存储浮点数数组。

3. 磁盘文件中转(超大规模数据)

如果数据大到内存无法容纳,可以将数据写入临时文件,主进程读取文件内容:

import time
from multiprocessing import Process
import numpy as np
import tempfile

def f(temp_file_path):
    data = [(np.random.rand(50000), 0.993) for _ in range(10000)]
    # 保存数据到临时文件(用numpy的savez更高效)
    np.savez(temp_file_path, arrays=np.array([x[0] for x in data]), scores=np.array([x[1] for x in data]))

if __name__ == '__main__':
    with tempfile.NamedTemporaryFile(delete=False) as tmp:
        temp_path = tmp.name
    
    p = Process(target=f, args=(temp_path,))
    p.start()
    p.join()
    
    # 读取数据
    loaded = np.load(temp_path)
    arrays = loaded['arrays']
    scores = loaded['scores']
    print(f"加载的数组形状: {arrays.shape}, 分数长度: {len(scores)}")
    
    # 删除临时文件
    import os
    os.unlink(temp_path)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:05:27