Skip to content

perf: Qwen3 offline inference — hybrid attention backend, fused rms_norm_rope, chunked prefill + prompt-lookup spec decoding - #585

Open
shsaihdsaiudh wants to merge 4 commits into
InfiniTensor:mainfrom
shsaihdsaiudh:perf/perf-baseline
Open

shsaihdsaiudh wants to merge 4 commits into
InfiniTensor:mainfrom
shsaihdsaiudh:perf/perf-baseline

Conversation

@shsaihdsaiudh

Copy link
Copy Markdown

概述 / Summary

LLAISys-26s 项目阶段交付(Project #2 性能优化方向)。在 Qwen3 离线推理路径上落地四层优化,全部默认不改变现有行为(新后端与新调度均为显式开启):

  1. Hybrid attention 后端:prefill/混合 batch 走 FlashAttention-2 varlen,纯 decode 走自研 paged splitkv kernel(经 strided 视图直读 FA 的 BSHD cache),--attn-backend hybrid 开启。
  2. rms_norm_rope 融合:Qwen3 paged 路径调用 InfiniCore 新增融合算子(依赖配套 InfiniCore PR,见下);full-rotary 且无后端设备自动回退非融合链路。
  3. 图化加固与图外开销:paged_compiler 捕获失败的 barrier 对称、非 HYBRID 不录双图、打包 H2D + 采样伴随图、decode 路由 hint(host 侧,零设备同步)。
  4. chunked prefill + prompt-lookup 投机采样(纯 Python 调度层,默认关闭):INFINILM_ENABLE_CHUNKED_PREFILL=1--speculative-method prompt_lookup 开启;spec×chunked 融合、融合单前向 verify(固定 b×(k+1) 形状)、自适应收益门控。

另含 dev_perf/ 双引擎(InfiniLM/vLLM)基线压测工具与 v1~v16 完整测量日志(dev_perf/gap_analysis.md),results 原始数据不入库(本地保留哈希归档)。

测量结果(RTX 5090,Qwen3-0.6B/1.7B,bf16;全部 ABBA 交错对拍)

hybrid 后端 vs flash-attn(e2e,0.6B,no-graph):w1 -33.7%、w2 -8.0%、w3 -37.2%、w4 -36.2%;vs paged-attn 长 prefill w2 -17.2%,其余持平。1.7B decode w1 -22.5%(vs FA)。

rms_norm_rope 融合(0.6B ABBA e2e):5090 -4%~-8%;5060 Ti -4%~-23%。

chunked prefill(w6 decode-stall:8 条 decode 流 + 第 64 步注入 6.5k tok prefill):decode 流最坏 ITL 尖峰削 3.5×(0.6B)/ 4.4×(1.7B),p90 几乎不动;代价为注入请求 TTFT +34~40%、e2e ~3%。

prompt-lookup 投机采样(k=4,hybrid+graph 基线):w4/w5/w7 2.1~2.4×,w6 吞吐 +57%,w1 打平(门控生效,无门控首轮 -46%)。

vs vLLM 0.28(健康平台 5090 全负载矩阵):vLLM 仍全面领先——w3 吞吐 +42%+80%、w2 e2e -36%-50%;1.7B 单请求 decode 差距收敛到 6%~11%。该差距结构(批处理调度/chunked/全图 decode)是后续方向,详见 gap_analysis.md v10。

正确性

  • 贪心解码逐 token 对拍(dev_perf/compare_outputs.py):hybrid vs paged-attn、融合 vs 非融合、chunked on/off(0.6B 全矩阵 43/43 请求 exact,1.7B 9/9)、投机 vs 非投机(高命中负载 w5/w7 全 exact;开放生成的分歧定位为 near-tie argmax 翻转,top-2 logit 间隙 0~0.125,非逻辑 bug,见 v16)。
  • 新增 stub 单测(无需 GPU):test/test_chunked_prefill.py 4 例、test/test_prompt_lookup_spec.py 7 例,本机全绿。
  • 已知边界:大 batch(bs>32)投机自动回退;verify/融合前向暂未图化(改动点已定位,见 v16 遗留节)。

复现步骤

# 需先构建配套 InfiniCore 分支(feat/rms-norm-rope,见关联 PR)
xmake build _infinilm && xmake install
python dev_perf/bench.py --engine infinilm --model Qwen/Qwen3-0.6B \
    --enable-graph --attn-backend hybrid --dump-outputs
# chunked prefill
INFINILM_ENABLE_CHUNKED_PREFILL=1 python dev_perf/bench.py --engine infinilm ... --only w6_decode_stall
# 投机采样
python dev_perf/bench.py --engine infinilm ... --speculative-method prompt_lookup --num-draft-tokens 4

各轮完整命令与负载矩阵定义见 dev_perf/README.mdgap_analysis.md 对应章节。

平台状态

平台 状态
NVIDIA(RTX 5090 / 5060 Ti,sm_120/sm_86) 全部功能实测通过(上表数据)
CPU 融合算子有 CPU 实现;引擎路径本 PR 未实测
其他(Metax/Ascend/Cambricon/...) 融合算子按设备门控回退非融合链路,行为与上游一致

依赖与 CI

  • 依赖配套 InfiniCore PR(rms_norm_rope 算子):feat: add fused rms_norm_rope operator (per-head RMSNorm + RoPE; CPU, NVIDIA) InfiniCore#1567 。不合并时本 PR 中 qwen3_attention.cpp#include "infinicore/ops/rms_norm_rope.hpp" 无法编译。CI 需以 infinicore_branch=feat/rms-norm-rope 运行,或待算子 PR 合入后重跑。
  • CI 矩阵已追加 --enable-paged-attn --enable-graph --attn=hybrid(nvidia gpu_benchtest)。
  • 本 PR 基于上游 main(270feb3e)最新提交开发,合并干净。

English summary: Qwen3 offline-inference performance work — hybrid FA2-prefill/splitkv-decode attention backend (e2e -8%-37% vs flash-attn alone on 5090), fused rms_norm_rope via new InfiniCore op (e2e -4%-8%), paged-graph hardening, plus opt-in chunked prefill (worst ITL spike -3.54.4x) and prompt-lookup speculative decoding (2.12.4x on high-hit workloads). All new paths default off / explicit opt-in; correctness verified by token-exact greedy diffing and 11 no-GPU stub tests. Full measurement log in dev_perf/gap_analysis.md. Depends on the companion InfiniCore PR for the fused op (CI: infinicore_branch=feat/rms-norm-rope).

…ed rms_norm_rope for Qwen3

- New HYBRID attention backend: prefill/mixed batches route to FlashAttention-2
  varlen, pure decode reuses the in-house paged splitkv kernel reading FA's
  BSHD cache through strided views. 5090 ABBA vs flash-attn e2e: w1 -33.7%,
  w3 -37.2%, w4 -36.2% (0.6B); hybrid is the best single backend on 5090.
- Qwen3 paged path calls InfiniCore's fused rms_norm_rope op (full-rotary,
  devices with a backend only; others fall back to the unfused chain).
  0.6B ABBA e2e -4%~-8% on 5090.
