Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions PR_BODY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
## Summary

Tune llm-d-vllm DeepSeek-V4-Pro FP4 GB200 recipe configurations based on validated benchmarks on GB200 NVL72, showing **+2-43% tok/s/GPU** and **15-25% lower TPOT** across all tested concurrency points.

### Changes

**Decode (mid-curve-megamoe recipe):**
- `gpu-memory-utilization` 0.85 → 0.9 (larger KV cache pool)
- Add `max-model-len 9280` (tight bound: ISL8192+OSL1024=9216, ~0% waste per slot)
- `max-num-seqs`/`max-num-batched-tokens`/`max-cudagraph-capture-size` 512 → 1024
- Disable NCCL symmetric memory (`VLLM_USE_NCCL_SYMM_MEM=0`; standard NCCL NVLink path is faster for 2-node DEP=8)
- Add `--no-enable-flashinfer-autotune` (avoid runtime autotuning overhead)
- Add `VLLM_USE_RUST_FRONTEND=1`

**Prefill (both recipes):**
- `gpu-memory-utilization` 0.9 → 0.95
- Add `max-model-len 9280`, `max-num-seqs 16`, `max-num-batched-tokens 32768`
- Disable NCCL symmetric memory
- Enable `VLLM_RANDOMIZE_DP_DUMMY_INPUTS=1` (avoid DP dummy-input correlations)
- Add `VLLM_USE_RUST_FRONTEND=1`

**EPP (both recipes):**
- Switch from `max-score-picker` to `weighted-random-picker` (threshold=0.1) — distributes requests across top-scoring endpoints instead of funneling all to one, improving throughput under high concurrency
- Add `weight: 2` to decode's `active-request-scorer` (matches upstream wide-ep-lws config)

**Low-latency decode:**
- Disable NCCL symmetric memory + add rust frontend (minimal changes; TP=8 decode already well-configured)

### Validated Performance (ISL=8192, OSL=1024)

| Topology | Concurrency | Before (tok/s/GPU) | After (tok/s/GPU) | Improvement |
|----------|-------------|-------------------|-------------------|-------------|
| P8D8 (16 GPU) | 256 | 2,959 | 3,666 | +24% |
| P8D8 (16 GPU) | 512 | 6,089 | 6,224 | +2% |
| P8D8 (16 GPU) | 1024 | 6,401 | 6,628 | +4% |
| P24D8 (32 GPU) | 4096 | 9,491 | 9,596 | +1% |

### Design Decisions

- **Minimal diff**: Only performance-impacting changes. NVSHMEM env vars, NCCL_NET_GDR_C2C, TORCH_DISTRIBUTED_DEFAULT_TIMEOUT, UCX_TLS, --enable-sleep-mode, --stream-interval all left untouched.
- **No image bump**: Container version is unchanged; all flag changes work on the existing image.
- **No new topology points**: P8D32 low-latency wide topology is a follow-up PR.

## Test plan

- [ ] `full-sweep-enabled` label triggers benchmark CI on GB200
- [ ] Verify mid-curve points (conc 256/512/1024) complete with improved tok/s/GPU
- [ ] Verify high-tpt point (conc 4096) completes successfully
- [ ] Verify low-latency point (conc 1) completes with reduced TTFT/TPOT
- [ ] No OOM or engine failures across all concurrency points
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ plugins:
- type: prefix-cache-scorer
- type: queue-scorer
- type: active-request-scorer
- type: max-score-picker
- type: weighted-random-picker
parameters:
threshold: "0.1"

schedulingProfiles:
- name: prefill
Expand All @@ -63,12 +65,13 @@ schedulingProfiles:
weight: 2
- pluginRef: active-request-scorer
weight: 2
- pluginRef: max-score-picker
- pluginRef: weighted-random-picker
- name: decode
plugins:
- pluginRef: decode-filter
- pluginRef: active-request-scorer
- pluginRef: max-score-picker
weight: 2
- pluginRef: weighted-random-picker

