Prhub

#32595 Support SGLANG_SIMULATE_ACC_LEN for DFLASH

原始 PR 作者 saatwiknagpal 合并时间 2026-07-31 05:10 文件变更 2 提交数 1 评论 7 代码增减 +73 / -0

执行摘要

DFLASH 支持模拟 acc_len 基准测试

SGLANG_SIMULATE_ACC_LEN 是强制固定投机接收长度的基准测试 knob。EAGLE 和 DSpark 已支持,DFLASH 忽略它。PR 旨在补齐 DFLASH 的支持,使其也能使用该机制进行性能评估。

值得精读的基准测试功能补齐 PR,设计清晰合理。关注点在于 new_seq_lens 重置的副作用处理以及 review 中关于 AI 注释和防御性代码的 nit 反馈,可在后续维护中改进。建议在后续 PR 中添加自动化测试。

讨论亮点

审核者 kpham-sgl 提出两条 nit 评论:

  • "Remove AI gen comments":要求移除函数中的 AI 生成注释(可能是自动生成的无关注释)。
  • "nit: some of these are too defensive":指出部分参数校验或逻辑过于防御性。
    两条评论均未进一步展开,审核者最终批准了 PR。

实现拆解

  1. dflash_utils.py 新增 apply_dflash_simulated_acceptance() 函数: 该函数接收 candidatestarget_predictaccept_lencommit_lensbonusout_tokens 等张量,根据 simulate_acc_lensimulate_acc_method 通过 _sample_simulated_acc_len() 计算强制 commit_len,并填充 accept_lencommit_lensbonusout_tokens。支持两种 token 填充模式:real-draft-token(使用真实 draft 和 target token)和 fixed(使用固定 token id)。
  2. dflash_worker_v2.pyforward_batch_generation() 方法中集成: 在贪心和采样两种验证分支收敛后,检查 SIMULATE_ACC_LEN > 0。若启用,校验 SIMULATE_ACC_TOKEN_MODE 的有效性。若为 real-draft-tokentarget_predict 未计算(采样分支),则通过 torch.argmax 计算目标 logits 的 argmax。然后调用 apply_dflash_simulated_acceptance() 覆盖接收结果。最后将 new_seq_lens 置为 None 以强制基于强制 commit_lens 重新计算,避免与真实验证结果冲突。
  3. 导入调整: dflash_utils.py 新增 from sglang.srt.speculative.spec_utils import _sample_simulated_acc_lendflash_worker_v2.py 的导入列表新增 apply_dflash_simulated_acceptance 以及常量 SIMULATE_ACC_LENSIMULATE_ACC_METHODSIMULATE_ACC_TOKEN_MODE
  4. 测试验证: PR body 报告了在 Llama-3.1-8B-Instruct + DFlash-UltraChat 上的实验,强制 acc_len 1 和 4 时平均接收长度精确匹配,且 SIM=1 输出与基线字节一致。但本次提交未包含自动化测试文件。
文件 模块 状态 重要度
python/sglang/srt/speculative/dflash_utils.py 投机解码 modified 7.03
python/sglang/srt/speculative/dflash_worker_v2.py 投机解码 modified 6.49

关键符号

apply_dflash_simulated_acceptance

关键源码片段

python/sglang/srt/speculative/dflash_utils.py core-logic

新增 `apply_dflash_simulated_acceptance()` 核心函数,实现强制覆盖接收逻辑。

# python/sglang/srt/speculative/dflash_utils.py
# 新增函数,强制覆盖 DFLASH 的接收长度和输出 token
# 用于基准测试 SGLANG_SIMULATE_ACC_LEN
def apply_dflash_simulated_acceptance(
    *,
    candidates: torch.Tensor, # [bs, 1 + block_size],draft tokens
    target_predict: Optional[torch.Tensor], # [bs, block_size],目标模型 argmax(greedy 时提供)
    accept_len: torch.Tensor, # [bs],当前接收长度,会被覆盖
    commit_lens: torch.Tensor, # [bs],当前提交长度,会被覆盖
    bonus: torch.Tensor, # [bs],bonus token,会被覆盖
    out_tokens: torch.Tensor, # [bs, block_size],输出 token,会被覆盖
    simulate_acc_len: float, # 环境变量 SGLANG_SIMULATE_ACC_LEN 的值
    simulate_acc_method: str, # 采样方法(如 "avg" 或 "fixed")
    simulate_acc_token_mode: str, # "fixed" 或 "real-draft-token"
    fixed_token_id: int = 100, # fixed 模式使用的 token id
) -> None:
    block_size = candidates.shape[1]
