执行摘要
- 一句话:修复 Inkling 测试中 decode cache-hit 检查的 flaky 问题
- 推荐动作:该 PR 值得精读,尤其适合负责测试维护或关注 mamba/SWA 缓存机制的工程师。它展示了一个由配置不对齐导致的 flaky 测试的典型排查过程,以及如何通过将对齐直觉转化为显式断言(0.99)来提升测试的信噪比。但本身不涉及核心推理逻辑,重要性中等。
功能与动机
PR body 指出:test_input_output_logprobs_match_decode_cache_hit 间歇性红色,报 Too few decode cache hits: 16/32,而 avg_kl_div 保持 0.0。命中数并非噪声——decode checkpoint 仅在滑动窗口完整存留时可用,而窗口外的 SWA 槽位按页释放,因此最深的可复用位置是页边界;默认 mamba_track_interval=256 配合 --page-size 128 导致只有一半 prompt 能命中,期望值恰好 16/32,而测试需要 17 个,所以从落地起就一直差一个。
实现拆解
- 根因定位:在
test/registered/models_e2e/test_inkling_small_nvfp4.py 中,服务启动参数使用 --page-size 128,但 --mamba-track-interval 未显式设置,沿用默认 256。decode checkpoint 的可复用性取决于页边界,间隔与页大小不对齐导致只有约一半序列长度满足条件。
- 修改测试配置:新增常量
KL_TRACK_INTERVAL = 128,并在 setUpClass 的服务启动参数中加入 --mamba-track-interval str(KL_TRACK_INTERVAL),使 checkpoint 间隔与页大小一致,让每个页边界都成为 checkpoint,从而所有 prompt 都能命中 decode 缓存。
- 泛化 helper:在
python/sglang/test/kl_test_utils.py 的 test_input_output_logprobs_match_decode_cache_hit_helper 中新增 min_cache_hit_ratio=0.5 参数,替换原先硬编码的 0.5,保持默认行为不变,同时允许调用方按需收紧断言。
- 收紧断言:在
test_input_output_logprobs_match_decode_cache_hit 中传入 min_cache_hit_ratio=0.99,将命中率从“过半数”提升到“几乎全部”,使单次 miss 即视为状态复用回归,测试覆盖范围从原来仅一半请求翻倍。
- 配套说明:调整
_run 方法支持透传 **kwargs,并更新注释解释对齐逻辑,避免未来维护者误改配置。
关键文件:
test/registered/models_e2e/test_inkling_small_nvfp4.py(模块 端到端测试;类别 test;类型 test-coverage;符号 _run): 修复 flaky 的主战场:新增 KL_TRACK_INTERVAL 常量、在服务启动参数中显式设置 --mamba-track-interval 128,并将 decode cache-hit 测试的命中率阈值提升到 0.99,从根本上消除间歇性失败。
python/sglang/test/kl_test_utils.py(模块 测试工具;类别 test;类型 test-coverage): 为 decode cache-hit helper 引入 min_cache_hit_ratio 参数,替代硬编码的 0.5,使调用方可以按需收紧断言阈值,是支撑本 PR 收紧测试的关键配套改动。
关键符号:_run, test_input_output_logprobs_match_decode_cache_hit_helper
关键源码片段
test/registered/models_e2e/test_inkling_small_nvfp4.py
修复 flaky 的主战场:新增 KL_TRACK_INTERVAL 常量、在服务启动参数中显式设置 --mamba-track-interval 128,并将 decode cache-hit 测试的命中率阈值提升到 0.99,从根本上消除间歇性失败。
# 与下方 --page-size 128 对齐:SWA 窗口外的槽位按页释放,
# 只有落在页边界上的 checkpoint 才能保留完整滑动窗口数据,
# 默认 256 间隔会使一半的序列长度错过边界、丢掉 decode 前缀。
KL_TRACK_INTERVAL = 128
class TestInklingSmallNvfp4(CustomTestCase):
@classmethod
def setUpClass(cls):
cls.model = _MODEL_PATH
cls.base_url = DEFAULT_URL_FOR_TEST
cls.process = popen_launch_server(
cls.model,
cls.base_url,
timeout=DEFAULT_TIMEOUT_FOR_SERVER_LAUNCH,
other_args=[
"--tp", "4",
"--trust-remote-code",
"--quantization", "modelopt_fp4",
"--attention-backend", "fa4",
"--page-size", "128",
"--fp4-gemm-backend", "flashinfer_trtllm",
"--moe-runner-backend", "flashinfer_trtllm_routed",
"--mamba-radix-cache-strategy", "extra_buffer",
"--swa-full-tokens-ratio", "0.1",
"--mamba-full-memory-ratio", "0.1",
"--mem-fraction-static", "0.85",
# 关键修复:checkpoint 间隔与页大小对齐,确保每个页边界都有 checkpoint
"--mamba-track-interval", str(KL_TRACK_INTERVAL),
"--enable-deterministic-inference",
],
env={**os.environ, "SGLANG_ENABLE_UNIFIED_RADIX_TREE": "1"},
)
def _run(self, helper, **kwargs):
helper(
self.base_url,
{self.model: {"kl_div": KL_DIV_THRESHOLD}},
self.model,
max_samples=32,
max_new_tokens=KL_MAX_NEW_TOKENS,
trust_remote_code=True,
**kwargs,
)
def test_input_output_logprobs_match_decode_cache_hit(self):
# 0.99 意味着要求几乎全部 prompt 命中:间隔与页对齐后复用成为无条件行为,
# 因此任何一次 miss 都代表状态复用回退,而不再是几何巧合。
self._run(assert_logprobs_match_decode_cache_hit, min_cache_hit_ratio=0.99)
python/sglang/test/kl_test_utils.py
为 decode cache-hit helper 引入 min_cache_hit_ratio 参数,替代硬编码的 0.5,使调用方可以按需收紧断言阈值,是支撑本 PR 收紧测试的关键配套改动。
def test_input_output_logprobs_match_decode_cache_hit_helper(
base_url,
ACC_THRESHOLDS,
model_name,
max_samples=None,
max_new_tokens=8192,
trust_remote_code=False,
min_cache_hit_ratio=0.5,
):
# ... 第一轮生成与第二轮生成逻辑 ...
for i, result in enumerate(results):
if result["meta_info"]["cached_tokens"] <= len(first_turn_input_ids[i]) + 1:
print(f"Decode cache miss for prompt {i}, skipping")
continue
new_input_ids.append(second_turn_input_ids[i] + result["output_ids"])
output_logprobs.append(_extract_output_logprobs(result))
if not os.environ.get("SGLANG_TEST_SKIP_CACHE_HIT_ASSERT"):
# 页对齐的 SWA 保留策略决定了哪些 prompt 能命中,因此默认阈值只用于排除“全 miss”的空跑;
# 调用方若通过配置让每个 prompt 都命中,可提高该阈值来获得更严格的回归检测。
assert len(new_input_ids) > min_cache_hit_ratio * len(
second_turn_input_ids
), f"Too few decode cache hits: {len(new_input_ids)}/{len(second_turn_input_ids)}"
评论区精华
本 PR 没有 review 评论,仅有一条 issue 评论由作者触发 /rerun-test,第二次 rerun 通过(4-gpu-b200 上的测试从失败转为成功)。没有公开的设计讨论或争议。
风险与影响
- 风险:风险主要在于测试行为收紧:
min_cache_hit_ratio=0.99 会把任何一次非预期的 cache miss 变成失败,若未来 mamba 或 SWA 的内存管理策略发生变化(如页大小调整、释放粒度变化),可能导致误报。另外,--mamba-track-interval 128 是测试专用配置,不会影响生产路径;helper 的参数默认值保持向后兼容,其他调用方不受影响。整体风险较低,但需要注意该测试对几何对齐的敏感性。
- 影响:影响范围限于 CI 测试:修复了
TestInklingSmallNvfp4 在 B200 4-GPU 上的间歇性红色,提升了测试稳定性;同时通过提高命中率要求,使该测试能更可靠地捕获 decode 阶段的状态复用回归。kl_test_utils.py 的改动对所有使用该 helper 的测试透明,默认行为不变,并提供了更灵活的阈值控制。对用户和运行时无影响。
- 风险标记:测试阈值收紧,可能暴露新的缓存回退问题, 依赖 mamba-track-interval 与 page-size 的隐式耦合
关联脉络
- PR #34301 Fix CI server warmup progress logging: 同为 CI 测试稳定性修复,针对多模态生成测试中的 flaky 日志/断言问题,说明团队持续治理测试稳定性,与本 PR 目标一致。
参与讨论