Skip to content

Optimize Triton decoding kernel for long context - #2394

Merged
merrymercy merged 7 commits into
sgl-project:mainfrom
ispobock:flash-decoding
Dec 8, 2024
Merged

merrymercy merged 7 commits into
sgl-project:mainfrom
ispobock:flash-decoding

Conversation

@ispobock

@ispobock ispobock commented Dec 8, 2024 •

Copy link
Copy Markdown
Collaborator

Motivation

As mentioned in #2271, the original triton decoding kernel has significant performance degradation on long context. We refactored the kernel and adapted the flash decoding implementation from lightllm. Currently, the long context speed decay has been alleviated a lot.

Benchmark

Tested for input 128, output 2048.

Triton (this PR) num_kv_splits=8: 150->138

$ python3 -m sglang.bench_offline_throughput --model meta-llama/Llama-3.1-8B-Instruct --dataset-name random --num-prompt 1 --random-input 128 --random-output 2048 --random-range 1 --attention-backend triton

[2024-12-08 08:37:24 TP0] Decode batch. #running-req: 1, #token: 194, token usage: 0.00, gen throughput (token/s): 150.66, #queue-req: 0

[2024-12-08 08:37:37 TP0] Decode batch. #running-req: 1, #token: 2154, token usage: 0.00, gen throughput (token/s): 138.86, #queue-req: 0

We can increase the --triton-attention-num-kv-splits to get better performance on long context.

Triton (this PR) num_kv_splits=16: 150->144

python3 -m sglang.bench_offline_throughput --model meta-llama/Llama-3.1-8B-Instruct --dataset-name random --num-prompt 1 --random-input 128 --random-output 2048 --random-range 1 --attention-backend triton --triton-attention-num-kv-splits 16

[2024-12-08 08:40:28 TP0] Decode batch. #running-req: 1, #token: 194, token usage: 0.00, gen throughput (token/s): 150.18, #queue-req: 0

[2024-12-08 08:40:42 TP0] Decode batch. #running-req: 1, #token: 2154, token usage: 0.00, gen throughput (token/s): 144.00, #queue-req: 0

Triton (main branch): 147->126

$ python3 -m sglang.bench_offline_throughput --model meta-llama/Llama-3.1-8B-Instruct --dataset-name random --num-prompt 1 --random-input 128 --random-output 2048 --random-range 1 --attention-backend triton

[2024-12-08 08:35:01 TP0] Decode batch. #running-req: 1, #token: 194, token usage: 0.00, gen throughput (token/s): 147.93, #queue-req: 0

[2024-12-08 08:35:15 TP0] Decode batch. #running-req: 1, #token: 2154, token usage: 0.00, gen throughput (token/s): 126.67, #queue-req: 0

Flashinfer: 143->143

$ python3 -m sglang.bench_offline_throughput --model meta-llama/Llama-3.1-8B-Instruct --dataset-name random --num-prompt 1 --random-input 128 --random-output 2048 --random-range 1

[2024-12-08 08:43:15 TP0] Decode batch. #running-req: 1, #token: 194, token usage: 0.00, gen throughput (token/s): 143.84, #queue-req: 0

[2024-12-08 08:43:29 TP0] Decode batch. #running-req: 1, #token: 2154, token usage: 0.00, gen throughput (token/s): 143.24, #queue-req: 0

o,
req_to_token,
b_req_idx,
b_start_loc,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove this in the func signature of decode_attention_fwd?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Sure. max_len_in_batch and triton_attention_reduce_in_fp32 may also need to be removed.

forward_batch.batch_size,
self.num_head,
self.num_kv_splits,
self.v_head_dim + 1,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

After this, we do not need to reduce the cuda graph max bs for deepseek models?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Let me verify it.

@merrymercy
merrymercy merged commit 7dc66fc into sgl-project:main Dec 8, 2024
timethink pushed a commit to timethink/sglang that referenced this pull request Mar 9, 2025
@WANG-GH

WANG-GH commented Mar 11, 2025

Copy link
Copy Markdown
Contributor

Hello, does issue #2271 still need further development? I saw this issue and would like to give it a try. However, I noticed that you are currently working on fixing it. Could you share the progress so far? Do you still need any help? @ispobock @merrymercy

@MLKoz2

MLKoz2 commented Mar 10, 2026 •

Copy link
Copy Markdown

This issue didn't aim to solve the problem with speculative decoding using Triton, did it?
(MTP/EAGLE3 slows down after a few thousands generated tokens with triton kernel, but with flashinfer there is no slow down even after 20k+ generated tokens)

