批不变性¶
Note
批不变性目前处于 beta 阶段。部分功能仍在积极开发中。 请在 跟踪问题 #5487 中查看进展和计划改进。
Note
要安装批不变性自定义算子库,请在构建 vllm-ascend 之前设置 VLLM_BATCH_INVARIANT=1。
有关安装说明,请参阅在现有 CANN 环境中安装。
本文档介绍如何在 vLLM-Ascend 中启用批不变性。批不变性确保模型输出是确定性的,并且独立于批大小或批内请求顺序。
动机¶
批不变性对以下多个用例至关重要:
- 框架调试:确定性输出使推理框架中的问题更容易调试,因为无论是否批处理,相同输入始终产生相同输出。
- 模型调试:通过确保在不同批配置下行为一致,有助于识别模型实现中的问题。
- 强化学习(RL):RL 训练通常需要确定性 rollout,以实现可复现性和稳定训练。
- 大规模推理系统:将 vLLM 作为组件的系统可以从确定性行为中受益,用于测试、验证和一致性保证。
硬件要求¶
批不变性支持 Atlas A2、A3 和 950PR&950DT 产品。
软件要求¶
批不变性需要 Atlas A2、A3 和 950PR&950DT 产品的自定义算子。在从源码构建 vllm-ascend 之前设置 VLLM_BATCH_INVARIANT=1,以构建并安装所需的算子包。
batch_invariant_ops 的构建和安装流程包括两个阶段,如 build_batch_invariant_ops.sh 所示,必须按顺序执行:
- 安装算子运行包。它提供使用 AscendC 实现的设备端批不变算子。
- 构建并安装
batch_invariant_opswheel。它提供调用 AscendC 算子的 PyTorch 扩展接口。
Note
预构建的 vllm-ascend wheel 不包含 csrc 目录或 csrc/build_batch_invariant_ops.sh,在安装该 wheel 时设置 VLLM_BATCH_INVARIANT=1 不会重新构建算子。手动安装算子需要匹配的 vllm-ascend 源码检出。以下命令中的 <vllm-ascend-source-dir> 指该源码检出,而不是 wheel 的 site-packages 目录。
从源码安装¶
选项 1:一起安装 vllm-ascend 和算子包¶
该环境变量由源码构建使用。当启用自定义内核编译时,它同时适用于常规源码安装和可编辑源码安装:
cd <vllm-ascend-source-dir>
# Regular source installation
COMPILE_CUSTOM_KERNELS=1 VLLM_BATCH_INVARIANT=1 \
pip install . --no-build-isolation
# Editable source installation
COMPILE_CUSTOM_KERNELS=1 VLLM_BATCH_INVARIANT=1 \
pip install -e . --no-build-isolation
选项 2:如果 vllm-ascend 已安装,则安装算子包¶
获取与已安装包版本匹配的 vllm-ascend 源码树,然后从该源码树构建并安装算子包。
A2:
A3:
950PR&950DT 产品:
使用 Docker 镜像¶
用于 Ubuntu 和 openEuler 的 A2、A3 和 950PR&950DT 产品 Docker 镜像会使用 VLLM_BATCH_INVARIANT=1 从源码构建 vllm-ascend,因此镜像构建会同时安装 AscendC 算子运行包和 batch_invariant_ops wheel。该构建时环境变量不会保留为运行时设置。启动服务器或运行离线推理时设置 VLLM_BATCH_INVARIANT=1 以启用批不变性。
快速检查¶
安装后,验证算子是否可用:
python -c "
import batch_invariant_ops
import torch
op = torch.ops.batch_invariant_ops.npu_matmul_batch_invariant
print(op)
assert 'npu_matmul_batch_invariant' in str(op)
"
启用批不变性¶
可以通过将 VLLM_BATCH_INVARIANT 环境变量设置为 1 来启用批不变性:
在线推理(服务器模式)¶
要启动启用批不变性的 vLLM 服务器:
VLLM_BATCH_INVARIANT=1 vllm serve Qwen/Qwen3-8B \
--no-enable-chunked-prefill \
--no-enable-prefix-caching \
--block-size 128
然后使用 OpenAI 兼容客户端:
from openai import OpenAI
client = OpenAI(
api_key="EMPTY",
base_url="http://localhost:8000/v1",
)
# These requests will produce deterministic outputs
# regardless of batch size or order
response = client.completions.create(
model="Qwen/Qwen3-8B",
prompt="The future of AI is",
max_tokens=100,
temperature=0.7,
seed=42,
)
print(response.choices[0].text)
离线推理¶
对于启用批不变性的离线批量推理:
import os
os.environ["VLLM_BATCH_INVARIANT"] = "1"
from vllm import LLM, SamplingParams
prompts = [
"The future of AI is",
"Machine learning enables",
"Deep learning models can",
]
sampling_params = SamplingParams(
temperature=0.7,
max_tokens=100,
seed=42,
)
llm = LLM(
model="Qwen/Qwen3-8B",
tensor_parallel_size=1,
enable_prefix_caching=False,
enable_chunked_prefill=False,
block_size=128,
)
# Outputs will be deterministic regardless of batch size
outputs = llm.generate(prompts, sampling_params)
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text
print(f"Prompt: {prompt!r}")
print(f"Generated: {generated_text!r}\n")
调度限制¶
启用批次不变性时,不支持分块预填充、前缀缓存和请求抢占(驱逐和重计算)。
这些调度功能不会自动禁用。您必须在配置中显式禁用分块预填充和前缀缓存,并将禁用分块预填充与 KV cache 块大小 128 配对使用——启动服务器时同时传入 --block-size 128 和 --no-enable-chunked-prefill,或在离线推理时同时使用 block_size=128 和 enable_chunked_prefill=False——如上文示例所示。
当 KV cache 耗尽时会触发请求抢占:被抢占的请求会被驱逐,并在之后重新计算。重新计算的预填充包含抢占前生成的 token,因此注意力机制会通过预填充(P)路径而不是原始解码(D)路径处理这些 token——P 和 D 的计算无法对齐,这会破坏批次不变性。为降低抢占发生的可能性,请增加可用 KV cache 或降低单请求和并发压力:
- 降低
--max-num-seqs,使更少的请求共享 KV cache。 - 将
--max-model-len设置为工作负载所需的最小值,并限制每个请求的输出长度(max_tokens)。 - 提高
--gpu-memory-utilization,为 KV cache 留出更多内存。
使用启动日志(GPU KV cache size 和 Maximum concurrency for ... tokens per request)根据 KV cache 容量来规划工作负载,并关注引擎统计信息:GPU KV cache usage 接近 100% 表示即将发生抢占。有关详细信息,请参阅抢占常见问题。
已测试模型¶
批次不变性已在以下模型上完成测试和验证:
- Qwen3 (Dense):
Qwen/Qwen3-1.7B,Qwen/Qwen3-8B - Qwen3 (MoE):
Qwen/Qwen3-30B-A3B,Qwen/Qwen3-235B-A22B
其他模型也可能可用,但这些模型已得到明确验证。如果您在特定模型上遇到问题,请在 GitHub 问题跟踪器 中报告。
实现细节¶
启用批次不变性后,vLLM 会:
- 使用确定性的内核实现来处理注意力和其他操作
- 确保在不同批次大小下具有一致的数值行为
- 禁用某些可能引入非确定性的优化
Note
与默认的非确定性模式相比,启用批次不变性可能会影响性能。这一权衡是有意为之,以保证可复现性。
未来改进¶
批次不变性功能正在积极开发中。计划改进包括:
- 支持更多 NPU 系列
- 扩展模型覆盖范围
- 性能优化
- 额外的测试和验证
有关最新状态以及贡献想法,请参阅跟踪 issue。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 vl/vllm-ascend