From 6aa6a8f9e9df9fda74bcf3a8e4a6634da9132e73 Mon Sep 17 00:00:00 2001 From: Markov Ilya Date: Wed, 15 Jul 2026 23:27:46 +0200 Subject: [PATCH 01/12] llm-d-vllm: optimize DSv4-Pro GB200 recipe configs Tune decode and prefill vLLM flags based on validated GB200 NVL72 benchmarks showing +2-43% tok/s/GPU and 15-25% lower TPOT: Decode (mid-curve-megamoe): - gpu-memory-utilization 0.85 -> 0.9 (larger KV cache pool) - Add max-model-len 9280 (tight ISL8192+OSL1024 bound) - max-num-seqs/batched-tokens/cudagraph-capture 512 -> 1024 - Disable NCCL symmetric memory (standard NVLink path faster) - Add no-enable-flashinfer-autotune, rust frontend 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 rust frontend - Enable randomize-dp-dummy-inputs EPP (both recipes): - Switch from max-score-picker to weighted-random-picker (threshold=0.1) for better load distribution under high concurrency Low-latency decode: disable NCCL symmetric memory, add rust frontend. --- PR_BODY.md | 50 +++++++++++++++++++ .../dsv4-fp4-gb200-low-latency.yaml | 29 ++++++++--- .../dsv4-fp4-gb200-mid-curve-megamoe.yaml | 35 +++++++++---- perf-changelog.yaml | 10 ++++ 4 files changed, 105 insertions(+), 19 deletions(-) create mode 100644 PR_BODY.md 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 cd0320fa99..43b2a4a257 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -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 From bf730c9245d741d60a1db34e3790d54b00bc54bb Mon Sep 17 00:00:00 2001 From: Cameron Quilici Date: Sun, 2 Aug 2026 13:12:40 -0500 Subject: [PATCH 02/12] Update perf-changelog.yaml --- perf-changelog.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 18db3a4c57..d120331b6b 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5365,4 +5365,4 @@ - "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 - \ No newline at end of file + From c6e4c33371190b50576e71cb80f26ad20376753d Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Sun, 2 Aug 2026 13:14:38 -0500 Subject: [PATCH 03/12] Fix llm-d sweep changelog config key --- perf-changelog.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/perf-changelog.yaml b/perf-changelog.yaml index d120331b6b..5ec7c68dcf 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5357,12 +5357,10 @@ pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2213 - config-keys: - - dsv4-fp4-gb200-llm-d-vllm-mid-curve-megamoe - - dsv4-fp4-gb200-llm-d-vllm-high-tpt-megamoe + - dsv4-fp4-gb200-llmd-vllm 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 - From 2f9e91e56dbe7d036e745f56e2ab3cd5ff2ff1f2 Mon Sep 17 00:00:00 2001 From: Markov Ilya Date: Mon, 3 Aug 2026 23:10:54 +0200 Subject: [PATCH 04/12] Bump version, remove stream-interval --- benchmarks/llm-d/Dockerfile | 2 +- .../multi_node/llm-d-recipes/dsv4-fp4-gb200-low-latency.yaml | 3 +-- .../llm-d-recipes/dsv4-fp4-gb200-mid-curve-megamoe.yaml | 1 - configs/nvidia-master.yaml | 2 +- perf-changelog.yaml | 5 +++-- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/benchmarks/llm-d/Dockerfile b/benchmarks/llm-d/Dockerfile index 8494027604..cfc04557c5 100644 --- a/benchmarks/llm-d/Dockerfile +++ b/benchmarks/llm-d/Dockerfile @@ -22,7 +22,7 @@ # --build-arg EPP_FROM_IMAGE="$EPP_FROM_IMAGE" \ # --build-arg ROUTING_SIDECAR_IMAGE="$ROUTING_SIDECAR_IMAGE" \ # --build-arg ENVOY_FROM_IMAGE="$ENVOY_FROM_IMAGE" ... -ARG VLLM_BASE=vllm/vllm-openai:v0.23.0 +ARG VLLM_BASE=vllm/vllm-openai:v0.26.0 ARG EPP_FROM_IMAGE=ghcr.io/llm-d/llm-d-router-endpoint-picker:v0.9.0 ARG ROUTING_SIDECAR_IMAGE=ghcr.io/llm-d/llm-d-router-disagg-sidecar:v0.9.0 ARG ENVOY_FROM_IMAGE=envoyproxy/envoy:distroless-v1.33.2 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 187041fcc3..be307349ec 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 @@ -18,7 +18,7 @@ # decode ep:1/dp-attn:false in the master key is what selects the # pure-TP path in server.sh. Decode knobs are latency-sized: max-num-seqs # 256, max-num-batched-tokens 256, max-cudagraph-capture-size 256, -# FULL_DECODE_ONLY graphs, stream-interval 50, gpu-memory-utilization 0.9. +# FULL_DECODE_ONLY graphs, gpu-memory-utilization 0.9. # 2. PREFILL is IDENTICAL to the mid-curve/high-tpt prefill (copied verbatim, # DEP8 with enable-ep-weight-filter + moe-backend deep_gemm_mega_moe). An # earlier srt-slurm-style low-latency prefill (weight-offload, no filter, @@ -165,7 +165,6 @@ decode: --no-enable-flashinfer-autotune --block-size 256 --compilation-config {"cudagraph_mode":"FULL_DECODE_ONLY","mode":0} - --stream-interval 50 --tokenizer-mode deepseek_v4 --no-disable-hybrid-kv-cache-manager --enable-sleep-mode 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 5b10ccf243..16032ca877 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 @@ -162,7 +162,6 @@ decode: --no-enable-flashinfer-autotune --block-size 256 --compilation-config {"cudagraph_mode":"FULL_DECODE_ONLY","mode":0} - --stream-interval 50 --tokenizer-mode deepseek_v4 --moe-backend deep_gemm_mega_moe --enable-ep-weight-filter diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index a30af59641..08776771be 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -5272,7 +5272,7 @@ dsv4-fp4-gb200-dynamo-vllm: # TODO: change image to official llmd image. # Build source: benchmarks/llm-d/Dockerfile. dsv4-fp4-gb200-llmd-vllm: - image: ghcr.io/ezrasilvera/llm-d-nokube-vllm:vllm0.23 + image: ghcr.io/ezrasilvera/llm-d-nokube-vllm:vllm0.26 model: deepseek-ai/DeepSeek-V4-Pro model-prefix: dsv4 runner: gb200 diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 5ec7c68dcf..1f6e9c0534 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5359,8 +5359,9 @@ - config-keys: - dsv4-fp4-gb200-llmd-vllm 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" + - "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, drop stream-interval (unsupported by rust frontend)" - "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" + - "Low-latency recipe: same prefill optimizations, decode NCCL symmetric memory disabled + rust frontend enabled, drop stream-interval" + - "Bump llmd-vllm image vllm0.23 -> vllm0.26 (v0.26 strips data_parallel_hybrid_lb from rust args-json; required for VLLM_USE_RUST_FRONTEND=1 on multi-node DEP8)" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2242 From 4ab04dfb29d72cb1bf9dd36844deb394815b5618 Mon Sep 17 00:00:00 2001 From: Cameron Quilici Date: Mon, 3 Aug 2026 17:45:37 -0500 Subject: [PATCH 05/12] Update perf-changelog.yaml --- perf-changelog.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 2cf1261549..12da4c54b9 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5382,4 +5382,5 @@ - "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, drop stream-interval" - "Bump llmd-vllm image vllm0.23 -> vllm0.26 (v0.26 strips data_parallel_hybrid_lb from rust args-json; required for VLLM_USE_RUST_FRONTEND=1 on multi-node DEP8)" - pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2242 \ No newline at end of file + pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2242 + From fced56caf01595b7574b02e5aa29d140ed685c32 Mon Sep 17 00:00:00 2001 From: Markov Ilya Date: Tue, 4 Aug 2026 15:04:49 +0200 Subject: [PATCH 06/12] Fix image tag --- configs/nvidia-master.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 08776771be..04fec6bf2c 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -5272,7 +5272,7 @@ dsv4-fp4-gb200-dynamo-vllm: # TODO: change image to official llmd image. # Build source: benchmarks/llm-d/Dockerfile. dsv4-fp4-gb200-llmd-vllm: - image: ghcr.io/ezrasilvera/llm-d-nokube-vllm:vllm0.26 + image: quay.io/rh-ee-imarkov/llm-d-nokube-vllm:vllm0.26 model: deepseek-ai/DeepSeek-V4-Pro model-prefix: dsv4 runner: gb200 From c500460ff68e3440e629c2a2ebc7f55406fd4fae Mon Sep 17 00:00:00 2001 From: Markov Ilya Date: Wed, 5 Aug 2026 19:51:23 +0200 Subject: [PATCH 07/12] Fix perf-changelog for PR #2498 Point pr-link at #2498 and drop inaccurate max-num-seqs 512->1024 claim. Co-authored-by: Cursor --- perf-changelog.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/perf-changelog.yaml b/perf-changelog.yaml index e2c4fa7fc6..320a1728f7 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5359,12 +5359,11 @@ - config-keys: - dsv4-fp4-gb200-llmd-vllm 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, drop stream-interval (unsupported by rust frontend)" + - "Decode: gpu-memory-utilization 0.85->0.9, add max-model-len 9280, disable NCCL symmetric memory, add no-enable-flashinfer-autotune, drop stream-interval (unsupported by rust frontend)" - "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, drop stream-interval" - - "Bump llmd-vllm image vllm0.23 -> vllm0.26 (v0.26 strips data_parallel_hybrid_lb from rust args-json; required for VLLM_USE_RUST_FRONTEND=1 on multi-node DEP8)" - pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2242 + pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2498 - config-keys: - qwen3.5-fp4-b300-sglang-agentic-mtp From 691d9a9d16c6a143bf5f6fb2b7b9c37ed5d61c6d Mon Sep 17 00:00:00 2001 From: Markov Ilya Date: Wed, 5 Aug 2026 19:54:54 +0200 Subject: [PATCH 08/12] Fix perf-changelog append-only CI failure for PR #2498 Move the changelog entry to the file tail and restore the two-space separator after PR #2420 so process_changelog sees additions only. Co-authored-by: Cursor --- perf-changelog.yaml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 320a1728f7..10c48bcd64 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5356,15 +5356,6 @@ - "Extend the TP4 and TP8 8k1k concurrency sweep from 64 to 128 (1k1k deprecated per #2263)" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2213 -- config-keys: - - dsv4-fp4-gb200-llmd-vllm - description: - - "Decode: gpu-memory-utilization 0.85->0.9, add max-model-len 9280, disable NCCL symmetric memory, add no-enable-flashinfer-autotune, drop stream-interval (unsupported by rust frontend)" - - "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, drop stream-interval" - pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2498 - - config-keys: - qwen3.5-fp4-b300-sglang-agentic-mtp description: @@ -5382,6 +5373,7 @@ - "Use the shared AIPerf watchdog to cap whole-trajectory runtime idle gaps at 300 seconds" - "Image: lmsysorg/sglang:v0.5.16-cu130" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2420 + - config-keys: - minimaxm3-fp4-b200-dynamo-vllm @@ -5457,3 +5449,12 @@ - "Enable prefill-only INT4 quick-reduce: set VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4 and VLLM_ROCM_QUICK_REDUCE_MAX_SIZE_BYTES_MB=2048 on the prefill workers via a new prefill_env channel (mirrors the existing decode_env path in server_vllm.sh)." - "Cap the 1P1D TP4 concurrency sweep at 256 (was 512); drop the 2P1D TP4 layout (128/256/512) as it is CI-flaky with negligible curve impact." pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/1943 + +- config-keys: + - dsv4-fp4-gb200-llmd-vllm + description: + - "Decode: gpu-memory-utilization 0.85->0.9, add max-model-len 9280, disable NCCL symmetric memory, add no-enable-flashinfer-autotune, drop stream-interval (unsupported by rust frontend)" + - "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, drop stream-interval" + pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2498 From 2d545f11d2fe166517e35603ff1b4844d493cee2 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Wed, 5 Aug 2026 15:00:37 -0500 Subject: [PATCH 09/12] fix(gb200): reuse guarded Enroot imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the shared image URI and squash import helpers before the llm-d early path, then use the same locked and atomic importer for its Quay image. Give fresh imports a private temporary Enroot runtime directory so CI does not fall back to /run/enroot. 中文:修复 GB200 启动器,让 llm-d 的 Quay 镜像复用带锁、原子替换和校验的共享导入逻辑。为全新导入创建独立的临时 Enroot 运行目录,避免 CI 回退到无写权限的 /run/enroot。 --- runners/launch_gb200-nv.sh | 187 +++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 103 deletions(-) diff --git a/runners/launch_gb200-nv.sh b/runners/launch_gb200-nv.sh index 672ccd0414..a54f568d32 100755 --- a/runners/launch_gb200-nv.sh +++ b/runners/launch_gb200-nv.sh @@ -16,6 +16,89 @@ SQUASH_DIR="/mnt/lustre01/users-public/sa-shared" POWER_SRT_SLURM_URL="https://github.com/edwingao28/srt-slurm.git" POWER_SRT_SLURM_PIN="6fc1bed01a0b82dae0088a105c03ce0cfb353443" +# Enroot 3.x does not parse Docker's tag@digest syntax. For digest-pinned +# images, use its explicit registry syntax and pass the digest as the +# manifest reference so the import remains immutable. +enroot_uri_for_image() { + local image="$1" + local image_without_digest="$image" + local digest="" + local first_component registry repository repository_dir repository_name + + if [[ "$image" == *@sha256:* ]]; then + image_without_digest="${image%@*}" + digest="${image##*@}" + fi + + first_component="${image_without_digest%%/*}" + if [[ "$image_without_digest" == */* && ( "$first_component" == *.* || "$first_component" == *:* || "$first_component" == "localhost" ) ]]; then + registry="$first_component" + repository="${image_without_digest#*/}" + else + registry="registry-1.docker.io" + repository="$image_without_digest" + fi + + if [[ -z "$digest" ]]; then + if [[ "$registry" == "registry-1.docker.io" ]]; then + printf 'docker://%s\n' "$image" + else + printf 'docker://%s#%s\n' "$registry" "$repository" + fi + return + fi + + repository_dir="${repository%/*}" + repository_name="${repository##*/}" + repository_name="${repository_name%%:*}" + if [[ "$repository" == */* ]]; then + repository="${repository_dir}/${repository_name}" + else + repository="$repository_name" + fi + if [[ "$registry" == "registry-1.docker.io" && "$repository" != */* ]]; then + repository="library/$repository" + fi + + printf 'docker://%s#%s:%s\n' "$registry" "$repository" "$digest" +} + +# Concurrent matrix jobs import to the same shared-FS squash path. +# Serialize imports and atomically replace invalid images so readers never +# observe a partially written squash file. +import_squash() { + local squash="$1" image="$2" + local lock="${squash}.lock" + local tmp="${squash}.tmp.$$" + local enroot_uri + enroot_uri=$(enroot_uri_for_image "$image") || exit 1 + ( + exec 9>"$lock" + flock -w 1800 9 || { echo "Failed to acquire lock for $squash" >&2; exit 1; } + if unsquashfs -l "$squash" > /dev/null 2>&1; then + echo "Squash file already exists and is valid, skipping import: $squash" + else + local enroot_runtime + enroot_runtime=$(mktemp -d "${TMPDIR:-/tmp}/enroot-import.XXXXXX") || exit 1 + trap 'rm -rf -- "$enroot_runtime"' EXIT + export ENROOT_RUNTIME_PATH="$enroot_runtime" + + rm -f "$squash" "$squash".tmp.* + if ! enroot import -o "$tmp" "$enroot_uri"; then + rm -f "$tmp" + echo "Error: enroot import failed for $enroot_uri" >&2 + exit 1 + fi + if ! unsquashfs -l "$tmp" > /dev/null 2>&1; then + rm -f "$tmp" + echo "Error: enroot import produced an invalid squash file: $tmp" >&2 + exit 1 + fi + mv -f "$tmp" "$squash" || exit 1 + fi + ) || exit 1 +} + if [[ "$FRAMEWORK" == "llmd-vllm" ]]; then if [[ "$MODEL_PREFIX" == "dsv4" && "$PRECISION" == "fp4" ]]; then export MODEL_PATH="/mnt/numa1/models/DeepSeek-V4-Pro" @@ -26,31 +109,7 @@ if [[ "$FRAMEWORK" == "llmd-vllm" ]]; then fi SQUASH_FILE="${SQUASH_DIR}/$(echo "$IMAGE" | sed 's/[\/:@#]/_/g').sqsh" - - # Enroot uses '#' between the registry and repository, e.g. docker://ghcr.io#org/image:tag. - case "$IMAGE" in - */*) - _registry="${IMAGE%%/*}" - _rest="${IMAGE#*/}" - if [[ "$_registry" == *.* || "$_registry" == *:* ]]; then - ENROOT_URL="docker://${_registry}#${_rest}" - else - ENROOT_URL="docker://${IMAGE}" # bare hub repo - fi - ;; - *) ENROOT_URL="docker://${IMAGE}" ;; - esac - echo "ENROOT_URL=$ENROOT_URL" - - if [[ ! -s "$SQUASH_FILE" ]]; then - echo "enroot import -> $SQUASH_FILE" - enroot import -o "$SQUASH_FILE" "$ENROOT_URL" || { - echo "Error: enroot import failed for $ENROOT_URL" >&2 - exit 1 - } - else - echo "Reusing existing squash: $SQUASH_FILE" - fi + import_squash "$SQUASH_FILE" "$IMAGE" export LLMD_CONTAINER_ENGINE=pyxis export LLMD_SQUASH_FILE="$SQUASH_FILE" @@ -207,84 +266,6 @@ uses_watchtower_shared_fs() { SQUASH_FILE="${SQUASH_DIR}/$(echo "$IMAGE" | sed 's/[\/:@#]/_/g').sqsh" NGINX_SQUASH_FILE="${SQUASH_DIR}/$(echo "$NGINX_IMAGE" | sed 's/[\/:@#]/_/g').sqsh" -# Enroot 3.x does not parse Docker's tag@digest syntax. For digest-pinned -# images, use its explicit registry syntax and pass the digest as the -# manifest reference so the import remains immutable. -enroot_uri_for_image() { - local image="$1" - local image_without_digest="$image" - local digest="" - local first_component registry repository repository_dir repository_name - - if [[ "$image" == *@sha256:* ]]; then - image_without_digest="${image%@*}" - digest="${image##*@}" - fi - - first_component="${image_without_digest%%/*}" - if [[ "$image_without_digest" == */* && ( "$first_component" == *.* || "$first_component" == *:* || "$first_component" == "localhost" ) ]]; then - registry="$first_component" - repository="${image_without_digest#*/}" - else - registry="registry-1.docker.io" - repository="$image_without_digest" - fi - - if [[ -z "$digest" ]]; then - if [[ "$registry" == "registry-1.docker.io" ]]; then - printf 'docker://%s\n' "$image" - else - printf 'docker://%s#%s\n' "$registry" "$repository" - fi - return - fi - - repository_dir="${repository%/*}" - repository_name="${repository##*/}" - repository_name="${repository_name%%:*}" - if [[ "$repository" == */* ]]; then - repository="${repository_dir}/${repository_name}" - else - repository="$repository_name" - fi - if [[ "$registry" == "registry-1.docker.io" && "$repository" != */* ]]; then - repository="library/$repository" - fi - - printf 'docker://%s#%s:%s\n' "$registry" "$repository" "$digest" -} - -# Concurrent matrix jobs import to the same shared-FS squash path. -# Serialize imports and atomically replace invalid images so readers never -# observe a partially written squash file. -import_squash() { - local squash="$1" image="$2" - local lock="${squash}.lock" - local tmp="${squash}.tmp.$$" - local enroot_uri - enroot_uri=$(enroot_uri_for_image "$image") || exit 1 - ( - exec 9>"$lock" - flock -w 1800 9 || { echo "Failed to acquire lock for $squash" >&2; exit 1; } - if unsquashfs -l "$squash" > /dev/null 2>&1; then - echo "Squash file already exists and is valid, skipping import: $squash" - else - rm -f "$squash" "$squash".tmp.* - if ! enroot import -o "$tmp" "$enroot_uri"; then - rm -f "$tmp" - echo "Error: enroot import failed for $enroot_uri" >&2 - exit 1 - fi - if ! unsquashfs -l "$tmp" > /dev/null 2>&1; then - rm -f "$tmp" - echo "Error: enroot import produced an invalid squash file: $tmp" >&2 - exit 1 - fi - mv -f "$tmp" "$squash" || exit 1 - fi - ) || exit 1 -} - import_squash "$SQUASH_FILE" "$IMAGE" import_squash "$NGINX_SQUASH_FILE" "$NGINX_IMAGE" From ece71e6611f8d21cfe09d6e1c9da43101b00dae8 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Wed, 5 Aug 2026 15:07:29 -0500 Subject: [PATCH 10/12] fix(gb200): pin Quay image digest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pin the vllm0.26 OCI index so Enroot 3.5 can query it on GB200. Quay returns 404 for the tag during Enroot’s headerless permission probe, while the immutable digest returns 200 and resolves the arm64 manifest. 中文:固定 vllm0.26 的 OCI 索引摘要,使 GB200 上的 Enroot 3.5 能够正常查询镜像。Quay 对 Enroot 不带 Accept 标头的标签权限探测返回 404,而不可变摘要返回 200 并可解析 arm64 清单。 --- configs/nvidia-master.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index ec4e055b43..27963f3e5a 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -5107,7 +5107,7 @@ dsv4-fp4-gb200-dynamo-vllm: # TODO: change image to official llmd image. # Build source: benchmarks/llm-d/Dockerfile. dsv4-fp4-gb200-llmd-vllm: - image: quay.io/rh-ee-imarkov/llm-d-nokube-vllm:vllm0.26 + image: quay.io/rh-ee-imarkov/llm-d-nokube-vllm:vllm0.26@sha256:a9095d4c835935c4070be2040de0a5ef3b44098f603092ab66d743b0e731b7b4 model: deepseek-ai/DeepSeek-V4-Pro model-prefix: dsv4 runner: gb200 From d834d4a582c1a724de4ed783599e74ba2faec5f2 Mon Sep 17 00:00:00 2001 From: Markov Ilya Date: Thu, 6 Aug 2026 10:43:54 +0200 Subject: [PATCH 11/12] Fix EPP startup by dropping unsupported weighted-random-picker threshold. EPP v0.9.0 rejects the threshold parameter; remove it from both GB200 recipes and update the changelog entry accordingly. Co-authored-by: Cursor --- .../multi_node/llm-d-recipes/dsv4-fp4-gb200-low-latency.yaml | 2 -- .../llm-d-recipes/dsv4-fp4-gb200-mid-curve-megamoe.yaml | 2 -- perf-changelog.yaml | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) 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 be307349ec..e29106062d 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 @@ -52,8 +52,6 @@ plugins: - type: queue-scorer - type: active-request-scorer - type: weighted-random-picker - parameters: - threshold: "0.1" schedulingProfiles: - name: prefill 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 16032ca877..f82a79f28c 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 @@ -46,8 +46,6 @@ plugins: - type: queue-scorer - type: active-request-scorer - type: weighted-random-picker - parameters: - threshold: "0.1" schedulingProfiles: - name: prefill diff --git a/perf-changelog.yaml b/perf-changelog.yaml index d73cba4976..7886587d62 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5466,6 +5466,6 @@ description: - "Decode: gpu-memory-utilization 0.85->0.9, add max-model-len 9280, disable NCCL symmetric memory, add no-enable-flashinfer-autotune, drop stream-interval (unsupported by rust frontend)" - "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" + - "EPP: switch from max-score-picker to weighted-random-picker for better load distribution under high concurrency" - "Low-latency recipe: same prefill optimizations, decode NCCL symmetric memory disabled + rust frontend enabled, drop stream-interval" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2498 From 98b6e6a61a6bda3e15cf1c17124c4de7b11ccad5 Mon Sep 17 00:00:00 2001 From: Markov Ilya Date: Thu, 6 Aug 2026 14:20:21 +0200 Subject: [PATCH 12/12] Drop llmd-vllm low-middle sweep using low-latency recipe at c256/512. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The low-latency recipe is tuned for c1 only (1P×1D); high-concurrency 1P×4D jobs were misconfigured and failing CI unrelated to recipe tuning. Co-authored-by: Cursor --- configs/nvidia-master.yaml | 22 ---------------------- perf-changelog.yaml | 1 + 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 27963f3e5a..7853626445 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -5143,28 +5143,6 @@ dsv4-fp4-gb200-llmd-vllm: - "DECODE_NODES=2" - "GPUS_PER_NODE=4" - # Low-middle: 1 prefill DEP8 + 4 decode TP8. - - spec-decoding: "none" - conc-list: [256, 512] - prefill: - num-worker: 1 - tp: 1 - ep: 8 - dp-attn: true - additional-settings: - - "PREFILL_NODES=2" - - "GPUS_PER_NODE=4" - - "CONFIG_FILE=dsv4-fp4-gb200-low-latency.yaml" - decode: - num-worker: 4 - tp: 8 - ep: 1 - dp-attn: false - additional-settings: - - "DECODE_NODES=8" - - "DECODE_WORKERS=4" - - "GPUS_PER_NODE=4" - # Mid curve: 1 prefill DEP8 + 1 decode DEP8. - spec-decoding: "none" conc-list: [256, 512, 1024] diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 7886587d62..abae8b7b42 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5468,4 +5468,5 @@ - "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 for better load distribution under high concurrency" - "Low-latency recipe: same prefill optimizations, decode NCCL symmetric memory disabled + rust frontend enabled, drop stream-interval" + - "Sweep: drop low-middle point (c256/512, 1P×4D) from llmd-vllm key; low-latency recipe runs at c1 only" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2498