diff --git a/benchmarks/multi_node/srt-slurm-recipes/sglang/deepseek-v4/agentic/agg-h200-tp8-mtp-kvoffload.yaml b/benchmarks/multi_node/srt-slurm-recipes/sglang/deepseek-v4/agentic/agg-h200-tp8-mtp-kvoffload.yaml new file mode 100644 index 0000000000..8fcaed4eb1 --- /dev/null +++ b/benchmarks/multi_node/srt-slurm-recipes/sglang/deepseek-v4/agentic/agg-h200-tp8-mtp-kvoffload.yaml @@ -0,0 +1,115 @@ +name: "agg-h200-tp8-mtp-kvoffload" + +# DeepSeek-V4-Pro AgentX aggregated TP8 serving on one 8xH200 node. The recipe is +# topology-invariant; configs/nvidia-master.yaml varies only concurrency to +# produce the latency/throughput Pareto curve. + +model: + path: "deepseek-v4-pro" + container: "dynamo-sglang" + precision: "fp8" + +dynamo: + install: true + wheel: "1.3.0.dev20260718" + +slurm: + time_limit: "8:00:00" + +health_check: + max_attempts: 1440 + interval_seconds: 10 + +resources: + gpu_type: "h200" + gpus_per_node: 8 + agg_nodes: 1 + agg_workers: 1 + gpus_per_agg: 8 + +infra: + etcd_nats_dedicated_node: true + # AgentX prompts can exceed NATS's 1 MiB default after JSON serialization. + nats_max_payload_mb: 32 + +frontend: + type: dynamo + nginx_session_affinity: true + nginx_session_affinity_header: X-Dynamo-Session-ID + enable_multiple_frontends: true + num_additional_frontends: 4 + env: + PIP_BREAK_SYSTEM_PACKAGES: "1" + args: + router-mode: "kv" + router-session-affinity-ttl-secs: "3600" + active-decode-blocks-threshold: "None" + active-prefill-tokens-threshold: "None" + active-prefill-tokens-threshold-frac: "None" + +backend: + type: sglang + + aggregated_environment: + SGLANG_DEFAULT_THINKING: "1" + SGLANG_DSV4_REASONING_EFFORT: high + SGLANG_SIMULATE_ACC_LEN: "2.49" + SGLANG_SIMULATE_ACC_METHOD: match-expected + SGLANG_SIMULATE_ACC_TOKEN_MODE: real-draft-token + PIP_BREAK_SYSTEM_PACKAGES: "1" + HF_HUB_CACHE: /hf_hub_cache + SGLANG_OPT_SWA_SPLIT_LEAF_ON_INSERT: "1" + SGLANG_OPT_UNIFIED_CACHE_FREE_OUT_OF_WINDOW_SLOTS: "1" + SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2: "1" + SGLANG_OPT_USE_ONLINE_COMPRESS: "0" + SGLANG_OPT_USE_JIT_INDEXER_METADATA: "1" + SGLANG_OPT_USE_JIT_NORM: "1" + SGLANG_OPT_USE_TOPK_V2: "True" + SGLANG_ENABLE_UNIFIED_RADIX_TREE: "1" + + sglang_config: + aggregated: + served-model-name: "deepseek-ai/DeepSeek-V4-Pro" + trust-remote-code: true + stream-interval: 50 + watchdog-timeout: 1000000 + mem-fraction-static: 0.88 + chunked-prefill-size: 4096 + moe-runner-backend: marlin + disable-flashinfer-autotune: true + swa-full-tokens-ratio: 0.1 + max-running-requests: 32 + cuda-graph-max-bs: 32 + + scheduler-recv-interval: 30 + tp-size: 8 + dp-size: 1 + ep-size: 1 + + enable-hierarchical-cache: true + hicache-ratio: 6 + hicache-write-policy: write_through + hicache-io-backend: kernel + + speculative-algorithm: EAGLE + speculative-num-steps: 3 + speculative-eagle-topk: 1 + speculative-num-draft-tokens: 4 + +srun_options: + # The custom benchmark installs its isolated AIPerf environment at runtime. + container-remap-root: "" + +benchmark: + type: custom + command: bash /infmax-workspace/benchmarks/multi_node/agentic_srt.sh + env: + INFMAX_CONTAINER_WORKSPACE: /infmax-workspace + RESULT_DIR: /logs/agentic + PORT: "8000" + # Aggregated serving uses one TP8 worker for both prefill and decode. + IS_MULTINODE: "false" + TP: "8" + AIPERF_HTTP_X_DYNAMO_SESSION_ID_FROM_CORRELATION_ID: "true" + AIPERF_DATASET_MMAP_CACHE_DIR: /aiperf_mmap_cache + HF_HUB_CACHE: /hf_hub_cache diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index a30af59641..1fafdeea4e 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1806,6 +1806,41 @@ dsv4-fp8-h200-vllm-agentic: - search-space: - { tp: 8, ep: 8, dp-attn: true, kv-offloading: none, conc-list: [1, 2, 4, 8, 16] } +# DeepSeek-V4-Pro AgentX on one aggregated TP8 H200 worker. Keep the serving +# topology fixed and sweep only concurrency to produce the Pareto curve. +dsv4-fp8-h200-dynamo-sglang-agentic-agg: + image: lmsysorg/sglang:nightly-dev-cu13-20260720-b3570a45 + model: deepseek-ai/DeepSeek-V4-Pro + model-prefix: dsv4 + runner: cluster:h200-dgxc + precision: fp8 + framework: dynamo-sglang + router: { name: dynamo-router, version: "1.3.0.dev20260718" } + multinode: true + disagg: false + scenarios: + agentic-coding: + - dram-utilization: 0.80 + search-space: + - spec-decoding: mtp + conc-list: [1, 2, 4, 8, 16] + kv-offloading: dram + kv-offload-backend: { name: hicache } + prefill: + num-worker: 1 + tp: 8 + ep: 1 + dp-attn: false + additional-settings: + - "CONFIG_FILE=recipes/sglang/deepseek-v4/agentic/agg-h200-tp8-mtp-kvoffload.yaml" + # The aggregated worker serves prefill and decode on the same GPUs. + # Keep decode at zero to avoid double-counting the TP8 allocation. + decode: + num-worker: 0 + tp: 8 + ep: 1 + dp-attn: false + # MTP variant of dsv4-fp8-h200-sglang. Mirrors the non-MTP recipe (same image, # runner pool, search space) and adds EAGLE speculative decoding via # --speculative-algorithm EAGLE with the (3,1,4) chain matching dsv4-fp4-b300-sglang-mtp. diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 6eebd97070..db9945625e 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5355,3 +5355,11 @@ - "Apply the accuracy-gated Kimi-K2.5 MXFP4 settings: tuned AITER MXFP4 MoE, fused shared experts, FP8 KV cache, block size 16, 16384 batched tokens, 512 sequences, async scheduling, gpu-memory-utilization 0.85 (headroom for CUDA-graph capture on MI355X), and the AITER BF16 GEMM path" - "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-fp8-h200-dynamo-sglang-agentic-agg + description: + - "Add one H200 TP8 aggregated DeepSeek-V4-Pro AgentX recipe with MTP and HiCache." + - "Generate Pareto points by sweeping concurrency [1, 2, 4, 8, 16] while keeping the serving topology fixed." + - "Use Dynamo header-based session affinity and pin AIPerf to the merged PR #17 implementation." + pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2364 diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 00c6cc4977..6feadd9747 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -4,6 +4,8 @@ set -eo pipefail # System-specific configuration for H200 DGXC Slurm cluster SLURM_PARTITION="main" SLURM_ACCOUNT="sa-shared" +HF_HUB_CACHE_MOUNT="${HF_HUB_CACHE_MOUNT:-/models/gharunners/hf-hub-cache}" +AIPERF_MMAP_CACHE_HOST_PATH="${AIPERF_MMAP_CACHE_HOST_PATH:-/home/sa-shared/gharunners/ai-perf-cache}" set -x @@ -13,7 +15,15 @@ if [[ "$IS_MULTINODE" == "true" ]]; then # The yaml files specify HuggingFace model IDs for portability, but we use # local paths to avoid repeated downloading on the shared H200 cluster. if [[ $FRAMEWORK == "dynamo-sglang" ]]; then - if [[ $MODEL_PREFIX == "dsr1" && $PRECISION == "fp8" ]]; then + if [[ $MODEL_PREFIX == "dsv4" && $PRECISION == "fp8" ]]; then + # The shared HF cache already contains the H200 FP8 checkpoint; + # default to that local path (overridable via DSV4_MODEL_PATH) so + # srtctl preflight finds the directory instead of trying to pull the + # hf: model ID, which fails on the compute node ("path is + # unavailable. Pull or register the model yourself"). + export MODEL_PATH="${DSV4_MODEL_PATH:-${HF_HUB_CACHE_MOUNT}/DeepSeek-V4-Pro}" + export SRT_SLURM_MODEL_PREFIX="deepseek-v4-pro" + elif [[ $MODEL_PREFIX == "dsr1" && $PRECISION == "fp8" ]]; then export MODEL_PATH="/models/DeepSeek-R1-0528" export SRT_SLURM_MODEL_PREFIX="dsr1-fp8" else @@ -42,7 +52,15 @@ if [[ "$IS_MULTINODE" == "true" ]]; then fi # TODO(CJQ): make first class upon srt-slurm upstream refactor - if [[ "$IS_AGENTIC" == "1" ]]; then + if [[ "$IS_AGENTIC" == "1" && $FRAMEWORK == "dynamo-sglang" && $MODEL_PREFIX == "dsv4" ]]; then + # Overlay the single H200 aggregated recipe on the upstream release + # that provides custom benchmarks, Dynamo wheels, and affinity config. + git clone --branch v1.0.10 --single-branch https://github.com/NVIDIA/srt-slurm.git "$SRT_REPO_DIR" + cd "$SRT_REPO_DIR" + mkdir -p recipes/sglang/deepseek-v4/agentic + cp "$GITHUB_WORKSPACE/benchmarks/multi_node/srt-slurm-recipes/sglang/deepseek-v4/agentic/agg-h200-tp8-mtp-kvoffload.yaml" \ + recipes/sglang/deepseek-v4/agentic/ + elif [[ "$IS_AGENTIC" == "1" ]]; then git clone --branch cam/sa-submission-q2-2026 --single-branch https://github.com/cquil11/srt-slurm-nv.git "$SRT_REPO_DIR" cd "$SRT_REPO_DIR" else @@ -98,6 +116,11 @@ gpus_per_node: 8 network_interface: "" # Path to srtctl repo root (where the configs live) srtctl_root: "${SRTCTL_ROOT}" +# Persistent AgentX dataset and Hugging Face caches mounted into every +# server and benchmark container. +default_mounts: + "${AIPERF_MMAP_CACHE_HOST_PATH}": "/aiperf_mmap_cache" + "${HF_HUB_CACHE_MOUNT}": "/hf_hub_cache" # Model path aliases model_paths: "${SRT_SLURM_MODEL_PREFIX}": "${MODEL_PATH}" @@ -271,9 +294,6 @@ EOF find . -name '.nfs*' -delete 2>/dev/null || true else - - HF_HUB_CACHE_MOUNT="/models/gharunners/hf-hub-cache" - AIPERF_MMAP_CACHE_HOST_PATH="/home/sa-shared/gharunners/ai-perf-cache" SQUASH_FILE="/data/gharunners/containers/$(echo "$IMAGE" | sed 's/[\/:@#]/_/g').sqsh" # Convert pyxis image format (nvcr.io#path) to docker format (nvcr.io/path) for enroot import