​
    # _sample_simulated_acc_len 将值限制在 [1, block_size] 之间
    forced_commit_len = _sample_simulated_acc_len(
        simulate_acc_len, simulate_acc_method, block_size
    )
    forced_accept_len = forced_commit_len - 1
​
    # 覆盖张量(原地修改)
    accept_len.fill_(forced_accept_len)
    commit_lens.fill_(forced_commit_len)
​
    if simulate_acc_token_mode != "real-draft-token":
        # fixed 模式:使用固定 token(常用于调试或控制变量实验)
        bonus.fill_(fixed_token_id)
        out_tokens.fill_(fixed_token_id)
        return
​
    # real-draft-token 模式:使用真实的 draft 和 target token
    out_tokens.zero_()
    if forced_accept_len > 0:
        out_tokens[:, :forced_accept_len].copy_(candidates[:, 1:forced_commit_len])
    bonus.copy_(target_predict[:, forced_accept_len].to(dtype=bonus.dtype))
    out_tokens[:, forced_accept_len].copy_(bonus.to(dtype=out_tokens.dtype))
python/sglang/srt/speculative/dflash_worker_v2.py core-logic

在 `forward_batch_generation()` 中集成模拟接收逻辑,是触发入口。

# python/sglang/srt/speculative/dflash_worker_v2.py
# 在 forward_batch_generation 方法中,两个验证分支收敛后加入以下代码
        # ... 前面是贪心或采样验证逻辑,得到 accept_len, commit_lens, bonus, out_tokens ...
​
        # 若启用了模拟接收长度环境变量,则覆盖实际计算结果
        if SIMULATE_ACC_LEN > 0:
            # 校验 token 模式参数
            if SIMULATE_ACC_TOKEN_MODE not in ("fixed", "real-draft-token"):
                raise ValueError(
                    "Invalid SGLANG_SIMULATE_ACC_TOKEN_MODE "
                    f"{SIMULATE_ACC_TOKEN_MODE!r}; expected 'fixed' or "
                    "'real-draft-token'."
                )
​
            # 若为 real-draft-token 模式但 target_predict 未计算(采样分支未计算 argmax)
            if SIMULATE_ACC_TOKEN_MODE == "real-draft-token" and target_predict is None:
                target_predict = torch.argmax(
                    logits_output.next_token_logits, dim=-1
                ).view(bs, int(self.block_size))
​
            # 调用核心覆盖函数
            apply_dflash_simulated_acceptance(
                candidates=candidates,
                target_predict=target_predict,
                accept_len=accept_len,
                commit_lens=commit_lens,
                bonus=bonus,
                out_tokens=out_tokens,
                simulate_acc_len=SIMULATE_ACC_LEN,
                simulate_acc_method=SIMULATE_ACC_METHOD,
                simulate_acc_token_mode=SIMULATE_ACC_TOKEN_MODE,
            )
            # 重置 new_seq_lens,以便后续从强制 commit_lens 重新计算
            new_seq_lens = None
​
        # ... 后续 mamba 状态更新等逻辑 ...

评论区精华

移除 AI 生成注释 style

审核者 kpham-sgl 要求移除函数中的 AI 生成注释,可能指自动化工具生成的冗余注释。

结论:未被进一步讨论,但审核者最终批准,推测开发者已接受并移除。 · 已解决

防御性代码过多 style

审核者指出 `apply_dflash_simulated_acceptance` 中部分参数校验或逻辑过于防御性(too defensive)。

结论:未被进一步讨论,审核者仍批准,可能是 minor 意见。 · 已解决

风险与影响

风险较低。 功能在 env var 未设置时默认不生效,不会影响正常流程。但存在以下潜在风险:

  • 回归风险:若 new_seq_lens 置为 None 后重新计算逻辑与其他部分(如 mamba 状态更新)交互异常,可能导致序列长度不一致。但 PR 中明确重置了该变量,且在 mamba commit 前处理,风险可控。
  • 性能影响:仅在 env var 设置时才引入额外计算(如采样分支的 argmax),无性能退化。
  • 缺少自动化测试:未包含 test/ 目录下的测试文件,依赖手动测试。

影响范围小,仅涉及 DFLASH 投机解码方案的基准测试场景。用户可通过设置环境变量 SGLANG_SIMULATE_ACC_LENSGLANG_SIMULATE_ACC_TOKEN_MODE 来控制行为。对系统其他模块(EAGLE、DSpark、调度器等)无影响。

缺少测试覆盖

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论