- Decode fills max_sequence_length from host-side length tensors so the
  hybrid layer can route long-context decode to FA's kvcache kernel.
- Expose --attn=hybrid in base_config and add it to the nvidia gpu_benchtest
  CI matrix. Numbers: dev_perf/gap_analysis.md v5-v9, v12.
- paged_compiler: symmetric barriers on capture failure, skip dual-graph
  recording for non-HYBRID backends, restrict packing to CPU tensors.
- Decode-step host overhead: packed H2D for per-step input tensors and a
  sampling companion graph (v11, dev_perf/gap_analysis.md).
- infer_engine: lenient host-side max over per-request length tensors feeds
  the decode routing hint without any device sync.
…ng (default off)

- Python scheduler layer: chunked prefill with prefill/decode mixed batching
  (INFINILM_ENABLE_CHUNKED_PREFILL=1). 5090: worst decode ITL spike under a
  mid-stream 6.5k-token prefill injection cut 3.5x (0.6B) / 4.4x (1.7B), p90
  unchanged; 0.6B full matrix 43/43 requests token-exact.
- Prompt-lookup speculative decoding: zero-training n-gram draft, fused
  single-forward verify (fixed b x (k+1) shape), spec x chunked compatible,
  adaptive profit gating (INFINILM_SPEC_MIN_AVG_TOKENS/_GATE_WINDOW/
  _GATE_COOLDOWN) so low-hit workloads do not regress. 5090: w4/w5/w7
  2.1~2.4x, w6 throughput +57%, w1 flat (gate engaged); high-hit workloads
  token-exact vs non-speculative.
- Stub-based tests: test_chunked_prefill.py (4 cases) and
  test_prompt_lookup_spec.py (7 cases), no GPU required.
  Numbers: dev_perf/gap_analysis.md v13/v14/v16.
- dev_perf/bench.py: same workload matrix against InfiniLM and vLLM, fair
  decoding conventions (greedy, ignore_eos, identical prompts), results as
  JSON; compare_outputs.py does token-exact cross-engine diffing.
- workload.py: w1-w7 matrix incl. concurrent-prefill, decode-stall
  injection and repetitive-copy (spec decoding acceptance demo).
- gap_analysis.md: v1-v16 measurement log — num_blocks cliff analysis,
  nsys kernel attribution (prefill attention 13.5x behind FA2), backend
  ABBA tables, vs-vLLM healthy-platform comparison, acceptance records.
- results/ data stays out of git (hashes + head-32 tokens only locally);
  numbers are reproduced with the commands in gap_analysis.md.
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.

1 participant