如何避免其他进程运行时Whisper模型推理速度过慢
解决方案
1. 限制PyTorch线程数,避免内部资源竞争
Whisper依赖的PyTorch默认会启用多线程并行计算,当Flask开启多线程时,多个推理请求的PyTorch线程会抢占CPU资源,导致单请求推理速度暴跌。你可以在模型加载前强制限制PyTorch的线程数,让每个推理任务只使用固定数量的线程:
import torch # 在全局初始化/模型加载前执行 torch.set_num_threads(1) torch.set_num_interop_threads(1)
或者通过环境变量设置(启动Flask服务前执行):
export OMP_NUM_THREADS=1 export MKL_NUM_THREADS=1
这样每个推理任务的计算资源被隔离,不会和其他请求的推理线程互相抢占。
2. 预加载模型+单实例复用,避免重复加载开销
不要在每个请求里加载模型,启动Flask时就把Whisper模型加载到全局变量中,所有请求共用同一个模型实例。同时用锁控制推理环节的串行执行,确保同一时间只有一个请求在使用模型,既节省加载时间,也避免多实例的资源冲突:
from flask import Flask, request import whisper import threading app = Flask(__name__) # 全局模型实例 model = None # 推理锁,保证同一时间仅一个请求执行推理 inference_lock = threading.Lock() @app.before_first_request def load_model(): global model torch.set_num_threads(1) model = whisper.load_model("base") @app.route("/transcribe", methods=["POST"]) def transcribe(): # 多线程并行处理请求解析等非推理逻辑 audio_file = request.files["audio"] audio_file.save("temp.wav") # 抢占锁,进入串行推理环节 with inference_lock: result = model.transcribe("temp.wav") # 多线程并行处理响应逻辑 return {"text": result["text"]}
3. 优先级队列+独立工作线程,分离请求接收与推理
保留Flask多线程接收请求,把请求按优先级放入队列,由一个独立的工作线程负责从队列中取出最高优先级的请求执行推理。这样既保证优先级队列生效,又让推理环节始终串行,避免多线程推理的速度问题:
from flask import Flask, request import whisper import threading from queue import PriorityQueue app = Flask(__name__) model = whisper.load_model("base") # 优先级队列,元素格式:(优先级数值, 请求标识, 音频路径, 结果回调) request_queue = PriorityQueue() # 工作线程运行标志 running = True def worker(): torch.set_num_threads(1) while running: # 取出最高优先级请求(数值越小优先级越高,可按需调整) priority, req_id, audio_path, callback = request_queue.get() try: result = model.transcribe(audio_path) callback(result) finally: request_queue.task_done() # 启动后台工作线程 threading.Thread(target=worker, daemon=True).start() @app.route("/transcribe", methods=["POST"]) def transcribe(): # 从请求头获取优先级,默认值为5 priority = int(request.headers.get("X-Priority", 5)) audio_file = request.files["audio"] audio_path = f"temp_{threading.get_ident()}.wav" audio_file.save(audio_path) # 用事件等待推理结果 result_event = threading.Event() result = None def callback(res): nonlocal result result = res result_event.set() # 将请求放入优先级队列 request_queue.put((priority, id(audio_path), audio_path, callback)) result_event.wait() return {"text": result["text"]}
4. 用单进程处理推理,彻底隔离CPU资源
如果是CPU推理场景,用单进程代替线程处理推理可以彻底避免GIL和PyTorch线程的竞争问题。你可以用multiprocessing创建一个单独的推理进程,Flask多线程接收请求后把任务发给这个进程:
from flask import Flask, request import whisper import multiprocessing app = Flask(__name__) # 进程间通信的任务队列和结果队列 task_queue = multiprocessing.Queue() result_queue = multiprocessing.Queue() def inference_process(): torch.set_num_threads(1) model = whisper.load_model("base") while True: priority, req_id, audio_path = task_queue.get() result = model.transcribe(audio_path) result_queue.put((req_id, result)) # 启动独立推理进程 multiprocessing.Process(target=inference_process, daemon=True).start() @app.route("/transcribe", methods=["POST"]) def transcribe(): priority = int(request.headers.get("X-Priority", 5)) audio_file = request.files["audio"] audio_path = f"temp_{multiprocessing.current_process().pid}.wav" audio_file.save(audio_path) req_id = id(audio_path) task_queue.put((priority, req_id, audio_path)) # 等待对应请求的推理结果 while True: res_id, result = result_queue.get() if res_id == req_id: break return {"text": result["text"]}
内容的提问来源于stack exchange,提问作者Høax
相关产品推荐
相关产品推荐

