快速结论:当单个 /v1/embeddings 请求里出现“短输入 + 需要截断的长输入”时,vLLM 会把 [Bug]: /v1/embeddings deadlocks when a truncated input follows a short one in the same request 表现为请求卡死、GPU 空闲、只有 Running: N reqs, Waiting: 0 reqs,优先排查 pooling 请求在 chunked prefill 下的调度器活性问题,而不是先怀疑 CUDA 或显卡故障。
适用环境:Issue 已确认环境为 vLLM 0.28.0(vllm/vllm-openai:v0.28.0)、NVIDIA RTX 3080 Ti(12 GiB)、驱动 580.173.02、Ubuntu、kernel 7.0.0-31-generic,模型 Qwen3-Embedding-4B bf16,启动参数 --runner pooling --convert embed;同版本 ROCm gfx1151 构建未复现。压缩张量 W4A16 版本也复现过。
最快修复方案:暂无确认的一步修复方案。Issue 中明确验证过的是该问题为 V1 调度器活性缺陷;可优先尝试降低并发、让每个请求不触发 chunked prefill,或避免 pooling 请求的 prompt 长度等于 max_model_len 后被分块,但这些都属于规避思路,Issue 未给出已验证的配置修复。
注意事项:提高 --max-num-batched-tokens 在 12 GiB 显卡上不可用,24576 和 65536 均在启动时 OOM;关闭编译缓存、调整批大小、怀疑 GPU 故障都没有解决问题。该问题只在 CUDA 路径复现,ROCm 构建未复现,因此不要直接套用到所有后端。
问题场景
用户用 vLLM 启动 OpenAI 兼容服务,加载 Qwen/Qwen3-Embedding-4B,使用 --runner pooling --convert embed,并通过 /v1/embeddings 传入多个输入。当同一个请求中先给一个短输入,再给一个长到需要 truncate_prompt_tokens 截断的输入时,请求永不返回。后续请求会排在它后面,只有 abort 该请求才能恢复。
Issue 后续还发现,这不只是“短后长”的排序问题。使用长度排序批处理时,单个长文档请求、总在途 token 接近默认批预算的情况下,也会出现相同卡死特征。
报错原文
[Bug]: /v1/embeddings deadlocks when a truncated input follows a short one in the same request
Engine 000: Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 0.0 tokens/s,
Running: 1 reqs, Waiting: 0 reqs
后续真实负载中出现的变体:
Engine 000: Avg prompt throughput: 0.0 tokens/s, Running: 4 reqs, Waiting: 0 reqs
原因分析
Issue 中已定位到根因:这是 V1 调度器活性 bug,不是 CUDA 路径问题,也不是 pooling 批处理 offset/index 问题。调度器对 pooling 请求是否需要为采样 token 预留槽位存在不一致:num_sampled_tokens_per_step 对非 diffusion runner 仍为 1,但 pooling runner 并不会追加采样 token。运行队列分支会把 num_new_tokens 限制到 max_model_len - request.num_computed_tokens - self.num_sampled_tokens_per_step,而等待队列分支没有同样的 clamp。于是当 pooling prompt 恰好为 max_model_len,且被 chunked prefill 分块时,运行分支会在 num_computed_tokens == max_model_len - 1 时把新 token 数钳到 0,请求既不能前进也不能完成,调度循环空转。
短后长的排序只是最小复现条件之一:truncate_prompt_tokens: 2048 等于 --max-model-len 2048,Qwen3-Embedding 支持 chunked prefill 且默认开启,12 GiB 显卡下默认 max_num_batched_tokens 为 2048,多个条件叠加正好触发该边界。
环境排查
- 确认 vLLM 版本是否为 0.28.0,是否使用官方
vllm/vllm-openai:v0.28.0镜像。 - 确认后端是 CUDA 还是 ROCm;Issue 中 ROCm gfx1151 构建未复现。
- 确认显卡型号与显存:RTX 3080 Ti 12 GiB 属于会触发默认
max_num_batched_tokens=2048的区间。 - 确认模型是否为 Qwen3-Embedding-4B,是否使用 bf16 或压缩张量 W4A16 版本。
- 确认启动参数包含
--runner pooling --convert embed。 - 确认
--max-model-len与请求中的truncate_prompt_tokens是否相等;Issue 复现中两者均为 2048。 - 确认 chunked prefill 是否处于默认开启状态;pooling 模型不能对 prefill 分块,但支持 chunked prefill 的模型会默认开启。
- 确认卡死时
nvidia-smi是否仍响应、dmesg 是否有 Xid;Issue 中无 Xid,GPU 始终可响应。
解决步骤
- 先复现最小用例:启动
vllm serve Qwen/Qwen3-Embedding-4B --runner pooling --convert embed --max-model-len 2048 --port 8094。 - 用单个请求依次发送
[SHORT]、[LONG]、[LONG, SHORT]、[SHORT, LONG],并设置truncate_prompt_tokens: 2048。 - 观察只有
[SHORT, LONG]是否卡死,以及日志是否出现Running: N reqs, Waiting: 0 reqs且吞吐为 0。 - abort 卡死请求,确认后续请求是否立刻恢复处理。
- 可优先尝试规避:降低并发,避免单个 pooling 请求的 prompt 长度恰好等于
max_model_len后被分块;或避免让请求在运行队列中进入max_model_len - 1的边界状态。 - 不要优先用提高
--max-num-batched-tokens解决;Issue 中 24576 和 65536 在 12 GiB 显卡上启动即 OOM。 - 如果必须使用 CUDA 构建,关注 vLLM 上游对 V1 scheduler 中 pooling 请求
num_sampled_tokens_per_step与运行队列 clamp 的修复;在修复可用前,按上述规避方式控制并发与请求长度。
验证方法
重新发送 [SHORT, LONG] 请求,确认请求能在超时前返回 embedding,日志不再出现吞吐为 0 且 Waiting: 0 的卡死状态。再用真实 DuRetrieval 负载或长度排序批处理测试,确认在并发和总在途 token 接近默认批预算时也不会卡住。若仍出现 Running: N reqs, Waiting: 0 reqs 且 GPU 0% 利用率,说明问题未解决。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。

![[Bug]: Qwen3-Reranker: Process Hang with `/score` Endpoint for Specific Data](https://www.chat-gpts.plus/wp-content/uploads/2026/10/24704-b0c5e643-768x403.jpg)
![issue: [regression] [dev] - Model editor JSON Preview Copy copies the model as last saved, not the edits shown](https://www.chat-gpts.plus/wp-content/uploads/2026/10/31955-efc6fbac-768x403.jpg)