[AI] max_num_seqs 参数详解

max_num_seqs 参数详解

一、参数定义

max_num_seqs 是 vLLM 和 vLLM-Ascend 中一个关键的调度配置参数,用于限制单个调度步骤中同时处理的最大序列(请求)数量

默认值

  • 默认值: 128
  • 位置 : vllm/vllm/config/scheduler.py 中的 SchedulerConfig.DEFAULT_MAX_NUM_SEQS
python 复制代码
DEFAULT_MAX_NUM_SEQS: ClassVar[int] = 128

二、核心作用

1. 调度器层面的限制

在调度器(Scheduler)中,max_num_seqs 被转换为 max_num_running_reqs,用于限制同时处于运行状态(RUNNING)的请求数量

代码位置 : vllm/vllm/v1/core/sched/scheduler.py

python 复制代码
# 第97行
self.max_num_running_reqs = self.scheduler_config.max_num_seqs

调度逻辑:

python 复制代码
# 第428-429行:当运行中的请求数达到上限时,停止从等待队列中调度新请求
if len(self.running) == self.max_num_running_reqs:
    break

这意味着:

  • 如果当前有 128 个请求正在运行(max_num_seqs=128),新的请求将停留在等待队列(WAITING)中
  • 只有当某个运行中的请求完成或被抢占后,等待队列中的请求才能被调度

2. 内存分配和缓冲区大小

max_num_seqs 直接影响 Worker 中各种缓冲区的分配大小。

2.1 RequestState 缓冲区

代码位置 : vllm/vllm/v1/worker/gpu/states.py

RequestState 类使用 max_num_reqs(即 max_num_seqs)来分配所有请求相关的状态缓冲区:

python 复制代码
class RequestState:
    def __init__(self, max_num_reqs: int, ...):
        # 为每个请求分配固定大小的缓冲区
        self.prompt_len = np.zeros(self.max_num_reqs, dtype=np.int32)
        self.prefill_token_ids = UvaBuffer(
            self.max_num_reqs, self.max_model_len, dtype=torch.int32
        )
        self.prefill_len = self._make_buffer(self.max_num_reqs, dtype=torch.int32)
        self.num_computed_tokens = torch.zeros(
            self.max_num_reqs, dtype=torch.int32, device=device
        )
        # ... 更多缓冲区

内存影响:

  • prefill_token_ids: 大小为 max_num_reqs × max_model_len × 4字节(int32)
    • 例如:128 × 32768 × 4 = 16MB(仅这一个缓冲区)
  • 所有请求状态缓冲区的总大小与 max_num_seqs 成正比
2.2 InputBuffers 缓冲区

代码位置 : vllm/vllm/v1/worker/gpu/model_runner.py

python 复制代码
self.input_buffers = InputBuffers(
    max_num_reqs=self.max_num_reqs,  # 使用 max_num_seqs
    max_num_tokens=self.max_num_tokens,
    ...
)

InputBuffers 用于存储每个推理步骤的输入数据,其大小也受 max_num_seqs 影响。

2.3 BlockTables 缓冲区

代码位置 : vllm/vllm/v1/worker/gpu/model_runner.py

python 复制代码
self.block_tables = BlockTables(
    block_sizes=block_sizes,
    max_num_reqs=self.max_num_reqs,  # 使用 max_num_seqs
    max_num_batched_tokens=self.max_num_tokens,
    ...
)

BlockTables 用于管理 KV Cache 的块表,其大小也与 max_num_seqs 相关。

3. 数据并行(DP)场景下的特殊含义

在 vLLM-Ascend 的文档中明确指出:

--max-num-seqs 表示每个 DP group 允许处理的最大请求数。如果发送到服务的请求数超过此限制,多余的请求将保持在等待状态,不会被调度。

重要公式:

复制代码
总并发能力 = max_num_seqs × data_parallel_size

示例:

  • 如果 max_num_seqs=16data_parallel_size=2
  • 那么总共有 16 × 2 = 32 个请求可以同时运行
  • 如果实际并发请求数为 40,那么有 8 个请求会处于等待状态

性能测试建议:

在测试性能时,一般建议 max_num_seqs × data_parallel_size >= 实际总并发数,否则等待时间也会被计入 TTFT(Time To First Token)和 TPOT(Time Per Output Token)等指标中。

4. 与 max_num_batched_tokens 的关系

max_num_seqsmax_num_batched_tokens 共同决定了批处理的能力:

验证逻辑vllm/vllm/config/scheduler.py):

python 复制代码
# 第264-269行:max_num_batched_tokens 必须 >= max_num_seqs
if self.max_num_batched_tokens < self.max_num_seqs:
    raise ValueError(
        f"max_num_batched_tokens ({self.max_num_batched_tokens}) must "
        "be greater than or equal to max_num_seqs "
        f"({self.max_num_seqs})."
    )

关系说明:

  • max_num_batched_tokens: 限制单次推理步骤中处理的总 token 数
  • max_num_seqs: 限制单次推理步骤中处理的总请求数
  • 理论上,如果每个请求只有 1 个 token,最多可以处理 max_num_batched_tokens 个请求
  • 但实际上,由于 max_num_seqs 的限制,最多只能处理 max_num_seqs 个请求

警告逻辑(第271-277行):

