Skip to content

[Optimization][Speculative Decoding]opt mtp logprob#7883

Open
Sunny-bot1 wants to merge 2 commits into
PaddlePaddle:developfrom
Sunny-bot1:opt_mtp_logprob
Open

[Optimization][Speculative Decoding]opt mtp logprob#7883
Sunny-bot1 wants to merge 2 commits into
PaddlePaddle:developfrom
Sunny-bot1:opt_mtp_logprob

Conversation

@Sunny-bot1
Copy link
Copy Markdown
Collaborator

@Sunny-bot1 Sunny-bot1 commented May 21, 2026

Motivation

MTP + logprob(top_logprobs:0) 性能提升10%

Modifications

Usage or Command

Accuracy Tests

Checklist

  • Add at least a tag in the PR title.
    • Tag list: [[FDConfig],[APIServer],[Engine], [Scheduler], [PD Disaggregation], [Executor], [Graph Optimization], [Speculative Decoding], [RL], [Models], [Quantization], [Loader], [OP], [KVCache], [DataProcessor], [BugFix], [Docs], [CI], [Optimization], [Feature], [Benchmark], [Others], [XPU], [HPU], [GCU], [DCU], [Iluvatar], [Metax]]
    • You can add new tags based on the PR content, but the semantics must be clear.
  • Format your code, run pre-commit before commit.
  • Add unit tests. Please write the reason in this PR if no unit tests.
  • Provide accuracy results.
  • If the current PR is submitting to the release branch, make sure the PR has been submitted to the develop branch, then cherry-pick it to the release branch with the [Cherry-Pick] PR tag.

@paddle-bot
Copy link
Copy Markdown

paddle-bot Bot commented May 21, 2026

Thanks for your contribution!

@Sunny-bot1 Sunny-bot1 changed the title [Optimization][[Speculative Decoding]]opt mtp logprob [Optimization][Speculative Decoding]opt mtp logprob May 21, 2026
@PaddlePaddle-bot
Copy link
Copy Markdown

PaddlePaddle-bot commented May 21, 2026

🤖 Paddle-CI-Agent | ci_status_monitor | 2026-05-22 16:14:54

CI报告基于以下代码生成(30分钟更新一次):


1 任务总览

Required 任务当前 8/10 通过,仍有 2 个 required 失败,暂不建议合入;其中 1 个为 PR 相关单测失败,1 个为人工 Approval 待处理。Optional 失败/取消仅供参考。

总执行(rerun次数) 总任务 ✅ 通过 ❌ 失败 ⏳ 运行中 ⏸️ 等待中 跳过
42(0) 42 36 5 0 0 0

补充:当前另有 1 个任务处于 cancelled 状态(optional,不计入上表“跳过”列)。

2 任务状态汇总

日志列说明:失败任务直接使用日志链接;运行中任务使用 Job 链接。

2.1 Required任务 : 8/10 通过

必选任务阻塞合并,失败需优先处理。

状态 任务 耗时 根因 修复建议 日志 重跑
Run FastDeploy Unit Tests and Coverage / run_tests_with_coverage 1h22m PR问题:MTP logprob topk协议适配不完整 统一打包meta[1]并修正topk协议 Job -
Approval 7s 需要 Approval 请通过人工审批 Job -
其余 8 个必选任务通过 - - - - -

2.2 可选任务 — 28/32 通过

可选任务不阻塞合并,失败仅供参考。

状态 任务 耗时 日志 重跑
Check PR Template 13s Job -
CI_HPU 1h30m Job -
Trigger Jenkins for PR 7m38s Job -
🚫 Run iluvatar Tests / run_iluvatar_cases - - -
其余 28 个可选任务通过 - - -

3 失败详情(仅 required)

Run FastDeploy Unit Tests and Coverage / run_tests_with_coverage — 测试失败(置信度: 高)

Run FastDeploy Unit Tests and Coverage / run_tests_with_coverage

  • 状态: ❌ 失败
  • 错误类型: 测试失败
  • 置信度: 高
  • 根因摘要: MTP logprob topk协议适配不完整
  • 分析器: ci_analyze_unittest_fastdeploy

失败用例:

测试 错误 根因
tests/e2e/test_ernie_21b_mtp_multistep.py::test_prefix_cache_text AssertionError: logprobs 与baseline不一致 PR 修改 MTP logprob/topk 传输协议后,真实流式输出 top_logprobs 候选与 baseline 不一致
tests/output/test_process_batch_output.py::test_process_batch_output_aborted_task_negative_token_speculative_decoding IndexError: list index out of range 测试仍写裸 mtype=3,Python 解包 actual_topk=0 后访问空 topk 列
tests/output/test_process_batch_output.py::test_speculative_decoding_use_logprobs IndexError: list index out of range 同上,mock 的 meta[1] 未按新协议携带 actual_topk
tests/output/test_token_processor.py::test_process_batch_output_speculative_logprob_handles_draft_batch IndexError: list index out of range draft 路径 mtype=4 未打包 actual_topk,_process_batch_draft_tokens 访问空列
tests/output/test_token_processor.py::test_process_batch_output_speculative_logprob_targets_topk_scores IndexError: list index out of range target 路径 mtype=3 未打包 actual_topk,tokens_lists[i] 每行为空

