[Optimization] Reduce logprob processing overhead by using actual topk instead of fixed K+1#7860
[Optimization] Reduce logprob processing overhead by using actual topk instead of fixed K+1#7860Sunny-bot1 wants to merge 1 commit into
Conversation
|
Thanks for your contribution! |
PaddlePaddle-bot
left a comment
There was a problem hiding this comment.
🤖 Paddle-CI-Agent | pr_review |
2026-05-19 21:05:13
📋 Review 摘要
PR 概述:通过 bit-pack 将 actual_topk 编入 mtext[1],使 logprob 数据传输与处理按实际列数而非固定 K+1=21 列进行,显著降低 TPOT。
变更范围:custom_ops/gpu_ops/(C++ 消息收发 op)、fastdeploy/output/token_processor.py
影响面 Tag:[OP] [DataProcessor]
问题
| 级别 | 文件 | 概述 |
|---|---|---|
| ❓ 疑问 | custom_ops/gpu_ops/get_output_msg_with_topk.cc:100 |
参数 k 在函数体中不再使用,可能触发 -Wunused-parameter 编译警告 |
| 🟡 建议 | custom_ops/gpu_ops/save_output_msg_with_topk.cc:121 |
custom op 变更未在 tests/operators/ 补充单测(A3 必查项) |
📝 PR 规范检查
标题含非官方 Tag [Logprob](不在 §D2 Tag list 中),按规范标题应仅含一个官方 Tag;Usage or Command、Accuracy Tests 两节内容为空(仅占位符);Checklist 全部未勾选。
标题建议(可直接复制):
[Optimization] Reduce logprob processing overhead by using actual topk instead of fixed K+1
PR 描述建议(可直接复制,必须复刻 checklist §D2 模板的完整结构):
## Motivation
开启 logprob(top_logprobs=0)时,性能下降明显,TPOT 比不开 logprob 高约 5ms。分析发现原因是 logprob 数据传输和处理均按固定的 K+1=21 列处理,而用户实际只需要 actual_topk=1 列,存在约 10 倍的冗余计算。
## Modifications
**save_output_msg_with_topk.cc**
- mtext[1] 改为 bit-pack 存储:bsz(低16位)| actual_topk(高16位)
- sender 循环改为 max_num_logprobs 次,stride 改为 max_num_logprobs
**get_output_msg_with_topk.cc**
- 从 mtext[1] 解包 bsz 和 actual_topk
- receiver 循环改为 actual_topk 次,stride 改为 actual_topk
**token_processor.py**
- 从 packed mtext[1] 解包 batch 和 actual_topk
- output_scores.numpy() 切片范围从 batch*21 缩小到 batch*actual_topk
- reshape 列数从固定 K+1 改为动态 actual_topk
- 提前将全量数组转换为 Python list,避免循环内多次 .tolist()
## Usage or Command
N/A(性能优化,无新增接口或命令)
## Accuracy Tests
N/A(本次变更仅优化数据传输和处理流程,不涉及模型前向计算,不影响输出精度)
## 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.
- [ ] 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.总体评价
整体思路清晰,通过 bit-pack 编码 actual_topk 消除了 K+1 固定宽度的冗余传输,C++ 与 Python 两端逻辑对称,消息结构体大小不变保证向后兼容。建议补充 operators 单测并修正 PR 规范后合入。
| for (int i = 0; i < bsz; i++) { | ||
| for (int j = 0; j < k + 1; j++) { | ||
| const int64_t offset = i * (K + 1) + j; | ||
| for (int j = 0; j < actual_topk; j++) { |
There was a problem hiding this comment.
❓ 疑问 参数 k 在函数体中已不再使用(原 for (int j = 0; j < k + 1; j++) 已替换为 actual_topk),但仍保留在函数签名和 PD_BUILD_STATIC_OP 的 Attrs 中(为保持调用侧 API 兼容性),可能触发 -Wunused-parameter 编译器警告。
建议在函数体开头显式抑制并注释原因:
(void)k; // retained for op-attr API compatibility; actual loop bound is from packed mtext[1]| // densely in the message buffer. | ||
| for (int j = 0; j < max_num_logprobs; j++) { | ||
| const int64_t offset = i * max_num_logprobs + j; | ||
| if (j == 0) { |
There was a problem hiding this comment.
🟡 建议 根据 checklist A3,custom_ops/ 下 op 变更需要在 tests/operators/ 补充单测。本次修改了 bit-pack 编码和 dense stride 传输逻辑,建议至少覆盖以下场景:
- bsz=1, actual_topk=1(top_logprobs=0 场景)
- bsz=N, actual_topk=K+1(满 topk 场景,验证不越界)
- 验证 save/get 端解包后数据一致性
若 CI 环境暂不支持运行 op 单测,请在 PR 描述中说明原因。
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #7860 +/- ##
==========================================
Coverage ? 63.36%
==========================================
Files ? 462
Lines ? 64370
Branches ? 9871
==========================================
Hits ? 40786
Misses ? 20810
Partials ? 2774
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
CI报告基于以下代码生成(30分钟更新一次): 1 任务总览有 2 个 required 任务失败,阻塞合并,需优先处理。
2 任务状态汇总2.1 Required任务 : 8/10 通过
2.2 可选任务 — 28/31 通过
3 失败详情(仅 required)Run FastDeploy Unit Tests and Coverage / run_tests_with_coverage — 用例失败(置信度: 高)Run FastDeploy Unit Tests and Coverage / run_tests_with_coverage
失败用例:
根因详情: 关键日志: 修复建议:
修复建议摘要: 更新测试,将output_tokens[1,0]改为新packing格式 关联变更: xpu_4cards_case_test / run_xpu_4cards_cases — 超时(置信度: 中)xpu_4cards_case_test / run_xpu_4cards_cases
失败用例:
根因详情: 关键日志: 修复建议:
修复建议摘要: 检查XPU后端是否已适配新packing格式 |
Motivation
开启 logprob(top_logprobs=0)时,性能下降明显,TPOT 比不开 logprob 高约 5ms。分析发现开销大的原因之一是 logprob 数据传输和处理均按固定的 K+1=21 列处理,而用户实际只需要 actual_topk=1 列,存在约 10 倍的冗余计算。
save_output_topk C++ op 中:
get_output_topk C++ op 中:
token_processor.py 中:
拷贝 batch*21 个 float(10752),以及 per-request tolist()
每行处理 21 个元素
Modifications
save_output_msg_with_topk.cc
get_output_msg_with_topk.cc
token_processor.py
top_logprobs=0,concurrency=256,GLM-4.5-Air,TP8:
Usage or Command
Accuracy Tests
Checklist
[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]]pre-commitbefore commit.releasebranch, make sure the PR has been submitted to thedevelopbranch, then cherry-pick it to thereleasebranch with the[Cherry-Pick]PR tag.