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

FastAPI中使用multiprocessing Pipe实现Keras模型推理遇通信问题

问题原因

当你用uvicorn启动FastAPI服务时,默认会根据CPU核心数创建多个工作进程处理请求。你在全局定义的pipe_p会在每个工作进程中被重新初始化,而子进程只和启动uvicorn的主进程的Pipe端建立了连接。API请求是在uvicorn的工作进程中处理的,这里的pipe_p和子进程监听的不是同一个管道,所以子进程收不到数据。

解决方案

方案一:强制uvicorn单进程启动

如果不需要多进程处理API请求,最简单的方式是指定uvicorn只启动1个工作进程,这样全局Pipe能和子进程正常通信:

修改主服务的启动代码:

if __name__ == "__main__":
    p = Process(target=main, args=(pipe_c, model_type, model_name))
    p.start()
    uvicorn.run("main:app", port=port, host=host, workers=1)  # 新增workers=1参数

方案二:使用Manager共享管道(多进程场景推荐)

如果需要多进程处理API请求,用multiprocessing.Manager创建可跨进程共享的Pipe,确保所有uvicorn工作进程都能访问同一个通信管道:

主服务代码调整:

from multiprocessing import Process, Manager
from multiprocessing.connection import PipeConnection

app = FastAPI()
pipe_p = None  # 全局变量,后续通过Manager初始化

@app.post("/api/test", response_model=MyResponse)
async def test(req:MyDataModel= Body(example=c.INFOEXAMPLE)):
    global pipe_p
    pipe_p.send(req)
    result = pipe_p.recv()
    return {
        "data": f"inference result: {result}"
    }

if __name__ == "__main__":
    with Manager() as manager:
        pipe_p, pipe_c = manager.Pipe()
        p = Process(target=main, args=(pipe_c, model_type, model_name))
        p.start()
        uvicorn.run("main:app", port=port, host=host)

方案三:改用Queue替代Pipe

multiprocessing.Queue是线程和进程安全的,更适合多生产者(API请求)多消费者(推理子进程)的场景,代码调整更直观:

主服务代码

from multiprocessing import Process, Queue

app = FastAPI()
request_queue = None
response_queue = None

@app.post("/api/test", response_model=MyResponse)
async def test(req:MyDataModel= Body(example=c.INFOEXAMPLE)):
    global request_queue, response_queue
    request_queue.put(req)
    result = response_queue.get()
    return {
        "data": f"inference result: {result}"
    }

if __name__ == "__main__":
    request_queue = Queue()
    response_queue = Queue()
    p = Process(target=main, args=(request_queue, response_queue, model_type, model_name))
    p.start()
    uvicorn.run("main:app", port=port, host=host)

子进程代码

def main(request_queue, response_queue, model_type:str, model_name:str):
    model = load_model(model_type)(model_name)

    while True:
        print("waiting...")
        data = request_queue.get()
        print(f"received {data}")
        if data == "kill":
            return
        if data == "test":
            print(data)
            continue
        result = model(data)
        response_queue.put(result)
注意事项
  • 确保传递给子进程的请求数据是可序列化的(multiprocessing依赖pickle序列化,Keras模型的输入数据要符合序列化要求)
  • 模型必须在子进程内部加载,不要在主进程加载后传递给子进程(Keras模型跨进程传递会出现兼容性问题)
  • 多进程场景下,避免用普通全局变量存储通信管道/队列,必须用进程间共享机制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 22:20:27