根因详情:
本 PR 将 speculative/MTP logprob 的 meta[1] 从单一 message_flag 改为 message_flag | (max_num_logprobs << 8),Python 端在 fastdeploy/output/token_processor.py:773-781 依赖该字段解包 actual_topk 并裁剪 topk 维度。单测中多处仍设置裸 3/4,导致 actual_topk=0,随后在 token_processor.py:741 / token_processor.py:865 访问 row[0] 触发 IndexError

此外,e2e 请求使用 logprobs=True, top_logprobs=3,日志显示 tests/e2e/test_ernie_21b_mtp_multistep.py:226 的 baseline 断言失败;首个差异处 baseline 第 3 个 top_logprob 为 ,实际输出变为 后期。这说明不仅测试 mock 需要更新,C++ 端 max_num_logprobs/stride 写入与 Python 端 actual_topk 解包后的真实 MTP logprob 候选也需要重新校准,避免改变输出准确性。

关键日志:

FAILED tests/e2e/test_ernie_21b_mtp_multistep.py::test_prefix_cache_text - AssertionError: logprobs 与baseline不一致
FAILED tests/output/test_process_batch_output.py::...negative_token_speculative_decoding - IndexError: list index out of range
FAILED tests/output/test_process_batch_output.py::...test_speculative_decoding_use_logprobs - IndexError: list index out of range
FAILED tests/output/test_token_processor.py::...handles_draft_batch - IndexError: list index out of range
FAILED tests/output/test_token_processor.py::...targets_topk_scores - IndexError: list index out of range
fastdeploy/output/token_processor.py:865: token_ids = [row[0] for row in tokens_lists[i][: accept_num[i]]]
fastdeploy/output/token_processor.py:741: token_ids = [row[0] for row in tokens_i[: accept_num[i]]]