mmangkad pushed a commit that referenced this pull request Sep 26, 2026
Since #2394, _fwd_kernel_stage1 has reduced q*k in bf16, so every partial
sum is rounded in a reduction order the compiler picks and may change
between releases. test_grouped_decode_attention (atol=3e-2) fails on ~50%
of seeds on both triton 3.7.1 and 3.8.0; the pinned seed 42 merely
happened to pass on 3.7.1 and fails on 3.8.0 (pulled in by torch 2.14).
This is a latent precision bug, not a triton regression, so fix the
kernel rather than loosen the tolerance.

Cast the bf16 product to fp32 before the reduction instead of upcasting
the operands: same accuracy (0/100 seeds fail, worst normal-vs-grouped
gap 0.055 -> 0.016) without materializing a fp32 [BLOCK_N, D] tile, so
D=128 stays at 80 registers and short-sequence decode does not regress.
The D=576 variant spills less and gets faster (749 -> 470 us at B=8,
S=512, H=128 on H200).
mmangkad pushed a commit that referenced this pull request Sep 26, 2026
Since #2394, _fwd_kernel_stage1 has reduced q*k in bf16, so every partial
sum is rounded in a reduction order the compiler picks and may change
between releases. test_grouped_decode_attention (atol=3e-2) fails on ~50%
of seeds on both triton 3.7.1 and 3.8.0; the pinned seed 42 merely
happened to pass on 3.7.1 and fails on 3.8.0 (pulled in by torch 2.14).
This is a latent precision bug, not a triton regression, so fix the
kernel rather than loosen the tolerance.

Cast the bf16 product to fp32 before the reduction instead of upcasting
the operands: same accuracy (0/100 seeds fail, worst normal-vs-grouped
gap 0.055 -> 0.016) without materializing a fp32 [BLOCK_N, D] tile, so
D=128 stays at 80 registers and short-sequence decode does not regress.
The D=576 variant spills less and gets faster (749 -> 470 us at B=8,
S=512, H=128 on H200).
mmangkad pushed a commit that referenced this pull request Sep 26, 2026
Since #2394, _fwd_kernel_stage1 has reduced q*k in bf16, so every partial
sum is rounded in a reduction order the compiler picks and may change
between releases. test_grouped_decode_attention (atol=3e-2) fails on ~50%
of seeds on both triton 3.7.1 and 3.8.0; the pinned seed 42 merely
happened to pass on 3.7.1 and fails on 3.8.0 (pulled in by torch 2.14).
This is a latent precision bug, not a triton regression, so fix the
kernel rather than loosen the tolerance.

Cast the bf16 product to fp32 before the reduction instead of upcasting
the operands: same accuracy (0/100 seeds fail, worst normal-vs-grouped
gap 0.055 -> 0.016) without materializing a fp32 [BLOCK_N, D] tile, so
D=128 stays at 80 registers and short-sequence decode does not regress.
The D=576 variant spills less and gets faster (749 -> 470 us at B=8,
S=512, H=128 on H200).
mmangkad pushed a commit that referenced this pull request Sep 26, 2026
Since #2394, _fwd_kernel_stage1 has reduced q*k in bf16, so every partial
sum is rounded in a reduction order the compiler picks and may change
between releases. test_grouped_decode_attention (atol=3e-2) fails on ~50%
of seeds on both triton 3.7.1 and 3.8.0; the pinned seed 42 merely
happened to pass on 3.7.1 and fails on 3.8.0 (pulled in by torch 2.14).
This is a latent precision bug, not a triton regression, so fix the
kernel rather than loosen the tolerance.

Cast the bf16 product to fp32 before the reduction instead of upcasting
the operands: same accuracy (0/100 seeds fail, worst normal-vs-grouped
gap 0.055 -> 0.016) without materializing a fp32 [BLOCK_N, D] tile, so
D=128 stays at 80 registers and short-sequence decode does not regress.
The D=576 variant spills less and gets faster (749 -> 470 us at B=8,
S=512, H=128 on H200).
mmangkad pushed a commit that referenced this pull request Sep 26, 2026
Since #2394, _fwd_kernel_stage1 has reduced q*k in bf16, so every partial
sum is rounded in a reduction order the compiler picks and may change
between releases. test_grouped_decode_attention (atol=3e-2) fails on ~50%
of seeds on both triton 3.7.1 and 3.8.0; the pinned seed 42 merely
happened to pass on 3.7.1 and fails on 3.8.0 (pulled in by torch 2.14).
This is a latent precision bug, not a triton regression, so fix the
kernel rather than loosen the tolerance.

Cast the bf16 product to fp32 before the reduction instead of upcasting
the operands: same accuracy (0/100 seeds fail, worst normal-vs-grouped
gap 0.055 -> 0.016) without materializing a fp32 [BLOCK_N, D] tile, so
D=128 stays at 80 registers and short-sequence decode does not regress.
The D=576 variant spills less and gets faster (749 -> 470 us at B=8,
S=512, H=128 on H200).
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.

4 participants