python 复制代码
if self.max_num_batched_tokens > self.max_num_seqs * max_model_len:
    logger.warning(
        "max_num_batched_tokens (%d) exceeds max_num_seqs "
        "* max_model_len (%d). This may lead to unexpected behavior.",
        ...
    )

三、影响范围

1. 内存占用

直接影响:

  • 所有请求状态缓冲区的大小
  • InputBuffers 的大小
  • BlockTables 的大小
  • 采样参数缓冲区的大小

内存计算公式(简化):

复制代码
额外内存 ≈ max_num_seqs × (
    max_model_len × 4 +      # prefill_token_ids
    各种状态缓冲区大小
)

2. 调度性能

正面影响:

  • 吞吐量 : 较大的 max_num_seqs 允许更多请求并发处理,可能提高吞吐量
  • GPU 利用率: 更多请求可以更好地利用 GPU 的并行计算能力

负面影响:

  • 延迟 : 如果 max_num_seqs 太小,请求会在等待队列中停留更长时间
  • 内存压力 : 更大的 max_num_seqs 需要更多 GPU 内存

3. 并发处理能力

限制因素:

  • 如果实际并发请求数 > max_num_seqs × data_parallel_size,多余的请求会排队等待
  • 等待时间会被计入性能指标(TTFT、TPOT),影响用户体验

4. 批处理效率

批处理大小:

  • 每次推理步骤最多处理 max_num_seqs 个请求
  • 如果请求数 < max_num_seqs,批处理可能不够满,GPU 利用率可能下降
  • 如果请求数 > max_num_seqs,需要多步处理,可能增加延迟

四、使用建议

1. 根据硬件资源调整

GPU 内存充足时:

  • 可以设置较大的 max_num_seqs(如 256、512)
  • 提高并发处理能力和吞吐量

GPU 内存受限时:

  • 需要减小 max_num_seqs(如 64、32)
  • 避免 OOM(Out of Memory)错误

2. 根据工作负载调整

高并发场景:

  • 确保 max_num_seqs × data_parallel_size >= 预期并发数
  • 避免请求长时间等待

低延迟优先场景:

  • 可以适当减小 max_num_seqs
  • 减少批处理大小,降低单步处理时间

高吞吐量优先场景:

  • 增大 max_num_seqs
  • 提高批处理效率

3. 与 max_num_batched_tokens 的平衡

经验法则:

  • max_num_batched_tokens 应该 >= max_num_seqs
  • 对于短序列请求,可以设置 max_num_batched_tokens 远大于 max_num_seqs
  • 对于长序列请求,需要确保 max_num_batched_tokens 足够大以处理长序列

4. 数据并行场景

重要公式:

复制代码
总并发能力 = max_num_seqs × data_parallel_size

建议:

  • 在设置 max_num_seqs 时,考虑 data_parallel_size
  • 确保总并发能力满足实际需求

五、代码示例

1. 在 vLLM 中设置

python 复制代码
from vllm import LLM

llm = LLM(
    model="your-model",
    max_num_seqs=128,  # 设置最大序列数
    max_num_batched_tokens=2048,  # 必须 >= max_num_seqs
)

2. 在 vLLM-Ascend 中设置

bash 复制代码
vllm serve Qwen/Qwen3-VL-235B-A22B-Instruct \
    --max-num-seqs 16 \
    --data-parallel-size 2 \
    --max-num-batched-tokens 4096 \
    ...

3. 验证配置

python 复制代码
# 在 SchedulerConfig 中会自动验证
# 如果 max_num_batched_tokens < max_num_seqs,会抛出 ValueError

六、常见问题

Q1: max_num_seqs 设置太小会怎样?

A:

  • 请求会在等待队列中停留更长时间
  • 吞吐量下降
  • 延迟增加(等待时间计入 TTFT/TPOT)

Q2: max_num_seqs 设置太大会怎样?

A:

  • GPU 内存占用增加
  • 可能导致 OOM
  • 批处理效率可能下降(如果实际请求数远小于 max_num_seqs)

Q3: 如何确定合适的 max_num_seqs?

A:

  1. 根据 GPU 内存容量估算
  2. 根据实际并发需求计算:max_num_seqs × data_parallel_size >= 并发数
  3. 通过性能测试找到最佳平衡点

Q4: max_num_seqs 和 max_num_batched_tokens 的区别?

A:

  • max_num_seqs: 限制请求数量
  • max_num_batched_tokens: 限制token 数量
  • 两者共同决定批处理能力

七、总结

max_num_seqs 是 vLLM 中一个关键的调度和资源管理参数,它:

  1. 限制并发: 控制同时处理的请求数量
  2. 分配内存: 决定各种缓冲区的分配大小
  3. 影响性能: 直接影响吞吐量、延迟和 GPU 利用率
  4. 与 DP 相关 : 在数据并行场景下,总并发能力 = max_num_seqs × data_parallel_size

合理设置 max_num_seqs 需要在内存占用并发能力性能指标之间找到平衡点。

相关推荐
AngelPP10 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年10 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
AI探索者10 小时前
LangGraph StateGraph 实战:状态机聊天机器人构建指南
python
AI探索者10 小时前
LangGraph 入门:构建带记忆功能的天气查询 Agent
python
九狼10 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS10 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区11 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈11 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
FishCoderh11 小时前
Python自动化办公实战:批量重命名文件,告别手动操作
python
躺平大鹅11 小时前
Python函数入门详解(定义+调用+参数)
python