修复建议:

  1. tests/output/test_process_batch_output.py:213/250/284tests/output/test_token_processor.py:751/928 等 speculative+logprobs mock 中,将 meta[1] 按新协议写为 mtype | ((K + 1) << 8)(或对应实际 topk),避免 actual_topk=0
  2. 复查 custom_ops/gpu_ops/speculate_decoding/*topk.ccmax_num_logprobs 的写入范围、读取 stride 与 fastdeploy/output/token_processor.py:773-785 的裁剪逻辑,保证 top_logprobs=3 时输出候选顺序与 baseline 一致。
  3. 复查 fastdeploy/worker/gpu_model_runner.py:1277-1285 去掉 speculative 固定 20 后,req.sampling_params.logprobs 与 OpenAI top_logprobs 语义是否需要 +1 或保留采样 token 的兼容处理,并补充该场景回归测试。

修复建议摘要: 统一打包meta[1]并修正topk协议

关联变更: fastdeploy/output/token_processor.py:773-785, 865fastdeploy/worker/gpu_model_runner.py:1277-1285custom_ops/gpu_ops/speculate_decoding/*topk.cc

链接: 查看日志

Approval — 需要人工审批(置信度: 高)

该 Job 需要人工 Approval,完成审批后 CI 才会继续执行。

PaddlePaddle-bot

This comment was marked as outdated.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 21, 2026

Codecov Report

❌ Patch coverage is 80.00000% with 4 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (develop@fe146ec). Learn more about missing BASE report.

Files with missing lines Patch % Lines
fastdeploy/output/token_processor.py 78.94% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             develop    #7883   +/-   ##
==========================================
  Coverage           ?   63.86%           
==========================================
  Files              ?      462           
  Lines              ?    64488           
  Branches           ?     9880           
==========================================
  Hits               ?    41185           
  Misses             ?    20502           
  Partials           ?     2801           
Flag Coverage Δ
GPU 73.03% <80.00%> (?)
XPU 7.11% <0.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@PaddlePaddle-bot PaddlePaddle-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Paddle-CI-Agent | pr_review | 2026-05-22 13:49:56

📋 Review 摘要

PR 概述:优化 MTP + logprob 路径,仅传输实际需要的 logprob 列数(top_logprobs:0 场景下性能提升 10%),并将 Python 侧张量索引改为预转 list 减少重复开销。
变更范围custom_ops/gpu_ops/speculate_decoding/(3 个 C++ 算子)、fastdeploy/output/token_processor.pyfastdeploy/worker/gpu_model_runner.py
影响面 Tag[Speculative Decoding] [OP] [DataProcessor]

问题

级别 文件 概述
🟡 建议 speculate_save_output_with_topk.cc:127 max_num_logprobs << 8 存入 16 位高位,词表 > 65535 时 actual_topk 被静默截断
❓ 疑问 speculate_get_output_with_topk.cc:81 real_k 参数循环中已不再使用,是否为死代码?
📝 PR 规范 ModificationsUsage or CommandAccuracy Tests 三节为空

📝 PR 规范检查

PR 标题格式合规,已包含 [Optimization][Speculative Decoding] 两个合法 Tag;但描述模板中 ModificationsUsage or CommandAccuracy Tests 三节均为空白,未按模板填写。

标题建议(可直接复制):

  • [Optimization][Speculative Decoding] opt mtp logprob: reduce topk transfer to actual needed columns

PR 描述建议(可直接复制,必须复刻 checklist §D2 模板的完整结构):

## Motivation
MTP + logprob(top_logprobs:0) 场景下,旧代码始终传输固定 SPEC_LOGPROB_K+1=21 列 token/score,其中大量未使用的列被置为 -1/0.0。通过仅传输实际需要的 max_num_logprobs 列,可减少消息体写入量,性能提升约 10%。

## Modifications
- `speculate_save_output_with_topk.cc` / `mtp_save_first_token_with_topk.cc`:将 `max_num_logprobs` 打包入 `meta[1]` 高 16 位,写循环从 `SPEC_LOGPROB_K+1` 改为 `max_num_logprobs` 列,不再填充无用 -1/0.0 槽位
- `speculate_get_output_with_topk.cc`:从 `meta[1]` 解包 `actual_topk`,读循环改为 `actual_topk`- `token_processor.py`:Python 侧解包 `packed_meta1`,对 tokens/scores 张量做 `[:, :, :actual_topk]` 裁剪;将热路径中的逐元素 `.item()` / `.tolist()` 改为批量 `.tolist()` 预转换
- `gpu_model_runner.py`:移除 speculative decoding 路径中 `max_logprobs` 硬限为 20 的特判,改为按实际请求计算

## Usage or Command
N/A(性能优化,接口不变)

## Accuracy Tests
N/A(本次变更不修改推理逻辑,仅减少无效数据传输;top_logprobs 输出结果不变)

## Checklist

- [x] Add at least a tag in the PR title.
  - Tag list: [`[FDConfig]`,`[APIServer]`,`[Engine]`, `[Scheduler]`, `[PD Disaggregation]`, `[Executor]`, `[Graph Optimization]`, `[Speculative Decoding]`, `[RL]`, `[Models]`, `[Quantization]`, `[Loader]`, `[OP]`, `[KVCache]`, `[DataProcessor]`, `[BugFix]`, `[Docs]`, `[CI]`, `[Optimization]`, `[Feature]`, `[Benchmark]`, `[Others]`, `[XPU]`, `[HPU]`, `[GCU]`, `[DCU]`, `[Iluvatar]`, `[Metax]`]
  - You can add new tags based on the PR content, but the semantics must be clear.
- [ ] Format your code, run `pre-commit` before commit.
- [ ] Add unit tests. Please write the reason in this PR if no unit tests.
- [x] Provide accuracy results.
- [ ] If the current PR is submitting to the `release` branch, make sure the PR has been submitted to the `develop` branch, then cherry-pick it to the `release` branch with the `[Cherry-Pick]` PR tag.

总体评价

优化思路清晰,通过减少无效 topk 槽位传输和批量 .tolist() 转换来降低热路径开销,代码改动结构合理。主要关注点是 max_num_logprobs 打包到 16 位高位后的词表溢出边界问题,建议加防御断言;real_k 参数的清理也可一并处理。

// Pack message_flag (low 8 bits) and max_num_logprobs (high 16 bits) into
// meta[1]. Receiver unpacks both to avoid reading unused topk slots.
int max_num_logprobs = logprob_token_ids.shape()[1];
msg_sed.meta[1] = message_flag | (max_num_logprobs << 8);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 建议 max_num_logprobs 打包进 16 位高位存在截断风险

max_num_logprobs > 65535 时(例如用户请求全词表 logprobs,vocab_size > 65K),接收端 (meta[1] >> 8) & 0xFFFF 会静默截断,导致 actual_topk 错误,进而越界读写或丢失数据。

旧代码中 speculative decoding 的 max_logprobs 硬限为 20,本次 gpu_model_runner.py 移除该上限后,此场景已可触发。

建议在此处加防御断言:

PD_CHECK(max_num_logprobs <= 0xFFFF,
         "max_num_logprobs %d exceeds 16-bit limit", max_num_logprobs);

// Unpack message_flag (low 8 bits) and actual_topk (high 16 bits) from
// meta[1]. Keep packed value; Python unpacks message_flag and actual_topk.
output_tokens_data[1] = (int64_t)msg_rcv.meta[1];
output_tokens_data[2] = (int64_t)msg_rcv.meta[2];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ 疑问 real_k 参数是否已成死代码?

本次修改将循环条件从 k < real_k + 1 改为 k < actual_topkreal_k 参数不再出现在循环体中。但 Python 侧在调用此算子时仍传入 K=20token_processor.py 中的常量)作为 real_k 属性。

请确认 real_k 是否还被用于输出 tensor 的预分配或其他地方;若已完全废弃,建议清理该参数以避免后续维护误解。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants