[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 需要在内存占用并发能力性能指标之间找到平衡点。

相关推荐
喜欢踢足球的老罗2 小时前
解构ClawdBot:当AI Agent遇上生产级工程化架构
人工智能·架构
freejackman2 小时前
持续集成-Jenkins 基础教程
java·python·ci/cd·自动化·jenkins·持续部署·持续集成
CCPC不拿奖不改名2 小时前
提示词工程(Prompt Engineering)全体系知识手册
大数据·人工智能·python·搜索引擎·prompt
OnYoung2 小时前
Python生成器(Generator)与Yield关键字:惰性求值之美
jvm·数据库·python
亚林瓜子2 小时前
AWS中国云中的ETL之从Amazon Glue Data Catalog搬数据到MySQL(Glue版)
python·mysql·spark·etl·aws·glue·py
雨中飘荡的记忆2 小时前
Spring AI + MCP:从入门到实战
java·人工智能·spring
薛定谔的猫19822 小时前
四、基于LangChain与HuggingFace Pipeline的本地大语言模型对话系统搭建指南(使用阿里千问-模型)
人工智能·语言模型·langchain
ZCXZ12385296a2 小时前
【无标题】
人工智能·计算机视觉·目标跟踪
赛卓电子Semiment2 小时前
汽车油门踏板 | 国产应用方案
人工智能