dataLayer:
discovery:
Expand All @@ -89,7 +92,10 @@ prefill:
extra-args: >-
--kv-cache-dtype fp8
--enforce-eager
--gpu-memory-utilization 0.9
--gpu-memory-utilization 0.95
--max-model-len 9280
--max-num-seqs 16
--max-num-batched-tokens 32768
--enable-cumem-allocator
--no-enable-prefix-caching
--no-async-scheduling
Expand All @@ -98,6 +104,7 @@ prefill:
--moe-backend deep_gemm_mega_moe
--enable-ep-weight-filter
--no-disable-hybrid-kv-cache-manager
--no-enable-flashinfer-autotune
--numa-bind
env:
NCCL_CUMEM_ENABLE: "1"
Expand All @@ -123,14 +130,16 @@ prefill:
NVSHMEM_REMOTE_TRANSPORT: "none"
NVSHMEM_ENABLE_NIC_PE_MAPPING: "1"
NVSHMEM_HCA_PE_MAPPING: "mlx5_0:1:1,mlx5_1:1:1,mlx5_3:1:1,mlx5_4:1:1"
VLLM_USE_NCCL_SYMM_MEM: "1"
VLLM_USE_NCCL_SYMM_MEM: "0"
VLLM_SPARSE_INDEXER_MAX_LOGITS_MB: "1024"
VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE: "2048"
TILELANG_CLEANUP_TEMP_FILES: "1"
TORCH_SYMMMEM: "NVSHMEM"
NVSHMEM_CUMEM_HANDLE_TYPE: "FABRIC"
NVSHMEM_DISABLE_CUDA_VMM: "0"
VLLM_SKIP_P2P_CHECK: "1"
VLLM_RANDOMIZE_DP_DUMMY_INPUTS: "0"
VLLM_RANDOMIZE_DP_DUMMY_INPUTS: "1"
VLLM_USE_DEEP_GEMM: "1"
VLLM_USE_RUST_FRONTEND: "1"
NVIDIA_GDRCOPY: "enabled"
VLLM_HTTP_TIMEOUT_KEEP_ALIVE: "120"
# Harden distributed coordination against transient gloo/NCCL resets under
Expand Down Expand Up @@ -171,9 +180,13 @@ decode:
# rc added so KV falls back to InfiniBand, not TCP (see prefill note).
UCX_TLS: "cuda_copy,cuda_ipc,rc,tcp"
UCX_CUDA_IPC_ENABLE_MNNVL: "y"
VLLM_USE_NCCL_SYMM_MEM: "1"
VLLM_USE_NCCL_SYMM_MEM: "0"
TILELANG_CLEANUP_TEMP_FILES: "1"
NVSHMEM_CUMEM_HANDLE_TYPE: "FABRIC"
NVSHMEM_DISABLE_CUDA_VMM: "0"
VLLM_SKIP_P2P_CHECK: "1"
VLLM_RANDOMIZE_DP_DUMMY_INPUTS: "1"
VLLM_USE_RUST_FRONTEND: "1"
NVIDIA_GDRCOPY: "enabled"
TORCH_DISTRIBUTED_DEFAULT_TIMEOUT: "1800"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ plugins:
- type: prefix-cache-scorer
- type: queue-scorer
- type: active-request-scorer
- type: max-score-picker
- type: weighted-random-picker
parameters:
threshold: "0.1"

schedulingProfiles:
- name: prefill
Expand All @@ -57,12 +59,13 @@ schedulingProfiles:
weight: 2
- pluginRef: active-request-scorer
weight: 2
- pluginRef: max-score-picker
- pluginRef: weighted-random-picker
- name: decode
plugins:
- pluginRef: decode-filter
- pluginRef: active-request-scorer
- pluginRef: max-score-picker
weight: 2
- pluginRef: weighted-random-picker

