diff --git a/PR_BODY.md b/PR_BODY.md new file mode 100644 index 0000000000..18966fdebe --- /dev/null +++ b/PR_BODY.md @@ -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 diff --git a/benchmarks/multi_node/llm-d-recipes/dsv4-fp4-gb200-low-latency.yaml b/benchmarks/multi_node/llm-d-recipes/dsv4-fp4-gb200-low-latency.yaml index f0cd876e4c..187041fcc3 100644 --- a/benchmarks/multi_node/llm-d-recipes/dsv4-fp4-gb200-low-latency.yaml +++ b/benchmarks/multi_node/llm-d-recipes/dsv4-fp4-gb200-low-latency.yaml @@ -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 @@ -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: @@ -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 @@ -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" @@ -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 @@ -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" diff --git a/benchmarks/multi_node/llm-d-recipes/dsv4-fp4-gb200-mid-curve-megamoe.yaml b/benchmarks/multi_node/llm-d-recipes/dsv4-fp4-gb200-mid-curve-megamoe.yaml index 2103ecf5c7..5b10ccf243 100644 --- a/benchmarks/multi_node/llm-d-recipes/dsv4-fp4-gb200-mid-curve-megamoe.yaml +++ b/benchmarks/multi_node/llm-d-recipes/dsv4-fp4-gb200-mid-curve-megamoe.yaml @@ -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 @@ -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: @@ -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 @@ -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" @@ -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 @@ -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 @@ -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. diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 38efdbf219..b3f1323ae7 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5010,4 +5010,13 @@ - "Add MTP speculative-decoding for the B300 vLLM AgentX recipe as a separate config-key, so the existing dsv4-fp4-b300-vllm-agentic aggregate is not re-run." - "dsv4-fp4-b300-vllm-agentic-mtp: MTP twins (--speculative-config {\"method\":\"mtp\",\"num_speculative_tokens\":3}) of the aggregate arms plus a new TP8 GPU-resident arm -- TP8 GPU-resident [1,2,4,6,8], TP4 GPU-resident [1,2,4,6,8,12,16,20], TP4 SimpleCPU [20,24,28,32,36,40], DEP4 [32,40,48,56], DEP8 [64,96,112,128,144,160,176,192,224]; routed via spec-decoding=mtp to dsv4_fp4_b300_vllm_mtp.sh (FULL_DECODE_ONLY cudagraph capture sizes in TOKENS = num_seqs*4)." pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2258 - + +- 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/2242