Repository navigation
[Perf] Improve GLM-5.3-Flash DFlash decoding on B300 - #42489
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
BBuf
left a comment
There was a problem hiding this comment.
I would split the optional FP8 MoE layout into a separate PR. It is independent of the DFlash changes and needs its own weight reload/offload validation.
Please include the full baseline/optimized commands, benchmark script and commit SHAs, especially linear-attn-verify-backend, and confirm the results on this head. The Triton KDA change won't run when verify uses FlashInfer.
Please also report peak loading memory, memory after graph capture, and final max_total_num_tokens for both runs with the same settings.
| for expert in weight: | ||
| shuffled = shuffle_matrix_a(expert.view(torch.uint8), epilogue_tile_m) | ||
| blocked = convert_to_block_layout(shuffled, _FP8_MOE_BLOCK_K) | ||
| expert.view(torch.uint8).copy_(blocked.reshape_as(expert)) |
There was a problem hiding this comment.
On a partial weight update, end_weight_update() postprocesses every layer, so weights that weren't reloaded get shuffled a second time. Please undo the packing in restore_weights_before_loading(), or only repack weights that were actually reloaded. The zero-filled view test won't catch this; check that untouched weights stay unchanged.
There was a problem hiding this comment.
moved moe to a separate branch. it now restores the original layout before reload; nonzero-weight tests confirm untouched weights stay unchanged.
|
|
||
| def get_fp8_moe_weights(layer: Module) -> tuple[torch.Tensor, torch.Tensor]: | ||
| weights = (layer.w13_weight, layer.w2_weight) | ||
| cached = getattr(layer, "_flashinfer_moe_weights", weights) |
There was a problem hiding this comment.
Do we need to cache these views? view() doesn't copy data, and CUDA graph replay won't repeat this Python code. Creating the view from the current parameters would remove the cache_views option and offload checks, and avoid having to refresh aliases after reload.
There was a problem hiding this comment.
removed the cache and offload checks. views now come directly from the current parameters
| ): | ||
| arch = get_jit_cuda_arch() | ||
| if (arch.major, arch.minor) == (10, 3): | ||
| BV = 4 |
There was a problem hiding this comment.
Please move this SM103 rule into _select_recurrent_launch_config instead of overriding its result here. Keep the rounding requirement tied to the selected configuration and explain why this exact shape needs it.
There was a problem hiding this comment.
moved into _select_recurrent_launch_config(). the narrow kda tile keeps separate fp32 multiply/add rounding to preserve parity
| pdl_kwargs = ( | ||
| {"USE_GDC": True, "launch_pdl": True} if is_arch_support_pdl() else {} | ||
| ) | ||
| if use_pdl and (T, D, x.dtype) == (64, 128, torch.bfloat16): |
There was a problem hiding this comment.
Why is BT=8 restricted to exactly (64, 128, bfloat16)? Please document the reason, or use a workload-based rule if the gain also applies to nearby shapes.
There was a problem hiding this comment.
tested nearby shapes and expanded bt8 to 8–256 rows for sigmoid rmsnorm on sm103, with bf16 and d=128
| SGLANG_TRTLLM_MOE_PDL_MAX_TOKENS = EnvInt(8192) | ||
| # Use FlashInfer's fused atomic CUTLASS/CuTe DSL MoE finalize. | ||
| SGLANG_FLASHINFER_MOE_FUSED_FINALIZE = EnvBool(False) | ||
| SGLANG_FLASHINFER_FP8_MOE_BLOCK_LAYOUT = EnvBool(False) |
There was a problem hiding this comment.
Can we avoid adding another environment variable and enable this layout conversion automatically on SM100 when using FlashInfer FP8 MoE with block_size=[128, 128]?
There was a problem hiding this comment.
removed the flag. the separate moe branch enables this automatically for supported sm100-family fp8 configurations
Motivation
Reduce synchronization and kernel overhead in GLM-5.3-Flash DFlash decoding. The DFlash/KDA-only comparison improves average decode throughput from 1091.85 to 1199.72 tokens/s (+9.88%) on 8×B300, with essentially unchanged memory usage.
Modifications
The FP8 MoE weight-layout optimization has been split out of this PR.
Accuracy Tests
Paired service checks matched output tokens and speculative acceptance statistics. Real-rejection cases also matched the checked generated-token logprobs.
Kernel checks cover KDA output/state parity and output/rstd parity for nearby norm shapes. Regression checks cover pooled metadata CUDA Graph replay and sequence-length bounds.
Speed Tests and Profiling
GLM-5.3-Flash + DFlash2, 8×B300, TP8, concurrency 1, 8192 input / 1024 output tokens, draft block size 8. Target linear-attention verification explicitly uses Triton (
--linear-attn-verify-backend triton); draft attention uses FA4.Three warmups followed by three rounds of two requests, without a profiler. The comparison pairs the same six measured inputs from the baseline and candidate records and aggregates decode throughput over those requests.
Timing runs from receipt of the first token to SSE
[DONE]. Timed requests had an acceptance length of 8; real-rejection cases were validated separately.Before optimization, NSYS identified blocking sequence-length transfers and repeated pooled-page-table work; NCU showed low parallelism in KDA recurrence and gated norm.
Memory and KV Capacity
Both runs use the same model, draft, dependencies, and TP8 settings. Target and draft graph buckets are
bs=[1]on both sides. Memory was measured separately, after all graphs were captured and before any inference requests.max_total_num_tokensLoading peaks are total process-memory samples from NVML with a target 50 ms sampling interval. Capacity was confirmed through the scheduler and server interface.
Performance and memory were measured on the recorded snapshots before the subsequent main merge.
Reproduction scripts, launch commands, source revisions, environment, and measurement summaries
CI States
Latest PR Test (Base): ❌ Run #37287781676
Latest PR Test (Extra): ⏳ Run #37287781460
Latest PR Test (AMD ROCm 10): ❌ Run #37287781809