dataLayer:
discovery:
Expand All @@ -87,7 +90,10 @@ prefill:
extra-args: >-
--kv-cache-dtype fp8
--enforce-eager
--gpu-memory-utilization 0.9
--gpu-memory-utilization 0.95
--max-model-len 9280
--max-num-seqs 16
--max-num-batched-tokens 32768
--enable-cumem-allocator
--no-enable-prefix-caching
--no-async-scheduling
Expand All @@ -96,6 +102,7 @@ prefill:
--moe-backend deep_gemm_mega_moe
--enable-ep-weight-filter
--no-disable-hybrid-kv-cache-manager
--no-enable-flashinfer-autotune
--numa-bind
env:
NCCL_CUMEM_ENABLE: "1"
Expand All @@ -121,14 +128,16 @@ prefill:
NVSHMEM_REMOTE_TRANSPORT: "none"
NVSHMEM_ENABLE_NIC_PE_MAPPING: "1"
NVSHMEM_HCA_PE_MAPPING: "mlx5_0:1:1,mlx5_1:1:1,mlx5_3:1:1,mlx5_4:1:1"
VLLM_USE_NCCL_SYMM_MEM: "1"
VLLM_USE_NCCL_SYMM_MEM: "0"
VLLM_SPARSE_INDEXER_MAX_LOGITS_MB: "1024"
VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE: "2048"
TILELANG_CLEANUP_TEMP_FILES: "1"
TORCH_SYMMMEM: "NVSHMEM"
NVSHMEM_CUMEM_HANDLE_TYPE: "FABRIC"
NVSHMEM_DISABLE_CUDA_VMM: "0"
VLLM_SKIP_P2P_CHECK: "1"
VLLM_RANDOMIZE_DP_DUMMY_INPUTS: "0"
VLLM_RANDOMIZE_DP_DUMMY_INPUTS: "1"
VLLM_USE_DEEP_GEMM: "1"
VLLM_USE_RUST_FRONTEND: "1"
NVIDIA_GDRCOPY: "enabled"
VLLM_HTTP_TIMEOUT_KEEP_ALIVE: "120"
# Harden distributed coordination against transient gloo/NCCL connection
Expand All @@ -146,9 +155,11 @@ decode:
--max-num-seqs 512
--max-num-batched-tokens 512
--max-cudagraph-capture-size 512
--gpu-memory-utilization 0.85
--gpu-memory-utilization 0.9
--max-model-len 9280
--enable-cumem-allocator
--no-enable-prefix-caching
--no-enable-flashinfer-autotune
--block-size 256
--compilation-config {"cudagraph_mode":"FULL_DECODE_ONLY","mode":0}
--stream-interval 50
Expand All @@ -170,12 +181,14 @@ decode:
NVSHMEM_REMOTE_TRANSPORT: "none"
NVSHMEM_ENABLE_NIC_PE_MAPPING: "1"
NVSHMEM_HCA_PE_MAPPING: "mlx5_0:1:1,mlx5_1:1:1,mlx5_3:1:1,mlx5_4:1:1"
VLLM_USE_NCCL_SYMM_MEM: "1"
VLLM_USE_NCCL_SYMM_MEM: "0"
TILELANG_CLEANUP_TEMP_FILES: "1"
TORCH_SYMMMEM: "NVSHMEM"
NVSHMEM_CUMEM_HANDLE_TYPE: "FABRIC"
NVSHMEM_DISABLE_CUDA_VMM: "0"
VLLM_SKIP_P2P_CHECK: "1"
VLLM_RANDOMIZE_DP_DUMMY_INPUTS: "0"
VLLM_RANDOMIZE_DP_DUMMY_INPUTS: "1"
VLLM_USE_DEEP_GEMM: "1"
VLLM_USE_RUST_FRONTEND: "1"
NVIDIA_GDRCOPY: "enabled"
# See prefill note: harden the decode's cross-node DP8/EP8 coordination
# against transient gloo resets under the conc4096 warmup burst.
Expand Down
10 changes: 10 additions & 0 deletions perf-changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4788,3 +4788,13 @@
- "Add EAGLE3 speculative-decoding arm for the Kimi K2.6 NVFP4 B300 AgentX recipe (draft lightseekorg/kimi-k2.6-eagle3-mla, TOKENSPEED_MLA attention backend with TRT-LLM ragged MLA kernel)."
- "TP8/TP4 GPU-only KV points plus a TP4 native CPU-offload ladder via SimpleCPUOffloadConnector with lazy_offload off; TP4/DCP4 high-concurrency points (conc 32/64) using num_speculative_tokens=3 and synthetic_acceptance_length=2.88."
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2222

- config-keys:
- dsv4-fp4-gb200-llm-d-vllm-mid-curve-megamoe
- dsv4-fp4-gb200-llm-d-vllm-high-tpt-megamoe
description:
- "Decode: gpu-memory-utilization 0.85->0.9, add max-model-len 9280, max-num-seqs 512->1024, disable NCCL symmetric memory, add no-enable-flashinfer-autotune"
- "Prefill: gpu-memory-utilization 0.9->0.95, add max-model-len 9280, add max-num-seqs 16 + max-num-batched-tokens 32768, enable rust frontend, enable randomize-dp-dummy-inputs"
- "EPP: switch from max-score-picker to weighted-random-picker (threshold=0.1) for better load distribution under high concurrency"
- "Low-latency recipe: same prefill optimizations, decode NCCL symmetric memory disabled + rust frontend enabled"
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/XXXX