From 9b1e9b2e4c78088ddf20c933dfbee4d03bb6d8ab Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 13:05:01 -0500 Subject: [PATCH 01/62] feat(agentx): add Kimi K3 H200 day-0 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add direct two-node Slurm serving for the official latency-oriented TP16, balanced TEP16, and throughput-oriented DEP16 vLLM strategies. Wire the configurations into AgentX and preserve srt-slurm for disaggregated deployments.\n\n中文:新增 Kimi K3 H200 Day-0 AgentX 支持,采用直接两节点 Slurm 部署,对接官方面向低延迟的 TP16、均衡型 TEP16 和面向吞吐量的 DEP16 vLLM 策略。将相关配置接入 AgentX,并继续仅将 srt-slurm 用于分离式部署。 --- .../agentic/kimik3_fp4_h200_vllm.sh | 117 ++++++++++++ configs/nvidia-master.yaml | 66 +++++++ perf-changelog.yaml | 9 + runners/launch_h200-dgxc-slurm.sh | 172 ++++++++++++++++++ 4 files changed, 364 insertions(+) create mode 100755 benchmarks/multi_node/agentic/kimik3_fp4_h200_vllm.sh diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_h200_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_h200_vllm.sh new file mode 100755 index 0000000000..bb78b53c2e --- /dev/null +++ b/benchmarks/multi_node/agentic/kimik3_fp4_h200_vllm.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash +set -euo pipefail +set -x + +# Two-node aggregated vLLM server for Kimi K3 MXFP4 on H200. +# +# Official recipe: +# https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200 +# +# Strategy mapping from vllm-project/recipes: +# latency -> multi_node_tp (TP16 across two nodes) +# balanced -> multi_node_tep (TP16 + expert parallelism) +# throughput -> multi_node_dep (DEP16, eight local DP ranks per node) + +source "$(dirname "$0")/../../benchmark_lib.sh" + +check_env_vars MODEL MODEL_PATH PORT KIMIK3_STRATEGY CONC_LIST + +NODE_COUNT="${KIMIK3_NODE_COUNT:-2}" +GPUS_PER_NODE="${KIMIK3_GPUS_PER_NODE:-8}" +NODE_RANK="${SLURM_PROCID:?SLURM_PROCID must identify the vLLM node rank}" +MASTER_ADDR="${KIMIK3_MASTER_ADDR:?KIMIK3_MASTER_ADDR must identify rank zero}" + +if [ "$NODE_COUNT" -ne 2 ] || [ "$GPUS_PER_NODE" -ne 8 ]; then + echo "Kimi K3 H200 Day-0 recipes require two nodes with eight GPUs each" >&2 + exit 1 +fi + +read -r -a CONCURRENCIES <<< "$CONC_LIST" +MAX_CONCURRENCY=0 +for concurrency in "${CONCURRENCIES[@]}"; do + if ! [[ "$concurrency" =~ ^[1-9][0-9]*$ ]]; then + echo "Invalid AgentX concurrency: $concurrency" >&2 + exit 1 + fi + if [ "$concurrency" -gt "$MAX_CONCURRENCY" ]; then + MAX_CONCURRENCY="$concurrency" + fi +done + +export GLOO_SOCKET_IFNAME="${GLOO_SOCKET_IFNAME:-eth0}" +export NCCL_SOCKET_IFNAME="${NCCL_SOCKET_IFNAME:-eth0}" +export VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1 +export VLLM_ENGINE_READY_TIMEOUT_S="${VLLM_ENGINE_READY_TIMEOUT_S:-7200}" +export PYTHONNOUSERSITE=1 + +VLLM_CMD=( + vllm serve "$MODEL_PATH" + --served-model-name "$MODEL" + --host 0.0.0.0 + --port "$PORT" + --trust-remote-code + --load-format fastsafetensors + --moe-backend marlin + --gpu-memory-utilization 0.95 + --no-enable-flashinfer-autotune + --disable-custom-all-reduce + --enable-prefix-caching + --enable-auto-tool-choice + --tool-call-parser kimi_k3 + --reasoning-parser kimi_k3 + --language-model-only + --max-model-len 1048576 + --max-num-seqs "$MAX_CONCURRENCY" +) + +case "$KIMIK3_STRATEGY" in + latency) + VLLM_CMD+=( + --tensor-parallel-size "$((NODE_COUNT * GPUS_PER_NODE))" + --nnodes "$NODE_COUNT" + --node-rank "$NODE_RANK" + --master-addr "$MASTER_ADDR" + -cc.pass_config.fuse_allreduce_rms=False + ) + if [ "$NODE_RANK" -gt 0 ]; then + VLLM_CMD+=(--headless) + fi + ;; + balanced) + VLLM_CMD+=( + --tensor-parallel-size "$((NODE_COUNT * GPUS_PER_NODE))" + --nnodes "$NODE_COUNT" + --node-rank "$NODE_RANK" + --master-addr "$MASTER_ADDR" + --enable-expert-parallel + -cc.pass_config.fuse_allreduce_rms=False + ) + if [ "$NODE_RANK" -gt 0 ]; then + VLLM_CMD+=(--headless) + fi + ;; + throughput) + VLLM_CMD+=( + --data-parallel-size "$((NODE_COUNT * GPUS_PER_NODE))" + --data-parallel-size-local "$GPUS_PER_NODE" + --data-parallel-address "$MASTER_ADDR" + --data-parallel-start-rank "$((NODE_RANK * GPUS_PER_NODE))" + --data-parallel-hybrid-lb + --enable-expert-parallel + ) + ;; + *) + echo "Unsupported KIMIK3_STRATEGY: $KIMIK3_STRATEGY" >&2 + exit 1 + ;; +esac + +printf 'Kimi K3 rank %s command: ' "$NODE_RANK" +printf '%q ' "${VLLM_CMD[@]}" +printf '\n' + +if [[ "${KIMIK3_DRY_RUN:-0}" == "1" ]]; then + exit 0 +fi + +exec "${VLLM_CMD[@]}" diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 6b40e856f3..8240569485 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1467,6 +1467,72 @@ kimik2.5-int4-h200-vllm-agentic: - { tp: 8, kv-offloading: none, conc-list: [1, 2, 3, 4, 5, 6, 7] } - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: vllm-simple }, conc-list: [6, 7, 8, 9, 10, 11, 12, 13, 14] } +# Kimi K3 is a 2.8T MXFP4 MoE whose ~1.5 TB checkpoint needs two 8xH200 +# nodes. These are the three aggregated strategies from the official H200 +# recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): +# multi-node TP is latency-oriented, TEP is balanced, and DEP is +# throughput-oriented. P/D disaggregation is intentionally deferred. +kimik3-fp4-h200-vllm-agentic: + image: vllm/vllm-openai:kimi-k3 + model: moonshotai/Kimi-K3 + model-prefix: kimik3 + runner: cluster:h200-dgxc + precision: fp4 + framework: vllm + multinode: true + disagg: false + scenarios: + agentic-coding: + - search-space: + # Latency-oriented: one TP16 engine spanning two H200 nodes. + - spec-decoding: none + kv-offloading: none + conc-list: [1, 2, 4, 8] + prefill: + num-worker: 1 + tp: 16 + ep: 1 + dp-attn: false + additional-settings: + - "KIMIK3_STRATEGY=latency" + decode: + num-worker: 0 + tp: 16 + ep: 1 + dp-attn: false + # Balanced: the same cross-node TP16 engine with expert parallelism. + - spec-decoding: none + kv-offloading: none + conc-list: [4, 8, 16, 32] + prefill: + num-worker: 1 + tp: 16 + ep: 16 + dp-attn: false + additional-settings: + - "KIMIK3_STRATEGY=balanced" + decode: + num-worker: 0 + tp: 16 + ep: 16 + dp-attn: false + # Throughput-oriented: DEP16 across two nodes (eight local DP ranks each). + - spec-decoding: none + kv-offloading: none + conc-list: [16, 32, 64, 128] + prefill: + num-worker: 2 + tp: 8 + ep: 16 + dp-attn: true + additional-settings: + - "KIMIK3_STRATEGY=throughput" + decode: + num-worker: 0 + tp: 8 + ep: 16 + dp-attn: true + # NOTE: At the time of submission, https://docs.vllm.ai/projects/recipes/en/latest/moonshotai/Kimi-K2.5.html # does not have a B300-specific recipe, so this config reuses the existing # Kimi-K2.5 FP4 B200 vLLM recipe as-is until B300-specific tuning is available. diff --git a/perf-changelog.yaml b/perf-changelog.yaml index ac1de53c7d..2c3e5543fd 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5191,3 +5191,12 @@ - "Agentic experiment Variant K (probe, of the #2374 Variant G): REMOVES the kimi-k3-container-deps.sh in-container patch (setup_script, script file, and launcher copy) to verify whether the mamba_hybrid index_fill_ dtype patch is still required by the current vllm/vllm-openai:kimi-k3 image — expected to fail at the first decode step if it is" - "Recipe: benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-b200-tp8pp2-agentic.yaml on the cluster:b200-dgxc pool" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2391 + +- config-keys: + - kimik3-fp4-h200-vllm-agentic + description: + - "Add Kimi K3 Day-0 AgentX support on two 8xH200 nodes with the official vllm/vllm-openai:kimi-k3 image and pre-staged 1.5 TB moonshotai/Kimi-K3 checkpoint" + - "Reference the official H200 recipe at https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200: latency-oriented multi-node TP16, balanced TEP16, and throughput-oriented DEP16" + - "Launch aggregated vLLM directly under Slurm instead of srt-slurm/Dynamo; P/D disaggregation is intentionally deferred" + - "Sweep AgentX concurrency 1-8 for latency, 4-32 for balanced, and 16-128 for throughput with prefix caching, the kimi_k3 tool/reasoning parsers, and the full 1M-token model context" + pr-link: TBD diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 00c6cc4977..e6b30a3b39 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -7,6 +7,178 @@ SLURM_ACCOUNT="sa-shared" set -x +run_kimik3_agentic_vllm() { + local node_count=2 + local gpus_per_node=8 + local model_host_path="/models/gharunners/hf-hub-cache/Kimi-K3" + local model_container_path="/models/hf-hub-cache/Kimi-K3" + local hf_cache_host_path="/models/gharunners/hf-hub-cache" + local hf_cache_container_path="/models/hf-hub-cache" + local aiperf_cache_host_path="/home/sa-shared/gharunners/ai-perf-cache" + local squash_dir="/data/gharunners/containers" + local squash_file + local lock_file + local server_log_dir="$GITHUB_WORKSPACE/agentic_logs/server" + local container_mounts + local job_id + local allocated_nodelist + local head_node + local server_step_pid + local client_rc + local ready=0 + + squash_file="$squash_dir/$(echo "$IMAGE" | sed 's/[\/:@#]/_/g').sqsh" + lock_file="${squash_file}.lock" + + if [[ "${IS_AGENTIC:-0}" != "1" || "$FRAMEWORK" != "vllm" || \ + "$MODEL_PREFIX" != "kimik3" || "$PRECISION" != "fp4" ]]; then + echo "Direct H200 multi-node vLLM is only configured for Kimi K3 FP4 AgentX" >&2 + return 1 + fi + if [[ ! -d "$model_host_path" ]]; then + echo "Pre-staged Kimi K3 weights not found at $model_host_path" >&2 + return 1 + fi + + mkdir -p "$squash_dir" "$server_log_dir" "$aiperf_cache_host_path" + container_mounts="$GITHUB_WORKSPACE:/workspace,$hf_cache_host_path:$hf_cache_container_path,$aiperf_cache_host_path:/aiperf_mmap_cache" + + salloc \ + --partition="$SLURM_PARTITION" \ + --account="$SLURM_ACCOUNT" \ + --nodes="$node_count" \ + --ntasks-per-node=1 \ + --gres="gpu:$gpus_per_node" \ + --exclusive \ + --time=240 \ + --no-shell \ + --job-name="$RUNNER_NAME" + job_id=$(squeue --name="$RUNNER_NAME" -u "$USER" -h -o %A | head -n1) + if [[ -z "$job_id" ]]; then + echo "Failed to resolve the Kimi K3 H200 Slurm allocation" >&2 + return 1 + fi + + cleanup_kimik3_allocation() { + local exit_code=$? + trap - EXIT INT TERM + set +e + if [[ -n "${server_step_pid:-}" ]]; then + kill "$server_step_pid" 2>/dev/null || true + wait "$server_step_pid" 2>/dev/null || true + fi + scancel "$job_id" 2>/dev/null || true + exit "$exit_code" + } + trap cleanup_kimik3_allocation EXIT + trap 'exit 130' INT + trap 'exit 143' TERM + + allocated_nodelist=$(squeue -j "$job_id" -h -o %N) + head_node=$(scontrol show hostnames "$allocated_nodelist" | head -n1) + if [[ -z "$head_node" ]]; then + echo "Failed to resolve the Kimi K3 rank-zero node" >&2 + return 1 + fi + + # Import once into the cluster's shared squash cache. All nodes use this + # same file, so a per-image flock prevents concurrent Day-0 jobs racing. + srun --jobid="$job_id" --nodes=1 --ntasks=1 --nodelist="$head_node" bash -c " + mkdir -p '$squash_dir' + exec 9>'$lock_file' + flock -w 1800 9 || { echo 'Failed to lock $squash_file' >&2; exit 1; } + if unsquashfs -l '$squash_file' >/dev/null 2>&1; then + echo 'Using cached Kimi K3 image: $squash_file' + else + rm -f '$squash_file' + enroot import -o '$squash_file' 'docker://$IMAGE' + unsquashfs -l '$squash_file' >/dev/null + chmod a+r '$squash_file' || true + fi + " + + # One vLLM process per node. TP/TEP followers use --headless; DEP starts + # eight local DP ranks per node. The benchmark client runs later as an + # overlapping CPU-only step on rank zero. + srun \ + --jobid="$job_id" \ + --nodes="$node_count" \ + --ntasks="$node_count" \ + --ntasks-per-node=1 \ + --kill-on-bad-exit=1 \ + --container-image="$squash_file" \ + --container-mounts="$container_mounts" \ + --no-container-mount-home \ + --container-remap-root \ + --container-workdir=/workspace \ + --no-container-entrypoint \ + --export="ALL,MODEL_PATH=$model_container_path,HF_HUB_CACHE=$hf_cache_container_path,AIPERF_DATASET_MMAP_CACHE_DIR=/aiperf_mmap_cache,KIMIK3_NODE_COUNT=$node_count,KIMIK3_GPUS_PER_NODE=$gpus_per_node,KIMIK3_MASTER_ADDR=$head_node,PORT=8888" \ + bash benchmarks/multi_node/agentic/kimik3_fp4_h200_vllm.sh \ + >"$server_log_dir/combined.log" 2>&1 & + server_step_pid=$! + + # A 1.5 TB checkpoint can take much longer than an ordinary model to load. + # Keep checking the server step while waiting so early launch failures + # surface immediately instead of waiting for the full two-hour timeout. + for ((attempt = 1; attempt <= 720; attempt++)); do + if curl --output /dev/null --silent --fail "http://$head_node:8888/health"; then + ready=1 + break + fi + if ! kill -0 "$server_step_pid" 2>/dev/null; then + echo "Kimi K3 server step exited before becoming ready" >&2 + tail -n 200 "$server_log_dir/combined.log" >&2 || true + return 1 + fi + if (( attempt % 6 == 0 )); then + echo "Waiting for Kimi K3 server readiness ($((attempt * 10))s elapsed)" + tail -n 20 "$server_log_dir/combined.log" || true + fi + sleep 10 + done + if [[ "$ready" != "1" ]]; then + echo "Kimi K3 server did not become healthy within 7200 seconds" >&2 + tail -n 200 "$server_log_dir/combined.log" >&2 || true + return 1 + fi + + set +e + srun \ + --jobid="$job_id" \ + --overlap \ + --nodes=1 \ + --ntasks=1 \ + --nodelist="$head_node" \ + --container-image="$squash_file" \ + --container-mounts="$container_mounts" \ + --no-container-mount-home \ + --container-remap-root \ + --container-workdir=/workspace \ + --no-container-entrypoint \ + --export="ALL,MODEL_PATH=$model_container_path,HF_HUB_CACHE=$hf_cache_container_path,AIPERF_DATASET_MMAP_CACHE_DIR=/aiperf_mmap_cache,INFMAX_CONTAINER_WORKSPACE=/workspace,RESULT_DIR=/workspace/agentic_logs,PORT=8888" \ + bash benchmarks/multi_node/agentic_srt.sh + client_rc=$? + set -e + + kill "$server_step_pid" 2>/dev/null || true + wait "$server_step_pid" 2>/dev/null || true + server_step_pid="" + scancel "$job_id" 2>/dev/null || true + job_id="" + trap - EXIT INT TERM + return "$client_rc" +} + +# The official Kimi K3 H200 TP/TEP/DEP strategies are aggregated vLLM +# deployments. Keep them on the direct Slurm path; srt-slurm remains the +# orchestrator for the existing Dynamo disaggregated configurations below. +if [[ "$IS_MULTINODE" == "true" && "${IS_AGENTIC:-0}" == "1" && \ + "$FRAMEWORK" == "vllm" && "$MODEL_PREFIX" == "kimik3" && \ + "$PRECISION" == "fp4" ]]; then + run_kimik3_agentic_vllm + exit $? +fi + if [[ "$IS_MULTINODE" == "true" ]]; then # MODEL_PATH: Override with pre-downloaded paths on H200 runner From 16d44efb2eca79dbcbcd711553847791b8b3d60f Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 13:05:28 -0500 Subject: [PATCH 02/62] chore: link Kimi K3 H200 changelog to PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Record the draft PR URL in the append-only performance changelog.\n\n中文:在只追加的性能变更日志中记录该草稿 PR 的链接。 --- perf-changelog.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 2c3e5543fd..6940197af8 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5199,4 +5199,4 @@ - "Reference the official H200 recipe at https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200: latency-oriented multi-node TP16, balanced TEP16, and throughput-oriented DEP16" - "Launch aggregated vLLM directly under Slurm instead of srt-slurm/Dynamo; P/D disaggregation is intentionally deferred" - "Sweep AgentX concurrency 1-8 for latency, 4-32 for balanced, and 16-128 for throughput with prefix caching, the kimi_k3 tool/reasoning parsers, and the full 1M-token model context" - pr-link: TBD + pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 From 18a61bddb49aa4605f7c84a798b4e512d1f14af3 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 14:30:54 -0500 Subject: [PATCH 03/62] refactor(runners): add pluggable Slurm multi-node connector Move allocation, Pyxis image handling, rank discovery, readiness, client execution, log packaging, and cleanup into a reusable connector. Keep the Kimi vLLM entrypoint scheduler- and hardware-independent, with H200-specific mounts, networking, and model mapping confined to the runner profile. --- .../agentic/kimik3_fp4_h200_vllm.sh | 117 ------- .../multi_node/agentic/kimik3_fp4_vllm.sh | 150 +++++++++ benchmarks/multi_node/agentic_srt.sh | 6 +- configs/nvidia-master.yaml | 40 ++- perf-changelog.yaml | 2 +- runners/connectors/slurm_pyxis.sh | 301 ++++++++++++++++++ runners/launch_h200-dgxc-slurm.sh | 200 ++---------- 7 files changed, 522 insertions(+), 294 deletions(-) delete mode 100755 benchmarks/multi_node/agentic/kimik3_fp4_h200_vllm.sh create mode 100755 benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh create mode 100755 runners/connectors/slurm_pyxis.sh diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_h200_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_h200_vllm.sh deleted file mode 100755 index bb78b53c2e..0000000000 --- a/benchmarks/multi_node/agentic/kimik3_fp4_h200_vllm.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -set -x - -# Two-node aggregated vLLM server for Kimi K3 MXFP4 on H200. -# -# Official recipe: -# https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200 -# -# Strategy mapping from vllm-project/recipes: -# latency -> multi_node_tp (TP16 across two nodes) -# balanced -> multi_node_tep (TP16 + expert parallelism) -# throughput -> multi_node_dep (DEP16, eight local DP ranks per node) - -source "$(dirname "$0")/../../benchmark_lib.sh" - -check_env_vars MODEL MODEL_PATH PORT KIMIK3_STRATEGY CONC_LIST - -NODE_COUNT="${KIMIK3_NODE_COUNT:-2}" -GPUS_PER_NODE="${KIMIK3_GPUS_PER_NODE:-8}" -NODE_RANK="${SLURM_PROCID:?SLURM_PROCID must identify the vLLM node rank}" -MASTER_ADDR="${KIMIK3_MASTER_ADDR:?KIMIK3_MASTER_ADDR must identify rank zero}" - -if [ "$NODE_COUNT" -ne 2 ] || [ "$GPUS_PER_NODE" -ne 8 ]; then - echo "Kimi K3 H200 Day-0 recipes require two nodes with eight GPUs each" >&2 - exit 1 -fi - -read -r -a CONCURRENCIES <<< "$CONC_LIST" -MAX_CONCURRENCY=0 -for concurrency in "${CONCURRENCIES[@]}"; do - if ! [[ "$concurrency" =~ ^[1-9][0-9]*$ ]]; then - echo "Invalid AgentX concurrency: $concurrency" >&2 - exit 1 - fi - if [ "$concurrency" -gt "$MAX_CONCURRENCY" ]; then - MAX_CONCURRENCY="$concurrency" - fi -done - -export GLOO_SOCKET_IFNAME="${GLOO_SOCKET_IFNAME:-eth0}" -export NCCL_SOCKET_IFNAME="${NCCL_SOCKET_IFNAME:-eth0}" -export VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1 -export VLLM_ENGINE_READY_TIMEOUT_S="${VLLM_ENGINE_READY_TIMEOUT_S:-7200}" -export PYTHONNOUSERSITE=1 - -VLLM_CMD=( - vllm serve "$MODEL_PATH" - --served-model-name "$MODEL" - --host 0.0.0.0 - --port "$PORT" - --trust-remote-code - --load-format fastsafetensors - --moe-backend marlin - --gpu-memory-utilization 0.95 - --no-enable-flashinfer-autotune - --disable-custom-all-reduce - --enable-prefix-caching - --enable-auto-tool-choice - --tool-call-parser kimi_k3 - --reasoning-parser kimi_k3 - --language-model-only - --max-model-len 1048576 - --max-num-seqs "$MAX_CONCURRENCY" -) - -case "$KIMIK3_STRATEGY" in - latency) - VLLM_CMD+=( - --tensor-parallel-size "$((NODE_COUNT * GPUS_PER_NODE))" - --nnodes "$NODE_COUNT" - --node-rank "$NODE_RANK" - --master-addr "$MASTER_ADDR" - -cc.pass_config.fuse_allreduce_rms=False - ) - if [ "$NODE_RANK" -gt 0 ]; then - VLLM_CMD+=(--headless) - fi - ;; - balanced) - VLLM_CMD+=( - --tensor-parallel-size "$((NODE_COUNT * GPUS_PER_NODE))" - --nnodes "$NODE_COUNT" - --node-rank "$NODE_RANK" - --master-addr "$MASTER_ADDR" - --enable-expert-parallel - -cc.pass_config.fuse_allreduce_rms=False - ) - if [ "$NODE_RANK" -gt 0 ]; then - VLLM_CMD+=(--headless) - fi - ;; - throughput) - VLLM_CMD+=( - --data-parallel-size "$((NODE_COUNT * GPUS_PER_NODE))" - --data-parallel-size-local "$GPUS_PER_NODE" - --data-parallel-address "$MASTER_ADDR" - --data-parallel-start-rank "$((NODE_RANK * GPUS_PER_NODE))" - --data-parallel-hybrid-lb - --enable-expert-parallel - ) - ;; - *) - echo "Unsupported KIMIK3_STRATEGY: $KIMIK3_STRATEGY" >&2 - exit 1 - ;; -esac - -printf 'Kimi K3 rank %s command: ' "$NODE_RANK" -printf '%q ' "${VLLM_CMD[@]}" -printf '\n' - -if [[ "${KIMIK3_DRY_RUN:-0}" == "1" ]]; then - exit 0 -fi - -exec "${VLLM_CMD[@]}" diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh new file mode 100755 index 0000000000..19986e217a --- /dev/null +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -0,0 +1,150 @@ +#!/usr/bin/env bash +set -euo pipefail +set -x + +# Scheduler- and hardware-independent aggregated vLLM server for Kimi K3 MXFP4. +# +# The benchmark configuration selects one of the official aggregate strategies: +# https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200 +# +# The runner connector supplies node ranks, rendezvous, and local GPU count. +# This script only translates the requested TP/EP/DP topology into vLLM flags. + +# shellcheck disable=SC1091 # Resolved relative to this entrypoint at runtime. +source "$(dirname "$0")/../../benchmark_lib.sh" + +check_env_vars \ + MODEL \ + MODEL_PATH \ + PORT \ + CONC_LIST \ + PREFILL_TP \ + PREFILL_EP \ + PREFILL_DP_ATTN \ + DECODE_NUM_WORKERS \ + MULTINODE_NODE_COUNT \ + MULTINODE_GPUS_PER_NODE \ + MULTINODE_NODE_RANK \ + MULTINODE_MASTER_ADDR + +NODE_COUNT="$MULTINODE_NODE_COUNT" +GPUS_PER_NODE="$MULTINODE_GPUS_PER_NODE" +NODE_RANK="$MULTINODE_NODE_RANK" +MASTER_ADDR="$MULTINODE_MASTER_ADDR" + +for topology_value in \ + "$NODE_COUNT" \ + "$GPUS_PER_NODE" \ + "$NODE_RANK" \ + "$PREFILL_TP" \ + "$PREFILL_EP" \ + "$DECODE_NUM_WORKERS"; do + if ! [[ "$topology_value" =~ ^[0-9]+$ ]]; then + echo "Invalid multi-node topology value: $topology_value" >&2 + exit 1 + fi +done +if [ "$NODE_COUNT" -eq 0 ] || [ "$GPUS_PER_NODE" -eq 0 ] || \ + [ "$NODE_RANK" -ge "$NODE_COUNT" ]; then + echo "Invalid multi-node rank layout: rank=$NODE_RANK nodes=$NODE_COUNT GPUs/node=$GPUS_PER_NODE" >&2 + exit 1 +fi +if [ "$PREFILL_TP" -eq 0 ] || [ "$PREFILL_EP" -eq 0 ]; then + echo "PREFILL_TP and PREFILL_EP must be positive" >&2 + exit 1 +fi +WORLD_SIZE=$((NODE_COUNT * GPUS_PER_NODE)) +if [ "$DECODE_NUM_WORKERS" -ne 0 ]; then + echo "The aggregated Kimi K3 entrypoint does not accept decode workers" >&2 + exit 1 +fi + +read -r -a CONCURRENCIES <<< "$CONC_LIST" +MAX_CONCURRENCY=0 +for concurrency in "${CONCURRENCIES[@]}"; do + if ! [[ "$concurrency" =~ ^[1-9][0-9]*$ ]]; then + echo "Invalid AgentX concurrency: $concurrency" >&2 + exit 1 + fi + if [ "$concurrency" -gt "$MAX_CONCURRENCY" ]; then + MAX_CONCURRENCY="$concurrency" + fi +done + +export VLLM_ENGINE_READY_TIMEOUT_S="${VLLM_ENGINE_READY_TIMEOUT_S:-7200}" +export PYTHONNOUSERSITE=1 + +VLLM_CMD=( + vllm serve "$MODEL_PATH" + --served-model-name "$MODEL" + --host 0.0.0.0 + --port "$PORT" + --trust-remote-code + --load-format fastsafetensors + --moe-backend "${VLLM_MOE_BACKEND:-auto}" + --gpu-memory-utilization 0.95 + --enable-prefix-caching + --enable-auto-tool-choice + --tool-call-parser kimi_k3 + --reasoning-parser kimi_k3 + --language-model-only + --max-model-len 1048576 + --max-num-seqs "$MAX_CONCURRENCY" +) + +if [[ "${VLLM_DISABLE_FLASHINFER_AUTOTUNE:-0}" == "1" ]]; then + VLLM_CMD+=(--no-enable-flashinfer-autotune) +fi +if [[ "${VLLM_DISABLE_CUSTOM_ALL_REDUCE:-0}" == "1" ]]; then + VLLM_CMD+=(--disable-custom-all-reduce) +fi + +if [[ "$PREFILL_DP_ATTN" == "true" ]]; then + DEPLOYMENT_ORIENTATION="throughput" + VLLM_CMD+=( + --data-parallel-size "$WORLD_SIZE" + --data-parallel-size-local "$GPUS_PER_NODE" + --data-parallel-address "$MASTER_ADDR" + --data-parallel-start-rank "$((NODE_RANK * GPUS_PER_NODE))" + --data-parallel-hybrid-lb + ) + if [ "$PREFILL_EP" -gt 1 ]; then + VLLM_CMD+=(--enable-expert-parallel) + fi +elif [[ "$PREFILL_DP_ATTN" == "false" ]]; then + if [ "$PREFILL_TP" -ne "$WORLD_SIZE" ]; then + echo "Cross-node TP ($PREFILL_TP) must match the allocated world size ($WORLD_SIZE)" >&2 + exit 1 + fi + + DEPLOYMENT_ORIENTATION="latency" + VLLM_CMD+=( + --tensor-parallel-size "$PREFILL_TP" + --nnodes "$NODE_COUNT" + --node-rank "$NODE_RANK" + --master-addr "$MASTER_ADDR" + ) + if [ "$PREFILL_EP" -gt 1 ]; then + DEPLOYMENT_ORIENTATION="balanced" + VLLM_CMD+=(--enable-expert-parallel) + fi + if [[ "${VLLM_DISABLE_FUSED_ALLREDUCE_RMS:-0}" == "1" ]]; then + VLLM_CMD+=(-cc.pass_config.fuse_allreduce_rms=False) + fi + if [ "$NODE_RANK" -gt 0 ]; then + VLLM_CMD+=(--headless) + fi +else + echo "PREFILL_DP_ATTN must be true or false, got: $PREFILL_DP_ATTN" >&2 + exit 1 +fi + +printf 'Kimi K3 %s-oriented rank %s command: ' "$DEPLOYMENT_ORIENTATION" "$NODE_RANK" +printf '%q ' "${VLLM_CMD[@]}" +printf '\n' + +if [[ "${KIMIK3_DRY_RUN:-0}" == "1" ]]; then + exit 0 +fi + +exec "${VLLM_CMD[@]}" diff --git a/benchmarks/multi_node/agentic_srt.sh b/benchmarks/multi_node/agentic_srt.sh index 79a36da524..642659c3e4 100644 --- a/benchmarks/multi_node/agentic_srt.sh +++ b/benchmarks/multi_node/agentic_srt.sh @@ -2,9 +2,9 @@ set -euo pipefail set -x -# Client-only agentic trace replay for srt-slurm multinode jobs. -# srt-slurm owns server startup; this script runs as benchmark.type=custom -# against the already-ready frontend on the head node. +# Client-only agentic trace replay for externally managed multi-node jobs. +# A deployment layer such as srt-slurm or a runner connector owns server +# startup; this script runs against the already-ready frontend on the head node. INFMAX_CONTAINER_WORKSPACE="${INFMAX_CONTAINER_WORKSPACE:-/infmax-workspace}" source "$INFMAX_CONTAINER_WORKSPACE/benchmarks/benchmark_lib.sh" diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 8240569485..4ce409a5ae 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1471,7 +1471,9 @@ kimik2.5-int4-h200-vllm-agentic: # nodes. These are the three aggregated strategies from the official H200 # recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): # multi-node TP is latency-oriented, TEP is balanced, and DEP is -# throughput-oriented. P/D disaggregation is intentionally deferred. +# throughput-oriented. The deployment settings feed a reusable cluster +# connector; the in-container Kimi entrypoint has no H200 or Slurm assumptions. +# P/D disaggregation is intentionally deferred. kimik3-fp4-h200-vllm-agentic: image: vllm/vllm-openai:kimi-k3 model: moonshotai/Kimi-K3 @@ -1494,7 +1496,17 @@ kimik3-fp4-h200-vllm-agentic: ep: 1 dp-attn: false additional-settings: - - "KIMIK3_STRATEGY=latency" + - "MULTINODE_GPU_COUNT=16" + - "MULTINODE_SERVER_SCRIPT=benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh" + - "MULTINODE_CLIENT_SCRIPT=benchmarks/multi_node/agentic_srt.sh" + - "MULTINODE_STARTUP_TIMEOUT_SECONDS=7200" + - "INFMAX_CONTAINER_WORKSPACE=/workspace" + - "RESULT_DIR=/workspace/LOGS/agentic" + - "VLLM_MOE_BACKEND=marlin" + - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" + - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" + - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" + - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 16 @@ -1510,7 +1522,17 @@ kimik3-fp4-h200-vllm-agentic: ep: 16 dp-attn: false additional-settings: - - "KIMIK3_STRATEGY=balanced" + - "MULTINODE_GPU_COUNT=16" + - "MULTINODE_SERVER_SCRIPT=benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh" + - "MULTINODE_CLIENT_SCRIPT=benchmarks/multi_node/agentic_srt.sh" + - "MULTINODE_STARTUP_TIMEOUT_SECONDS=7200" + - "INFMAX_CONTAINER_WORKSPACE=/workspace" + - "RESULT_DIR=/workspace/LOGS/agentic" + - "VLLM_MOE_BACKEND=marlin" + - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" + - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" + - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" + - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 16 @@ -1526,7 +1548,17 @@ kimik3-fp4-h200-vllm-agentic: ep: 16 dp-attn: true additional-settings: - - "KIMIK3_STRATEGY=throughput" + - "MULTINODE_GPU_COUNT=16" + - "MULTINODE_SERVER_SCRIPT=benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh" + - "MULTINODE_CLIENT_SCRIPT=benchmarks/multi_node/agentic_srt.sh" + - "MULTINODE_STARTUP_TIMEOUT_SECONDS=7200" + - "INFMAX_CONTAINER_WORKSPACE=/workspace" + - "RESULT_DIR=/workspace/LOGS/agentic" + - "VLLM_MOE_BACKEND=marlin" + - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" + - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" + - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" + - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 8 diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 6940197af8..7236bd1acd 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5197,6 +5197,6 @@ description: - "Add Kimi K3 Day-0 AgentX support on two 8xH200 nodes with the official vllm/vllm-openai:kimi-k3 image and pre-staged 1.5 TB moonshotai/Kimi-K3 checkpoint" - "Reference the official H200 recipe at https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200: latency-oriented multi-node TP16, balanced TEP16, and throughput-oriented DEP16" - - "Launch aggregated vLLM directly under Slurm instead of srt-slurm/Dynamo; P/D disaggregation is intentionally deferred" + - "Launch aggregated vLLM through a reusable Slurm/Pyxis multi-node connector that separates cluster allocation, mounts, networking, readiness, and cleanup from the hardware-agnostic Kimi K3 benchmark entrypoint; P/D disaggregation is intentionally deferred" - "Sweep AgentX concurrency 1-8 for latency, 4-32 for balanced, and 16-128 for throughput with prefix caching, the kimi_k3 tool/reasoning parsers, and the full 1M-token model context" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 diff --git a/runners/connectors/slurm_pyxis.sh b/runners/connectors/slurm_pyxis.sh new file mode 100755 index 0000000000..6b716eab22 --- /dev/null +++ b/runners/connectors/slurm_pyxis.sh @@ -0,0 +1,301 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Reusable connector for a long-running multi-node service and an overlapping +# benchmark client on Slurm clusters using Pyxis/Enroot. +# +# Deployment inputs: +# MULTINODE_GPU_COUNT +# MULTINODE_SERVER_SCRIPT +# MULTINODE_CLIENT_SCRIPT +# +# Runner profile inputs: +# SLURM_PARTITION +# SLURM_ACCOUNT (optional) +# SLURM_PYXIS_GPUS_PER_NODE +# SLURM_PYXIS_IMAGE_CACHE_DIR +# SLURM_PYXIS_CONTAINER_MOUNTS +# SLURM_PYXIS_CONTAINER_WORKDIR +# MODEL_HOST_PATH +# MODEL_PATH +# +# The server receives a scheduler-independent contract: +# MULTINODE_NODE_COUNT +# MULTINODE_GPUS_PER_NODE +# MULTINODE_NODE_RANK +# MULTINODE_MASTER_ADDR + +_slurm_pyxis_require_vars() { + local variable_name + + for variable_name in "$@"; do + if [[ -z "${!variable_name:-}" ]]; then + echo "Missing required Slurm/Pyxis connector variable: $variable_name" >&2 + return 1 + fi + done +} + +_slurm_pyxis_is_positive_integer() { + [[ "$1" =~ ^[1-9][0-9]*$ ]] +} + +_slurm_pyxis_package_logs() { + if [[ "${_SLURM_PYXIS_LOGS_PACKAGED:-0}" == "1" ]]; then + return + fi + _SLURM_PYXIS_LOGS_PACKAGED=1 + + if [[ -n "${_SLURM_PYXIS_SERVER_LOG_DIR:-}" && \ + -d "$_SLURM_PYXIS_SERVER_LOG_DIR" ]]; then + tar czf "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" \ + -C "$_SLURM_PYXIS_SERVER_LOG_DIR" . || true + fi +} + +_slurm_pyxis_cleanup() { + if [[ -n "${_SLURM_PYXIS_SERVER_STEP_PID:-}" ]]; then + kill "$_SLURM_PYXIS_SERVER_STEP_PID" 2>/dev/null || true + wait "$_SLURM_PYXIS_SERVER_STEP_PID" 2>/dev/null || true + _SLURM_PYXIS_SERVER_STEP_PID="" + fi + + _slurm_pyxis_package_logs + + if [[ -n "${_SLURM_PYXIS_JOB_ID:-}" ]]; then + scancel "$_SLURM_PYXIS_JOB_ID" 2>/dev/null || true + _SLURM_PYXIS_JOB_ID="" + fi +} + +_slurm_pyxis_exit_trap() { + local exit_code="$1" + + trap - EXIT INT TERM + _slurm_pyxis_cleanup + exit "$exit_code" +} + +run_slurm_pyxis_multinode_service() { + local node_count + local squash_file + local lock_file + local docker_image + local allocated_nodelist + local head_node + local startup_timeout + local poll_interval + local max_attempts + local attempt + local ready=0 + local client_rc + local slurm_gres + local -a allocation_args + + _slurm_pyxis_require_vars \ + IMAGE \ + RUNNER_NAME \ + GITHUB_WORKSPACE \ + PORT \ + MULTINODE_GPU_COUNT \ + MULTINODE_SERVER_SCRIPT \ + MULTINODE_CLIENT_SCRIPT \ + SLURM_PARTITION \ + SLURM_PYXIS_GPUS_PER_NODE \ + SLURM_PYXIS_IMAGE_CACHE_DIR \ + SLURM_PYXIS_CONTAINER_MOUNTS \ + SLURM_PYXIS_CONTAINER_WORKDIR \ + MODEL_HOST_PATH \ + MODEL_PATH || return 1 + + if ! _slurm_pyxis_is_positive_integer "$MULTINODE_GPU_COUNT"; then + echo "MULTINODE_GPU_COUNT must be a positive integer" >&2 + return 1 + fi + if ! _slurm_pyxis_is_positive_integer "$SLURM_PYXIS_GPUS_PER_NODE"; then + echo "SLURM_PYXIS_GPUS_PER_NODE must be a positive integer" >&2 + return 1 + fi + if (( MULTINODE_GPU_COUNT % SLURM_PYXIS_GPUS_PER_NODE != 0 )); then + echo "MULTINODE_GPU_COUNT ($MULTINODE_GPU_COUNT) must be divisible by the runner's GPUs per node ($SLURM_PYXIS_GPUS_PER_NODE)" >&2 + return 1 + fi + + node_count=$((MULTINODE_GPU_COUNT / SLURM_PYXIS_GPUS_PER_NODE)) + startup_timeout="${MULTINODE_STARTUP_TIMEOUT_SECONDS:-3600}" + poll_interval="${MULTINODE_HEALTH_POLL_SECONDS:-10}" + if ! _slurm_pyxis_is_positive_integer "$startup_timeout" || \ + ! _slurm_pyxis_is_positive_integer "$poll_interval"; then + echo "Multi-node startup timeout and poll interval must be positive integers" >&2 + return 1 + fi + + if [[ "$MULTINODE_SERVER_SCRIPT" == /* || \ + ! -f "$GITHUB_WORKSPACE/$MULTINODE_SERVER_SCRIPT" ]]; then + echo "MULTINODE_SERVER_SCRIPT must be a repository-relative file: $MULTINODE_SERVER_SCRIPT" >&2 + return 1 + fi + if [[ "$MULTINODE_CLIENT_SCRIPT" == /* || \ + ! -f "$GITHUB_WORKSPACE/$MULTINODE_CLIENT_SCRIPT" ]]; then + echo "MULTINODE_CLIENT_SCRIPT must be a repository-relative file: $MULTINODE_CLIENT_SCRIPT" >&2 + return 1 + fi + + echo "Slurm/Pyxis deployment: ${MULTINODE_GPU_COUNT} GPUs as ${node_count} nodes x ${SLURM_PYXIS_GPUS_PER_NODE} GPUs" + if [[ "${MULTINODE_CONNECTOR_DRY_RUN:-0}" == "1" ]]; then + echo "Server entrypoint: $MULTINODE_SERVER_SCRIPT" + echo "Client entrypoint: $MULTINODE_CLIENT_SCRIPT" + return + fi + + if [[ ! -d "$MODEL_HOST_PATH" ]]; then + echo "Pre-staged model path not found: $MODEL_HOST_PATH" >&2 + return 1 + fi + + _SLURM_PYXIS_SERVER_LOG_DIR="${MULTINODE_SERVER_LOG_DIR:-$GITHUB_WORKSPACE/multinode_server_logs}" + _SLURM_PYXIS_LOGS_PACKAGED=0 + _SLURM_PYXIS_JOB_ID="" + _SLURM_PYXIS_SERVER_STEP_PID="" + + mkdir -p "$SLURM_PYXIS_IMAGE_CACHE_DIR" "$_SLURM_PYXIS_SERVER_LOG_DIR" + squash_file="$SLURM_PYXIS_IMAGE_CACHE_DIR/$(echo "$IMAGE" | sed 's/[\/:@#]/_/g').sqsh" + lock_file="${squash_file}.lock" + docker_image="${IMAGE//#//}" + slurm_gres="${SLURM_PYXIS_GRES:-gpu:$SLURM_PYXIS_GPUS_PER_NODE}" + + allocation_args=( + "--partition=$SLURM_PARTITION" + "--nodes=$node_count" + "--ntasks-per-node=1" + "--gres=$slurm_gres" + --exclusive + "--time=${MULTINODE_TIME_LIMIT_MINUTES:-240}" + --no-shell + "--job-name=$RUNNER_NAME" + ) + if [[ -n "${SLURM_ACCOUNT:-}" ]]; then + allocation_args+=("--account=$SLURM_ACCOUNT") + fi + + salloc "${allocation_args[@]}" + _SLURM_PYXIS_JOB_ID=$(squeue --name="$RUNNER_NAME" -u "$USER" -h -o %A | sed -n '1p') + if [[ -z "$_SLURM_PYXIS_JOB_ID" ]]; then + echo "Failed to resolve the Slurm/Pyxis allocation" >&2 + scancel --name="$RUNNER_NAME" 2>/dev/null || true + return 1 + fi + + trap '_slurm_pyxis_exit_trap $?' EXIT + trap 'exit 130' INT + trap 'exit 143' TERM + + allocated_nodelist=$(squeue -j "$_SLURM_PYXIS_JOB_ID" -h -o %N) + head_node=$(scontrol show hostnames "$allocated_nodelist" | sed -n '1p') + if [[ -z "$head_node" ]]; then + echo "Failed to resolve the rank-zero node" >&2 + return 1 + fi + + # Import once into the runner profile's shared cache. The image lock keeps + # concurrent jobs from replacing the same squash file. + # shellcheck disable=SC2016 # The worker-side shell expands positional args. + srun \ + --jobid="$_SLURM_PYXIS_JOB_ID" \ + --nodes=1 \ + --ntasks=1 \ + --nodelist="$head_node" \ + bash -c ' + set -e + image_cache_dir=$1 + squash_file=$2 + lock_file=$3 + docker_image=$4 + mkdir -p "$image_cache_dir" "$HOME/.cache/enroot" + export ENROOT_CACHE_PATH="$HOME/.cache/enroot" + exec 9>"$lock_file" + flock -w "${SLURM_PYXIS_IMPORT_LOCK_TIMEOUT_SECONDS:-1800}" 9 + if unsquashfs -l "$squash_file" >/dev/null 2>&1; then + echo "Using cached image: $squash_file" + else + rm -f "$squash_file" + enroot import -o "$squash_file" "docker://$docker_image" + unsquashfs -l "$squash_file" >/dev/null + chmod a+r "$squash_file" || true + fi + ' bash "$SLURM_PYXIS_IMAGE_CACHE_DIR" "$squash_file" "$lock_file" "$docker_image" + + export MULTINODE_NODE_COUNT="$node_count" + export MULTINODE_GPUS_PER_NODE="$SLURM_PYXIS_GPUS_PER_NODE" + export MULTINODE_MASTER_ADDR="$head_node" + + # The connector translates SLURM_PROCID into the scheduler-independent + # node-rank contract before invoking the in-container server entrypoint. + # shellcheck disable=SC2016 # SLURM_PROCID is created inside each srun task. + srun \ + --jobid="$_SLURM_PYXIS_JOB_ID" \ + --nodes="$node_count" \ + --ntasks="$node_count" \ + --ntasks-per-node=1 \ + --kill-on-bad-exit=1 \ + --container-image="$squash_file" \ + --container-mounts="$SLURM_PYXIS_CONTAINER_MOUNTS" \ + --no-container-mount-home \ + --container-remap-root \ + --container-workdir="$SLURM_PYXIS_CONTAINER_WORKDIR" \ + --no-container-entrypoint \ + --export=ALL \ + bash -c 'export MULTINODE_NODE_RANK="$SLURM_PROCID"; exec bash "$MULTINODE_SERVER_SCRIPT"' \ + >"$_SLURM_PYXIS_SERVER_LOG_DIR/combined.log" 2>&1 & + _SLURM_PYXIS_SERVER_STEP_PID=$! + + max_attempts=$(((startup_timeout + poll_interval - 1) / poll_interval)) + for ((attempt = 1; attempt <= max_attempts; attempt++)); do + if curl --output /dev/null --silent --fail \ + "http://$head_node:$PORT${MULTINODE_HEALTH_PATH:-/health}"; then + ready=1 + break + fi + if ! kill -0 "$_SLURM_PYXIS_SERVER_STEP_PID" 2>/dev/null; then + echo "Multi-node server step exited before becoming ready" >&2 + tail -n 200 "$_SLURM_PYXIS_SERVER_LOG_DIR/combined.log" >&2 || true + return 1 + fi + if (( attempt * poll_interval % 60 == 0 )); then + echo "Waiting for multi-node server readiness ($((attempt * poll_interval))s elapsed)" + tail -n 20 "$_SLURM_PYXIS_SERVER_LOG_DIR/combined.log" || true + fi + sleep "$poll_interval" + done + if [[ "$ready" != "1" ]]; then + echo "Multi-node server did not become healthy within $startup_timeout seconds" >&2 + tail -n 200 "$_SLURM_PYXIS_SERVER_LOG_DIR/combined.log" >&2 || true + return 1 + fi + + set +e + srun \ + --jobid="$_SLURM_PYXIS_JOB_ID" \ + --overlap \ + --nodes=1 \ + --ntasks=1 \ + --nodelist="$head_node" \ + --container-image="$squash_file" \ + --container-mounts="$SLURM_PYXIS_CONTAINER_MOUNTS" \ + --no-container-mount-home \ + --container-remap-root \ + --container-workdir="$SLURM_PYXIS_CONTAINER_WORKDIR" \ + --no-container-entrypoint \ + --export=ALL,MULTINODE_NODE_RANK=0 \ + bash "$MULTINODE_CLIENT_SCRIPT" + client_rc=$? + set -e + + _slurm_pyxis_cleanup + trap - EXIT INT TERM + return "$client_rc" +} + +if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then + run_slurm_pyxis_multinode_service +fi diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index e6b30a3b39..8c20da5752 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -7,175 +7,37 @@ SLURM_ACCOUNT="sa-shared" set -x -run_kimik3_agentic_vllm() { - local node_count=2 - local gpus_per_node=8 - local model_host_path="/models/gharunners/hf-hub-cache/Kimi-K3" - local model_container_path="/models/hf-hub-cache/Kimi-K3" - local hf_cache_host_path="/models/gharunners/hf-hub-cache" - local hf_cache_container_path="/models/hf-hub-cache" - local aiperf_cache_host_path="/home/sa-shared/gharunners/ai-perf-cache" - local squash_dir="/data/gharunners/containers" - local squash_file - local lock_file - local server_log_dir="$GITHUB_WORKSPACE/agentic_logs/server" - local container_mounts - local job_id - local allocated_nodelist - local head_node - local server_step_pid - local client_rc - local ready=0 - - squash_file="$squash_dir/$(echo "$IMAGE" | sed 's/[\/:@#]/_/g').sqsh" - lock_file="${squash_file}.lock" - - if [[ "${IS_AGENTIC:-0}" != "1" || "$FRAMEWORK" != "vllm" || \ - "$MODEL_PREFIX" != "kimik3" || "$PRECISION" != "fp4" ]]; then - echo "Direct H200 multi-node vLLM is only configured for Kimi K3 FP4 AgentX" >&2 - return 1 - fi - if [[ ! -d "$model_host_path" ]]; then - echo "Pre-staged Kimi K3 weights not found at $model_host_path" >&2 - return 1 - fi - - mkdir -p "$squash_dir" "$server_log_dir" "$aiperf_cache_host_path" - container_mounts="$GITHUB_WORKSPACE:/workspace,$hf_cache_host_path:$hf_cache_container_path,$aiperf_cache_host_path:/aiperf_mmap_cache" - - salloc \ - --partition="$SLURM_PARTITION" \ - --account="$SLURM_ACCOUNT" \ - --nodes="$node_count" \ - --ntasks-per-node=1 \ - --gres="gpu:$gpus_per_node" \ - --exclusive \ - --time=240 \ - --no-shell \ - --job-name="$RUNNER_NAME" - job_id=$(squeue --name="$RUNNER_NAME" -u "$USER" -h -o %A | head -n1) - if [[ -z "$job_id" ]]; then - echo "Failed to resolve the Kimi K3 H200 Slurm allocation" >&2 - return 1 - fi - - cleanup_kimik3_allocation() { - local exit_code=$? - trap - EXIT INT TERM - set +e - if [[ -n "${server_step_pid:-}" ]]; then - kill "$server_step_pid" 2>/dev/null || true - wait "$server_step_pid" 2>/dev/null || true - fi - scancel "$job_id" 2>/dev/null || true - exit "$exit_code" - } - trap cleanup_kimik3_allocation EXIT - trap 'exit 130' INT - trap 'exit 143' TERM - - allocated_nodelist=$(squeue -j "$job_id" -h -o %N) - head_node=$(scontrol show hostnames "$allocated_nodelist" | head -n1) - if [[ -z "$head_node" ]]; then - echo "Failed to resolve the Kimi K3 rank-zero node" >&2 - return 1 - fi - - # Import once into the cluster's shared squash cache. All nodes use this - # same file, so a per-image flock prevents concurrent Day-0 jobs racing. - srun --jobid="$job_id" --nodes=1 --ntasks=1 --nodelist="$head_node" bash -c " - mkdir -p '$squash_dir' - exec 9>'$lock_file' - flock -w 1800 9 || { echo 'Failed to lock $squash_file' >&2; exit 1; } - if unsquashfs -l '$squash_file' >/dev/null 2>&1; then - echo 'Using cached Kimi K3 image: $squash_file' - else - rm -f '$squash_file' - enroot import -o '$squash_file' 'docker://$IMAGE' - unsquashfs -l '$squash_file' >/dev/null - chmod a+r '$squash_file' || true - fi - " - - # One vLLM process per node. TP/TEP followers use --headless; DEP starts - # eight local DP ranks per node. The benchmark client runs later as an - # overlapping CPU-only step on rank zero. - srun \ - --jobid="$job_id" \ - --nodes="$node_count" \ - --ntasks="$node_count" \ - --ntasks-per-node=1 \ - --kill-on-bad-exit=1 \ - --container-image="$squash_file" \ - --container-mounts="$container_mounts" \ - --no-container-mount-home \ - --container-remap-root \ - --container-workdir=/workspace \ - --no-container-entrypoint \ - --export="ALL,MODEL_PATH=$model_container_path,HF_HUB_CACHE=$hf_cache_container_path,AIPERF_DATASET_MMAP_CACHE_DIR=/aiperf_mmap_cache,KIMIK3_NODE_COUNT=$node_count,KIMIK3_GPUS_PER_NODE=$gpus_per_node,KIMIK3_MASTER_ADDR=$head_node,PORT=8888" \ - bash benchmarks/multi_node/agentic/kimik3_fp4_h200_vllm.sh \ - >"$server_log_dir/combined.log" 2>&1 & - server_step_pid=$! - - # A 1.5 TB checkpoint can take much longer than an ordinary model to load. - # Keep checking the server step while waiting so early launch failures - # surface immediately instead of waiting for the full two-hour timeout. - for ((attempt = 1; attempt <= 720; attempt++)); do - if curl --output /dev/null --silent --fail "http://$head_node:8888/health"; then - ready=1 - break - fi - if ! kill -0 "$server_step_pid" 2>/dev/null; then - echo "Kimi K3 server step exited before becoming ready" >&2 - tail -n 200 "$server_log_dir/combined.log" >&2 || true - return 1 - fi - if (( attempt % 6 == 0 )); then - echo "Waiting for Kimi K3 server readiness ($((attempt * 10))s elapsed)" - tail -n 20 "$server_log_dir/combined.log" || true - fi - sleep 10 - done - if [[ "$ready" != "1" ]]; then - echo "Kimi K3 server did not become healthy within 7200 seconds" >&2 - tail -n 200 "$server_log_dir/combined.log" >&2 || true - return 1 - fi - - set +e - srun \ - --jobid="$job_id" \ - --overlap \ - --nodes=1 \ - --ntasks=1 \ - --nodelist="$head_node" \ - --container-image="$squash_file" \ - --container-mounts="$container_mounts" \ - --no-container-mount-home \ - --container-remap-root \ - --container-workdir=/workspace \ - --no-container-entrypoint \ - --export="ALL,MODEL_PATH=$model_container_path,HF_HUB_CACHE=$hf_cache_container_path,AIPERF_DATASET_MMAP_CACHE_DIR=/aiperf_mmap_cache,INFMAX_CONTAINER_WORKSPACE=/workspace,RESULT_DIR=/workspace/agentic_logs,PORT=8888" \ - bash benchmarks/multi_node/agentic_srt.sh - client_rc=$? - set -e - - kill "$server_step_pid" 2>/dev/null || true - wait "$server_step_pid" 2>/dev/null || true - server_step_pid="" - scancel "$job_id" 2>/dev/null || true - job_id="" - trap - EXIT INT TERM - return "$client_rc" -} - -# The official Kimi K3 H200 TP/TEP/DEP strategies are aggregated vLLM -# deployments. Keep them on the direct Slurm path; srt-slurm remains the -# orchestrator for the existing Dynamo disaggregated configurations below. -if [[ "$IS_MULTINODE" == "true" && "${IS_AGENTIC:-0}" == "1" && \ - "$FRAMEWORK" == "vllm" && "$MODEL_PREFIX" == "kimik3" && \ - "$PRECISION" == "fp4" ]]; then - run_kimik3_agentic_vllm +# Native multi-node benchmarks opt into the reusable service connector by +# providing in-container server and client entrypoints. This runner only maps +# H200 DGXC storage, networking, and Slurm/Pyxis resources. +if [[ "$IS_MULTINODE" == "true" && -n "${MULTINODE_SERVER_SCRIPT:-}" ]]; then + case "$MODEL_PREFIX/$PRECISION" in + kimik3/fp4) + export MODEL_HOST_PATH="/models/gharunners/hf-hub-cache/Kimi-K3" + export MODEL_PATH="/models/hf-hub-cache/Kimi-K3" + ;; + *) + echo "No native multi-node model mapping for $MODEL_PREFIX/$PRECISION on H200 DGXC" >&2 + exit 1 + ;; + esac + + hf_cache_host_path="/models/gharunners/hf-hub-cache" + hf_cache_container_path="/models/hf-hub-cache" + aiperf_cache_host_path="/home/sa-shared/gharunners/ai-perf-cache" + mkdir -p "$aiperf_cache_host_path" + + export PORT="${PORT:-8888}" + export HF_HUB_CACHE="$hf_cache_container_path" + export AIPERF_DATASET_MMAP_CACHE_DIR="/aiperf_mmap_cache" + export GLOO_SOCKET_IFNAME="${GLOO_SOCKET_IFNAME:-eth0}" + export NCCL_SOCKET_IFNAME="${NCCL_SOCKET_IFNAME:-eth0}" + export SLURM_PYXIS_GPUS_PER_NODE=8 + export SLURM_PYXIS_IMAGE_CACHE_DIR="/data/gharunners/containers" + export SLURM_PYXIS_CONTAINER_WORKDIR="/workspace" + export SLURM_PYXIS_CONTAINER_MOUNTS="$GITHUB_WORKSPACE:/workspace,$hf_cache_host_path:$hf_cache_container_path,$aiperf_cache_host_path:/aiperf_mmap_cache" + + bash "$GITHUB_WORKSPACE/runners/connectors/slurm_pyxis.sh" exit $? fi From c31b634f7f5dce51b898ad12775c1ca2006fb97d Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 18:32:54 -0500 Subject: [PATCH 04/62] refactor(runners): simplify native multi-node launch Inline the concrete Slurm/Pyxis lifecycle in the H200 runner and remove the speculative connector layer. Preserve only the scheduler-independent rank and rendezvous contract for in-container benchmarks. --- .../multi_node/agentic/kimik3_fp4_vllm.sh | 59 +--- configs/nvidia-master.yaml | 25 +- perf-changelog.yaml | 2 +- runners/connectors/slurm_pyxis.sh | 301 ------------------ runners/launch_h200-dgxc-slurm.sh | 148 ++++++++- 5 files changed, 152 insertions(+), 383 deletions(-) delete mode 100755 runners/connectors/slurm_pyxis.sh diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 19986e217a..ad4c0cdc84 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -7,7 +7,7 @@ set -x # The benchmark configuration selects one of the official aggregate strategies: # https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200 # -# The runner connector supplies node ranks, rendezvous, and local GPU count. +# The runner supplies node ranks, rendezvous, and local GPU count. # This script only translates the requested TP/EP/DP topology into vLLM flags. # shellcheck disable=SC1091 # Resolved relative to this entrypoint at runtime. @@ -21,51 +21,15 @@ check_env_vars \ PREFILL_TP \ PREFILL_EP \ PREFILL_DP_ATTN \ - DECODE_NUM_WORKERS \ MULTINODE_NODE_COUNT \ MULTINODE_GPUS_PER_NODE \ MULTINODE_NODE_RANK \ MULTINODE_MASTER_ADDR -NODE_COUNT="$MULTINODE_NODE_COUNT" -GPUS_PER_NODE="$MULTINODE_GPUS_PER_NODE" -NODE_RANK="$MULTINODE_NODE_RANK" -MASTER_ADDR="$MULTINODE_MASTER_ADDR" - -for topology_value in \ - "$NODE_COUNT" \ - "$GPUS_PER_NODE" \ - "$NODE_RANK" \ - "$PREFILL_TP" \ - "$PREFILL_EP" \ - "$DECODE_NUM_WORKERS"; do - if ! [[ "$topology_value" =~ ^[0-9]+$ ]]; then - echo "Invalid multi-node topology value: $topology_value" >&2 - exit 1 - fi -done -if [ "$NODE_COUNT" -eq 0 ] || [ "$GPUS_PER_NODE" -eq 0 ] || \ - [ "$NODE_RANK" -ge "$NODE_COUNT" ]; then - echo "Invalid multi-node rank layout: rank=$NODE_RANK nodes=$NODE_COUNT GPUs/node=$GPUS_PER_NODE" >&2 - exit 1 -fi -if [ "$PREFILL_TP" -eq 0 ] || [ "$PREFILL_EP" -eq 0 ]; then - echo "PREFILL_TP and PREFILL_EP must be positive" >&2 - exit 1 -fi -WORLD_SIZE=$((NODE_COUNT * GPUS_PER_NODE)) -if [ "$DECODE_NUM_WORKERS" -ne 0 ]; then - echo "The aggregated Kimi K3 entrypoint does not accept decode workers" >&2 - exit 1 -fi - +WORLD_SIZE=$((MULTINODE_NODE_COUNT * MULTINODE_GPUS_PER_NODE)) read -r -a CONCURRENCIES <<< "$CONC_LIST" MAX_CONCURRENCY=0 for concurrency in "${CONCURRENCIES[@]}"; do - if ! [[ "$concurrency" =~ ^[1-9][0-9]*$ ]]; then - echo "Invalid AgentX concurrency: $concurrency" >&2 - exit 1 - fi if [ "$concurrency" -gt "$MAX_CONCURRENCY" ]; then MAX_CONCURRENCY="$concurrency" fi @@ -100,12 +64,11 @@ if [[ "${VLLM_DISABLE_CUSTOM_ALL_REDUCE:-0}" == "1" ]]; then fi if [[ "$PREFILL_DP_ATTN" == "true" ]]; then - DEPLOYMENT_ORIENTATION="throughput" VLLM_CMD+=( --data-parallel-size "$WORLD_SIZE" - --data-parallel-size-local "$GPUS_PER_NODE" - --data-parallel-address "$MASTER_ADDR" - --data-parallel-start-rank "$((NODE_RANK * GPUS_PER_NODE))" + --data-parallel-size-local "$MULTINODE_GPUS_PER_NODE" + --data-parallel-address "$MULTINODE_MASTER_ADDR" + --data-parallel-start-rank "$((MULTINODE_NODE_RANK * MULTINODE_GPUS_PER_NODE))" --data-parallel-hybrid-lb ) if [ "$PREFILL_EP" -gt 1 ]; then @@ -117,21 +80,19 @@ elif [[ "$PREFILL_DP_ATTN" == "false" ]]; then exit 1 fi - DEPLOYMENT_ORIENTATION="latency" VLLM_CMD+=( --tensor-parallel-size "$PREFILL_TP" - --nnodes "$NODE_COUNT" - --node-rank "$NODE_RANK" - --master-addr "$MASTER_ADDR" + --nnodes "$MULTINODE_NODE_COUNT" + --node-rank "$MULTINODE_NODE_RANK" + --master-addr "$MULTINODE_MASTER_ADDR" ) if [ "$PREFILL_EP" -gt 1 ]; then - DEPLOYMENT_ORIENTATION="balanced" VLLM_CMD+=(--enable-expert-parallel) fi if [[ "${VLLM_DISABLE_FUSED_ALLREDUCE_RMS:-0}" == "1" ]]; then VLLM_CMD+=(-cc.pass_config.fuse_allreduce_rms=False) fi - if [ "$NODE_RANK" -gt 0 ]; then + if [ "$MULTINODE_NODE_RANK" -gt 0 ]; then VLLM_CMD+=(--headless) fi else @@ -139,7 +100,7 @@ else exit 1 fi -printf 'Kimi K3 %s-oriented rank %s command: ' "$DEPLOYMENT_ORIENTATION" "$NODE_RANK" +printf 'Kimi K3 rank %s command: ' "$MULTINODE_NODE_RANK" printf '%q ' "${VLLM_CMD[@]}" printf '\n' diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 4ce409a5ae..a0eb020193 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1471,8 +1471,8 @@ kimik2.5-int4-h200-vllm-agentic: # nodes. These are the three aggregated strategies from the official H200 # recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): # multi-node TP is latency-oriented, TEP is balanced, and DEP is -# throughput-oriented. The deployment settings feed a reusable cluster -# connector; the in-container Kimi entrypoint has no H200 or Slurm assumptions. +# throughput-oriented. The runner owns Slurm/Pyxis; the in-container Kimi +# entrypoint only receives rank and rendezvous information. # P/D disaggregation is intentionally deferred. kimik3-fp4-h200-vllm-agentic: image: vllm/vllm-openai:kimi-k3 @@ -1496,12 +1496,7 @@ kimik3-fp4-h200-vllm-agentic: ep: 1 dp-attn: false additional-settings: - - "MULTINODE_GPU_COUNT=16" - - "MULTINODE_SERVER_SCRIPT=benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh" - - "MULTINODE_CLIENT_SCRIPT=benchmarks/multi_node/agentic_srt.sh" - - "MULTINODE_STARTUP_TIMEOUT_SECONDS=7200" - - "INFMAX_CONTAINER_WORKSPACE=/workspace" - - "RESULT_DIR=/workspace/LOGS/agentic" + - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" @@ -1522,12 +1517,7 @@ kimik3-fp4-h200-vllm-agentic: ep: 16 dp-attn: false additional-settings: - - "MULTINODE_GPU_COUNT=16" - - "MULTINODE_SERVER_SCRIPT=benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh" - - "MULTINODE_CLIENT_SCRIPT=benchmarks/multi_node/agentic_srt.sh" - - "MULTINODE_STARTUP_TIMEOUT_SECONDS=7200" - - "INFMAX_CONTAINER_WORKSPACE=/workspace" - - "RESULT_DIR=/workspace/LOGS/agentic" + - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" @@ -1548,12 +1538,7 @@ kimik3-fp4-h200-vllm-agentic: ep: 16 dp-attn: true additional-settings: - - "MULTINODE_GPU_COUNT=16" - - "MULTINODE_SERVER_SCRIPT=benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh" - - "MULTINODE_CLIENT_SCRIPT=benchmarks/multi_node/agentic_srt.sh" - - "MULTINODE_STARTUP_TIMEOUT_SECONDS=7200" - - "INFMAX_CONTAINER_WORKSPACE=/workspace" - - "RESULT_DIR=/workspace/LOGS/agentic" + - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 7236bd1acd..dfd232195f 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5197,6 +5197,6 @@ description: - "Add Kimi K3 Day-0 AgentX support on two 8xH200 nodes with the official vllm/vllm-openai:kimi-k3 image and pre-staged 1.5 TB moonshotai/Kimi-K3 checkpoint" - "Reference the official H200 recipe at https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200: latency-oriented multi-node TP16, balanced TEP16, and throughput-oriented DEP16" - - "Launch aggregated vLLM through a reusable Slurm/Pyxis multi-node connector that separates cluster allocation, mounts, networking, readiness, and cleanup from the hardware-agnostic Kimi K3 benchmark entrypoint; P/D disaggregation is intentionally deferred" + - "Launch aggregated vLLM directly from the H200 runner with Slurm/Pyxis while passing only node rank, node count, local GPU count, and rendezvous address into the hardware-agnostic Kimi K3 benchmark entrypoint; P/D disaggregation is intentionally deferred" - "Sweep AgentX concurrency 1-8 for latency, 4-32 for balanced, and 16-128 for throughput with prefix caching, the kimi_k3 tool/reasoning parsers, and the full 1M-token model context" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 diff --git a/runners/connectors/slurm_pyxis.sh b/runners/connectors/slurm_pyxis.sh deleted file mode 100755 index 6b716eab22..0000000000 --- a/runners/connectors/slurm_pyxis.sh +++ /dev/null @@ -1,301 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Reusable connector for a long-running multi-node service and an overlapping -# benchmark client on Slurm clusters using Pyxis/Enroot. -# -# Deployment inputs: -# MULTINODE_GPU_COUNT -# MULTINODE_SERVER_SCRIPT -# MULTINODE_CLIENT_SCRIPT -# -# Runner profile inputs: -# SLURM_PARTITION -# SLURM_ACCOUNT (optional) -# SLURM_PYXIS_GPUS_PER_NODE -# SLURM_PYXIS_IMAGE_CACHE_DIR -# SLURM_PYXIS_CONTAINER_MOUNTS -# SLURM_PYXIS_CONTAINER_WORKDIR -# MODEL_HOST_PATH -# MODEL_PATH -# -# The server receives a scheduler-independent contract: -# MULTINODE_NODE_COUNT -# MULTINODE_GPUS_PER_NODE -# MULTINODE_NODE_RANK -# MULTINODE_MASTER_ADDR - -_slurm_pyxis_require_vars() { - local variable_name - - for variable_name in "$@"; do - if [[ -z "${!variable_name:-}" ]]; then - echo "Missing required Slurm/Pyxis connector variable: $variable_name" >&2 - return 1 - fi - done -} - -_slurm_pyxis_is_positive_integer() { - [[ "$1" =~ ^[1-9][0-9]*$ ]] -} - -_slurm_pyxis_package_logs() { - if [[ "${_SLURM_PYXIS_LOGS_PACKAGED:-0}" == "1" ]]; then - return - fi - _SLURM_PYXIS_LOGS_PACKAGED=1 - - if [[ -n "${_SLURM_PYXIS_SERVER_LOG_DIR:-}" && \ - -d "$_SLURM_PYXIS_SERVER_LOG_DIR" ]]; then - tar czf "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" \ - -C "$_SLURM_PYXIS_SERVER_LOG_DIR" . || true - fi -} - -_slurm_pyxis_cleanup() { - if [[ -n "${_SLURM_PYXIS_SERVER_STEP_PID:-}" ]]; then - kill "$_SLURM_PYXIS_SERVER_STEP_PID" 2>/dev/null || true - wait "$_SLURM_PYXIS_SERVER_STEP_PID" 2>/dev/null || true - _SLURM_PYXIS_SERVER_STEP_PID="" - fi - - _slurm_pyxis_package_logs - - if [[ -n "${_SLURM_PYXIS_JOB_ID:-}" ]]; then - scancel "$_SLURM_PYXIS_JOB_ID" 2>/dev/null || true - _SLURM_PYXIS_JOB_ID="" - fi -} - -_slurm_pyxis_exit_trap() { - local exit_code="$1" - - trap - EXIT INT TERM - _slurm_pyxis_cleanup - exit "$exit_code" -} - -run_slurm_pyxis_multinode_service() { - local node_count - local squash_file - local lock_file - local docker_image - local allocated_nodelist - local head_node - local startup_timeout - local poll_interval - local max_attempts - local attempt - local ready=0 - local client_rc - local slurm_gres - local -a allocation_args - - _slurm_pyxis_require_vars \ - IMAGE \ - RUNNER_NAME \ - GITHUB_WORKSPACE \ - PORT \ - MULTINODE_GPU_COUNT \ - MULTINODE_SERVER_SCRIPT \ - MULTINODE_CLIENT_SCRIPT \ - SLURM_PARTITION \ - SLURM_PYXIS_GPUS_PER_NODE \ - SLURM_PYXIS_IMAGE_CACHE_DIR \ - SLURM_PYXIS_CONTAINER_MOUNTS \ - SLURM_PYXIS_CONTAINER_WORKDIR \ - MODEL_HOST_PATH \ - MODEL_PATH || return 1 - - if ! _slurm_pyxis_is_positive_integer "$MULTINODE_GPU_COUNT"; then - echo "MULTINODE_GPU_COUNT must be a positive integer" >&2 - return 1 - fi - if ! _slurm_pyxis_is_positive_integer "$SLURM_PYXIS_GPUS_PER_NODE"; then - echo "SLURM_PYXIS_GPUS_PER_NODE must be a positive integer" >&2 - return 1 - fi - if (( MULTINODE_GPU_COUNT % SLURM_PYXIS_GPUS_PER_NODE != 0 )); then - echo "MULTINODE_GPU_COUNT ($MULTINODE_GPU_COUNT) must be divisible by the runner's GPUs per node ($SLURM_PYXIS_GPUS_PER_NODE)" >&2 - return 1 - fi - - node_count=$((MULTINODE_GPU_COUNT / SLURM_PYXIS_GPUS_PER_NODE)) - startup_timeout="${MULTINODE_STARTUP_TIMEOUT_SECONDS:-3600}" - poll_interval="${MULTINODE_HEALTH_POLL_SECONDS:-10}" - if ! _slurm_pyxis_is_positive_integer "$startup_timeout" || \ - ! _slurm_pyxis_is_positive_integer "$poll_interval"; then - echo "Multi-node startup timeout and poll interval must be positive integers" >&2 - return 1 - fi - - if [[ "$MULTINODE_SERVER_SCRIPT" == /* || \ - ! -f "$GITHUB_WORKSPACE/$MULTINODE_SERVER_SCRIPT" ]]; then - echo "MULTINODE_SERVER_SCRIPT must be a repository-relative file: $MULTINODE_SERVER_SCRIPT" >&2 - return 1 - fi - if [[ "$MULTINODE_CLIENT_SCRIPT" == /* || \ - ! -f "$GITHUB_WORKSPACE/$MULTINODE_CLIENT_SCRIPT" ]]; then - echo "MULTINODE_CLIENT_SCRIPT must be a repository-relative file: $MULTINODE_CLIENT_SCRIPT" >&2 - return 1 - fi - - echo "Slurm/Pyxis deployment: ${MULTINODE_GPU_COUNT} GPUs as ${node_count} nodes x ${SLURM_PYXIS_GPUS_PER_NODE} GPUs" - if [[ "${MULTINODE_CONNECTOR_DRY_RUN:-0}" == "1" ]]; then - echo "Server entrypoint: $MULTINODE_SERVER_SCRIPT" - echo "Client entrypoint: $MULTINODE_CLIENT_SCRIPT" - return - fi - - if [[ ! -d "$MODEL_HOST_PATH" ]]; then - echo "Pre-staged model path not found: $MODEL_HOST_PATH" >&2 - return 1 - fi - - _SLURM_PYXIS_SERVER_LOG_DIR="${MULTINODE_SERVER_LOG_DIR:-$GITHUB_WORKSPACE/multinode_server_logs}" - _SLURM_PYXIS_LOGS_PACKAGED=0 - _SLURM_PYXIS_JOB_ID="" - _SLURM_PYXIS_SERVER_STEP_PID="" - - mkdir -p "$SLURM_PYXIS_IMAGE_CACHE_DIR" "$_SLURM_PYXIS_SERVER_LOG_DIR" - squash_file="$SLURM_PYXIS_IMAGE_CACHE_DIR/$(echo "$IMAGE" | sed 's/[\/:@#]/_/g').sqsh" - lock_file="${squash_file}.lock" - docker_image="${IMAGE//#//}" - slurm_gres="${SLURM_PYXIS_GRES:-gpu:$SLURM_PYXIS_GPUS_PER_NODE}" - - allocation_args=( - "--partition=$SLURM_PARTITION" - "--nodes=$node_count" - "--ntasks-per-node=1" - "--gres=$slurm_gres" - --exclusive - "--time=${MULTINODE_TIME_LIMIT_MINUTES:-240}" - --no-shell - "--job-name=$RUNNER_NAME" - ) - if [[ -n "${SLURM_ACCOUNT:-}" ]]; then - allocation_args+=("--account=$SLURM_ACCOUNT") - fi - - salloc "${allocation_args[@]}" - _SLURM_PYXIS_JOB_ID=$(squeue --name="$RUNNER_NAME" -u "$USER" -h -o %A | sed -n '1p') - if [[ -z "$_SLURM_PYXIS_JOB_ID" ]]; then - echo "Failed to resolve the Slurm/Pyxis allocation" >&2 - scancel --name="$RUNNER_NAME" 2>/dev/null || true - return 1 - fi - - trap '_slurm_pyxis_exit_trap $?' EXIT - trap 'exit 130' INT - trap 'exit 143' TERM - - allocated_nodelist=$(squeue -j "$_SLURM_PYXIS_JOB_ID" -h -o %N) - head_node=$(scontrol show hostnames "$allocated_nodelist" | sed -n '1p') - if [[ -z "$head_node" ]]; then - echo "Failed to resolve the rank-zero node" >&2 - return 1 - fi - - # Import once into the runner profile's shared cache. The image lock keeps - # concurrent jobs from replacing the same squash file. - # shellcheck disable=SC2016 # The worker-side shell expands positional args. - srun \ - --jobid="$_SLURM_PYXIS_JOB_ID" \ - --nodes=1 \ - --ntasks=1 \ - --nodelist="$head_node" \ - bash -c ' - set -e - image_cache_dir=$1 - squash_file=$2 - lock_file=$3 - docker_image=$4 - mkdir -p "$image_cache_dir" "$HOME/.cache/enroot" - export ENROOT_CACHE_PATH="$HOME/.cache/enroot" - exec 9>"$lock_file" - flock -w "${SLURM_PYXIS_IMPORT_LOCK_TIMEOUT_SECONDS:-1800}" 9 - if unsquashfs -l "$squash_file" >/dev/null 2>&1; then - echo "Using cached image: $squash_file" - else - rm -f "$squash_file" - enroot import -o "$squash_file" "docker://$docker_image" - unsquashfs -l "$squash_file" >/dev/null - chmod a+r "$squash_file" || true - fi - ' bash "$SLURM_PYXIS_IMAGE_CACHE_DIR" "$squash_file" "$lock_file" "$docker_image" - - export MULTINODE_NODE_COUNT="$node_count" - export MULTINODE_GPUS_PER_NODE="$SLURM_PYXIS_GPUS_PER_NODE" - export MULTINODE_MASTER_ADDR="$head_node" - - # The connector translates SLURM_PROCID into the scheduler-independent - # node-rank contract before invoking the in-container server entrypoint. - # shellcheck disable=SC2016 # SLURM_PROCID is created inside each srun task. - srun \ - --jobid="$_SLURM_PYXIS_JOB_ID" \ - --nodes="$node_count" \ - --ntasks="$node_count" \ - --ntasks-per-node=1 \ - --kill-on-bad-exit=1 \ - --container-image="$squash_file" \ - --container-mounts="$SLURM_PYXIS_CONTAINER_MOUNTS" \ - --no-container-mount-home \ - --container-remap-root \ - --container-workdir="$SLURM_PYXIS_CONTAINER_WORKDIR" \ - --no-container-entrypoint \ - --export=ALL \ - bash -c 'export MULTINODE_NODE_RANK="$SLURM_PROCID"; exec bash "$MULTINODE_SERVER_SCRIPT"' \ - >"$_SLURM_PYXIS_SERVER_LOG_DIR/combined.log" 2>&1 & - _SLURM_PYXIS_SERVER_STEP_PID=$! - - max_attempts=$(((startup_timeout + poll_interval - 1) / poll_interval)) - for ((attempt = 1; attempt <= max_attempts; attempt++)); do - if curl --output /dev/null --silent --fail \ - "http://$head_node:$PORT${MULTINODE_HEALTH_PATH:-/health}"; then - ready=1 - break - fi - if ! kill -0 "$_SLURM_PYXIS_SERVER_STEP_PID" 2>/dev/null; then - echo "Multi-node server step exited before becoming ready" >&2 - tail -n 200 "$_SLURM_PYXIS_SERVER_LOG_DIR/combined.log" >&2 || true - return 1 - fi - if (( attempt * poll_interval % 60 == 0 )); then - echo "Waiting for multi-node server readiness ($((attempt * poll_interval))s elapsed)" - tail -n 20 "$_SLURM_PYXIS_SERVER_LOG_DIR/combined.log" || true - fi - sleep "$poll_interval" - done - if [[ "$ready" != "1" ]]; then - echo "Multi-node server did not become healthy within $startup_timeout seconds" >&2 - tail -n 200 "$_SLURM_PYXIS_SERVER_LOG_DIR/combined.log" >&2 || true - return 1 - fi - - set +e - srun \ - --jobid="$_SLURM_PYXIS_JOB_ID" \ - --overlap \ - --nodes=1 \ - --ntasks=1 \ - --nodelist="$head_node" \ - --container-image="$squash_file" \ - --container-mounts="$SLURM_PYXIS_CONTAINER_MOUNTS" \ - --no-container-mount-home \ - --container-remap-root \ - --container-workdir="$SLURM_PYXIS_CONTAINER_WORKDIR" \ - --no-container-entrypoint \ - --export=ALL,MULTINODE_NODE_RANK=0 \ - bash "$MULTINODE_CLIENT_SCRIPT" - client_rc=$? - set -e - - _slurm_pyxis_cleanup - trap - EXIT INT TERM - return "$client_rc" -} - -if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then - run_slurm_pyxis_multinode_service -fi diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 8c20da5752..32e743ee29 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -7,13 +7,17 @@ SLURM_ACCOUNT="sa-shared" set -x -# Native multi-node benchmarks opt into the reusable service connector by -# providing in-container server and client entrypoints. This runner only maps -# H200 DGXC storage, networking, and Slurm/Pyxis resources. -if [[ "$IS_MULTINODE" == "true" && -n "${MULTINODE_SERVER_SCRIPT:-}" ]]; then +# Native multi-node vLLM: keep Slurm/Pyxis on the host and pass only rank and +# rendezvous information to the hardware-independent benchmark entrypoint. +if [[ "$IS_MULTINODE" == "true" && "${NATIVE_MULTINODE:-0}" == "1" ]]; then + if [[ "${IS_AGENTIC:-0}" != "1" || "$FRAMEWORK" != "vllm" ]]; then + echo "Native multi-node H200 currently supports AgentX vLLM jobs" >&2 + exit 1 + fi + case "$MODEL_PREFIX/$PRECISION" in kimik3/fp4) - export MODEL_HOST_PATH="/models/gharunners/hf-hub-cache/Kimi-K3" + model_host_path="/models/gharunners/hf-hub-cache/Kimi-K3" export MODEL_PATH="/models/hf-hub-cache/Kimi-K3" ;; *) @@ -25,20 +29,140 @@ if [[ "$IS_MULTINODE" == "true" && -n "${MULTINODE_SERVER_SCRIPT:-}" ]]; then hf_cache_host_path="/models/gharunners/hf-hub-cache" hf_cache_container_path="/models/hf-hub-cache" aiperf_cache_host_path="/home/sa-shared/gharunners/ai-perf-cache" - mkdir -p "$aiperf_cache_host_path" + image_cache_dir="/data/gharunners/containers" + server_log_dir="$GITHUB_WORKSPACE/multinode_server_logs" + gpus_per_node=8 + gpu_count=$((PREFILL_NUM_WORKERS * PREFILL_TP)) + if (( gpu_count % gpus_per_node != 0 )); then + echo "Native multi-node GPU count ($gpu_count) must use full 8xH200 nodes" >&2 + exit 1 + fi + node_count=$((gpu_count / gpus_per_node)) + server_script="benchmarks/multi_node/${SCENARIO_SUBDIR}${MODEL_PREFIX}_${PRECISION}_${FRAMEWORK}.sh" + client_script="benchmarks/multi_node/agentic_srt.sh" + squash_file="$image_cache_dir/$(echo "$IMAGE" | sed 's/[\/:@#]/_/g').sqsh" + lock_file="${squash_file}.lock" + container_mounts="$GITHUB_WORKSPACE:/workspace,$hf_cache_host_path:$hf_cache_container_path,$aiperf_cache_host_path:/aiperf_mmap_cache" + + if [[ ! -d "$model_host_path" || ! -f "$server_script" ]]; then + echo "Missing model or benchmark entrypoint: $model_host_path / $server_script" >&2 + exit 1 + fi + mkdir -p "$aiperf_cache_host_path" "$image_cache_dir" "$server_log_dir" export PORT="${PORT:-8888}" export HF_HUB_CACHE="$hf_cache_container_path" export AIPERF_DATASET_MMAP_CACHE_DIR="/aiperf_mmap_cache" + export INFMAX_CONTAINER_WORKSPACE="/workspace" + export RESULT_DIR="/workspace/LOGS/agentic" export GLOO_SOCKET_IFNAME="${GLOO_SOCKET_IFNAME:-eth0}" export NCCL_SOCKET_IFNAME="${NCCL_SOCKET_IFNAME:-eth0}" - export SLURM_PYXIS_GPUS_PER_NODE=8 - export SLURM_PYXIS_IMAGE_CACHE_DIR="/data/gharunners/containers" - export SLURM_PYXIS_CONTAINER_WORKDIR="/workspace" - export SLURM_PYXIS_CONTAINER_MOUNTS="$GITHUB_WORKSPACE:/workspace,$hf_cache_host_path:$hf_cache_container_path,$aiperf_cache_host_path:/aiperf_mmap_cache" - bash "$GITHUB_WORKSPACE/runners/connectors/slurm_pyxis.sh" - exit $? + salloc \ + --partition="$SLURM_PARTITION" \ + --account="$SLURM_ACCOUNT" \ + --nodes="$node_count" \ + --ntasks-per-node=1 \ + --gres="gpu:$gpus_per_node" \ + --exclusive \ + --time=240 \ + --no-shell \ + --job-name="$RUNNER_NAME" + job_id=$(squeue --name="$RUNNER_NAME" -u "$USER" -h -o %A | sed -n '1p') + if [[ -z "$job_id" ]]; then + echo "Failed to resolve native multi-node Slurm allocation" >&2 + exit 1 + fi + + cleanup_native_multinode() { + local exit_code=$? + trap - EXIT INT TERM + kill "${server_step_pid:-}" 2>/dev/null || true + wait "${server_step_pid:-}" 2>/dev/null || true + tar czf "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" \ + -C "$server_log_dir" . 2>/dev/null || true + scancel "$job_id" 2>/dev/null || true + exit "$exit_code" + } + trap cleanup_native_multinode EXIT + trap 'exit 130' INT + trap 'exit 143' TERM + + allocated_nodelist=$(squeue -j "$job_id" -h -o %N) + head_node=$(scontrol show hostnames "$allocated_nodelist" | sed -n '1p') + if [[ -z "$head_node" ]]; then + echo "Failed to resolve native multi-node head node" >&2 + exit 1 + fi + + srun --jobid="$job_id" --nodes=1 --ntasks=1 --nodelist="$head_node" bash -c " + export ENROOT_CACHE_PATH=\$HOME/.cache/enroot + mkdir -p \$ENROOT_CACHE_PATH + exec 9>'$lock_file' + flock -w 1800 9 + if ! unsquashfs -l '$squash_file' >/dev/null 2>&1; then + rm -f '$squash_file' + enroot import -o '$squash_file' 'docker://${IMAGE//#//}' + fi + " + + export MULTINODE_NODE_COUNT="$node_count" + export MULTINODE_GPUS_PER_NODE="$gpus_per_node" + export MULTINODE_MASTER_ADDR="$head_node" + + # shellcheck disable=SC2016 # SLURM_PROCID is created inside each srun task. + srun \ + --jobid="$job_id" \ + --nodes="$node_count" \ + --ntasks="$node_count" \ + --ntasks-per-node=1 \ + --kill-on-bad-exit=1 \ + --container-image="$squash_file" \ + --container-mounts="$container_mounts" \ + --no-container-mount-home \ + --container-remap-root \ + --container-workdir=/workspace \ + --no-container-entrypoint \ + --export=ALL \ + bash -c 'export MULTINODE_NODE_RANK="$SLURM_PROCID"; exec bash "$1"' \ + bash "$server_script" \ + >"$server_log_dir/combined.log" 2>&1 & + server_step_pid=$! + + for ((attempt = 1; attempt <= 720; attempt++)); do + if curl --output /dev/null --silent --fail "http://$head_node:$PORT/health"; then + break + fi + if ! kill -0 "$server_step_pid" 2>/dev/null; then + echo "Native multi-node server exited before becoming ready" >&2 + tail -n 200 "$server_log_dir/combined.log" >&2 || true + exit 1 + fi + sleep 10 + done + if (( attempt > 720 )); then + echo "Native multi-node server did not become ready within 7200 seconds" >&2 + exit 1 + fi + + set +e + srun \ + --jobid="$job_id" \ + --overlap \ + --nodes=1 \ + --ntasks=1 \ + --nodelist="$head_node" \ + --container-image="$squash_file" \ + --container-mounts="$container_mounts" \ + --no-container-mount-home \ + --container-remap-root \ + --container-workdir=/workspace \ + --no-container-entrypoint \ + --export=ALL,MULTINODE_NODE_RANK=0 \ + bash "$client_script" + client_rc=$? + set -e + exit "$client_rc" fi if [[ "$IS_MULTINODE" == "true" ]]; then From f4279ac43bd28f5ffe6e1d2f9cca96cd3d0aa1fc Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 18:46:20 -0500 Subject: [PATCH 05/62] fix(kimik3): use default model context length Remove the explicit max-model-len override and let vLLM derive the model default. --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 1 - perf-changelog.yaml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index ad4c0cdc84..6d7fed6604 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -52,7 +52,6 @@ VLLM_CMD=( --tool-call-parser kimi_k3 --reasoning-parser kimi_k3 --language-model-only - --max-model-len 1048576 --max-num-seqs "$MAX_CONCURRENCY" ) diff --git a/perf-changelog.yaml b/perf-changelog.yaml index dfd232195f..83069497c8 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5198,5 +5198,5 @@ - "Add Kimi K3 Day-0 AgentX support on two 8xH200 nodes with the official vllm/vllm-openai:kimi-k3 image and pre-staged 1.5 TB moonshotai/Kimi-K3 checkpoint" - "Reference the official H200 recipe at https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200: latency-oriented multi-node TP16, balanced TEP16, and throughput-oriented DEP16" - "Launch aggregated vLLM directly from the H200 runner with Slurm/Pyxis while passing only node rank, node count, local GPU count, and rendezvous address into the hardware-agnostic Kimi K3 benchmark entrypoint; P/D disaggregation is intentionally deferred" - - "Sweep AgentX concurrency 1-8 for latency, 4-32 for balanced, and 16-128 for throughput with prefix caching, the kimi_k3 tool/reasoning parsers, and the full 1M-token model context" + - "Sweep AgentX concurrency 1-8 for latency, 4-32 for balanced, and 16-128 for throughput with prefix caching and the kimi_k3 tool/reasoning parsers" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 From 902951a2acb5fd5ffad41067d2331711f00a8ea1 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 18:46:50 -0500 Subject: [PATCH 06/62] docs(kimik3): trim benchmark changelog Keep the changelog focused on performance topology and concurrency, and remove the unnecessary AgentX client comment change. --- benchmarks/multi_node/agentic_srt.sh | 6 +++--- perf-changelog.yaml | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/benchmarks/multi_node/agentic_srt.sh b/benchmarks/multi_node/agentic_srt.sh index 642659c3e4..79a36da524 100644 --- a/benchmarks/multi_node/agentic_srt.sh +++ b/benchmarks/multi_node/agentic_srt.sh @@ -2,9 +2,9 @@ set -euo pipefail set -x -# Client-only agentic trace replay for externally managed multi-node jobs. -# A deployment layer such as srt-slurm or a runner connector owns server -# startup; this script runs against the already-ready frontend on the head node. +# Client-only agentic trace replay for srt-slurm multinode jobs. +# srt-slurm owns server startup; this script runs as benchmark.type=custom +# against the already-ready frontend on the head node. INFMAX_CONTAINER_WORKSPACE="${INFMAX_CONTAINER_WORKSPACE:-/infmax-workspace}" source "$INFMAX_CONTAINER_WORKSPACE/benchmarks/benchmark_lib.sh" diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 83069497c8..83f3cae730 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5195,8 +5195,5 @@ - config-keys: - kimik3-fp4-h200-vllm-agentic description: - - "Add Kimi K3 Day-0 AgentX support on two 8xH200 nodes with the official vllm/vllm-openai:kimi-k3 image and pre-staged 1.5 TB moonshotai/Kimi-K3 checkpoint" - - "Reference the official H200 recipe at https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200: latency-oriented multi-node TP16, balanced TEP16, and throughput-oriented DEP16" - - "Launch aggregated vLLM directly from the H200 runner with Slurm/Pyxis while passing only node rank, node count, local GPU count, and rendezvous address into the hardware-agnostic Kimi K3 benchmark entrypoint; P/D disaggregation is intentionally deferred" - - "Sweep AgentX concurrency 1-8 for latency, 4-32 for balanced, and 16-128 for throughput with prefix caching and the kimi_k3 tool/reasoning parsers" + - "Add Kimi K3 FP4 AgentX benchmarks on 2x8 H200: TP16 at concurrency 1-8, TEP16 at 4-32, and DEP16 at 16-128" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 From 4be37db5f855fde55690592f4583ff8000cbd178 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 18:48:19 -0500 Subject: [PATCH 07/62] refactor(kimik3): trust benchmark environment Remove fallback parameter expansion and redundant environment validation from the native multi-node path. Keep the changelog concise while identifying Day-0 performance coverage from the official vLLM H200 recipe. --- .../multi_node/agentic/kimik3_fp4_vllm.sh | 30 ++++--------------- perf-changelog.yaml | 2 +- runners/launch_h200-dgxc-slurm.sh | 14 ++++----- 3 files changed, 13 insertions(+), 33 deletions(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 6d7fed6604..ad16a3683f 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -10,22 +10,6 @@ set -x # The runner supplies node ranks, rendezvous, and local GPU count. # This script only translates the requested TP/EP/DP topology into vLLM flags. -# shellcheck disable=SC1091 # Resolved relative to this entrypoint at runtime. -source "$(dirname "$0")/../../benchmark_lib.sh" - -check_env_vars \ - MODEL \ - MODEL_PATH \ - PORT \ - CONC_LIST \ - PREFILL_TP \ - PREFILL_EP \ - PREFILL_DP_ATTN \ - MULTINODE_NODE_COUNT \ - MULTINODE_GPUS_PER_NODE \ - MULTINODE_NODE_RANK \ - MULTINODE_MASTER_ADDR - WORLD_SIZE=$((MULTINODE_NODE_COUNT * MULTINODE_GPUS_PER_NODE)) read -r -a CONCURRENCIES <<< "$CONC_LIST" MAX_CONCURRENCY=0 @@ -35,7 +19,7 @@ for concurrency in "${CONCURRENCIES[@]}"; do fi done -export VLLM_ENGINE_READY_TIMEOUT_S="${VLLM_ENGINE_READY_TIMEOUT_S:-7200}" +export VLLM_ENGINE_READY_TIMEOUT_S=7200 export PYTHONNOUSERSITE=1 VLLM_CMD=( @@ -45,7 +29,7 @@ VLLM_CMD=( --port "$PORT" --trust-remote-code --load-format fastsafetensors - --moe-backend "${VLLM_MOE_BACKEND:-auto}" + --moe-backend "$VLLM_MOE_BACKEND" --gpu-memory-utilization 0.95 --enable-prefix-caching --enable-auto-tool-choice @@ -55,10 +39,10 @@ VLLM_CMD=( --max-num-seqs "$MAX_CONCURRENCY" ) -if [[ "${VLLM_DISABLE_FLASHINFER_AUTOTUNE:-0}" == "1" ]]; then +if [[ "$VLLM_DISABLE_FLASHINFER_AUTOTUNE" == "1" ]]; then VLLM_CMD+=(--no-enable-flashinfer-autotune) fi -if [[ "${VLLM_DISABLE_CUSTOM_ALL_REDUCE:-0}" == "1" ]]; then +if [[ "$VLLM_DISABLE_CUSTOM_ALL_REDUCE" == "1" ]]; then VLLM_CMD+=(--disable-custom-all-reduce) fi @@ -88,7 +72,7 @@ elif [[ "$PREFILL_DP_ATTN" == "false" ]]; then if [ "$PREFILL_EP" -gt 1 ]; then VLLM_CMD+=(--enable-expert-parallel) fi - if [[ "${VLLM_DISABLE_FUSED_ALLREDUCE_RMS:-0}" == "1" ]]; then + if [[ "$VLLM_DISABLE_FUSED_ALLREDUCE_RMS" == "1" ]]; then VLLM_CMD+=(-cc.pass_config.fuse_allreduce_rms=False) fi if [ "$MULTINODE_NODE_RANK" -gt 0 ]; then @@ -103,8 +87,4 @@ printf 'Kimi K3 rank %s command: ' "$MULTINODE_NODE_RANK" printf '%q ' "${VLLM_CMD[@]}" printf '\n' -if [[ "${KIMIK3_DRY_RUN:-0}" == "1" ]]; then - exit 0 -fi - exec "${VLLM_CMD[@]}" diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 83f3cae730..8a35ed209b 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5195,5 +5195,5 @@ - config-keys: - kimik3-fp4-h200-vllm-agentic description: - - "Add Kimi K3 FP4 AgentX benchmarks on 2x8 H200: TP16 at concurrency 1-8, TEP16 at 4-32, and DEP16 at 16-128" + - "Add Day-0 Kimi K3 FP4 AgentX performance coverage on 2x8 H200 using the official vLLM H200 recipe: TP16 at concurrency 1-8, TEP16 at 4-32, and DEP16 at 16-128" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 32e743ee29..2a79900856 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -9,8 +9,8 @@ set -x # Native multi-node vLLM: keep Slurm/Pyxis on the host and pass only rank and # rendezvous information to the hardware-independent benchmark entrypoint. -if [[ "$IS_MULTINODE" == "true" && "${NATIVE_MULTINODE:-0}" == "1" ]]; then - if [[ "${IS_AGENTIC:-0}" != "1" || "$FRAMEWORK" != "vllm" ]]; then +if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then + if [[ "$IS_AGENTIC" != "1" || "$FRAMEWORK" != "vllm" ]]; then echo "Native multi-node H200 currently supports AgentX vLLM jobs" >&2 exit 1 fi @@ -50,13 +50,13 @@ if [[ "$IS_MULTINODE" == "true" && "${NATIVE_MULTINODE:-0}" == "1" ]]; then fi mkdir -p "$aiperf_cache_host_path" "$image_cache_dir" "$server_log_dir" - export PORT="${PORT:-8888}" + export PORT="$PORT" export HF_HUB_CACHE="$hf_cache_container_path" export AIPERF_DATASET_MMAP_CACHE_DIR="/aiperf_mmap_cache" export INFMAX_CONTAINER_WORKSPACE="/workspace" export RESULT_DIR="/workspace/LOGS/agentic" - export GLOO_SOCKET_IFNAME="${GLOO_SOCKET_IFNAME:-eth0}" - export NCCL_SOCKET_IFNAME="${NCCL_SOCKET_IFNAME:-eth0}" + export GLOO_SOCKET_IFNAME=eth0 + export NCCL_SOCKET_IFNAME=eth0 salloc \ --partition="$SLURM_PARTITION" \ @@ -77,8 +77,8 @@ if [[ "$IS_MULTINODE" == "true" && "${NATIVE_MULTINODE:-0}" == "1" ]]; then cleanup_native_multinode() { local exit_code=$? trap - EXIT INT TERM - kill "${server_step_pid:-}" 2>/dev/null || true - wait "${server_step_pid:-}" 2>/dev/null || true + kill "$server_step_pid" 2>/dev/null || true + wait "$server_step_pid" 2>/dev/null || true tar czf "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" \ -C "$server_log_dir" . 2>/dev/null || true scancel "$job_id" 2>/dev/null || true From b12f1ae05d027ece16e2cccc562d11ec0cdf07a3 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 19:15:31 -0500 Subject: [PATCH 08/62] fix(h200): set native vLLM port Use the H200 runner's fixed port for direct multi-node vLLM jobs because the multi-node Actions path does not provide PORT. --- runners/launch_h200-dgxc-slurm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 2a79900856..dec9e63edb 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -50,7 +50,7 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then fi mkdir -p "$aiperf_cache_host_path" "$image_cache_dir" "$server_log_dir" - export PORT="$PORT" + export PORT=8888 export HF_HUB_CACHE="$hf_cache_container_path" export AIPERF_DATASET_MMAP_CACHE_DIR="/aiperf_mmap_cache" export INFMAX_CONTAINER_WORKSPACE="/workspace" From 2d8d435a0c133e33f29446d479bf0b89057bd565 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 19:50:58 -0500 Subject: [PATCH 09/62] fix(kimik3): unblock H200 model loading Use the streaming safetensor loader, remove the SM100-only latent MoE tail fusion toggle, and route DEP traffic and metrics across both node-local endpoints. --- benchmarks/benchmark_lib.sh | 15 +++++++++- .../multi_node/agentic/kimik3_fp4_vllm.sh | 1 - configs/nvidia-master.yaml | 3 -- runners/launch_h200-dgxc-slurm.sh | 28 +++++++++++++++++-- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/benchmarks/benchmark_lib.sh b/benchmarks/benchmark_lib.sh index c5e6fb2c86..3554f3c448 100644 --- a/benchmarks/benchmark_lib.sh +++ b/benchmarks/benchmark_lib.sh @@ -1766,7 +1766,20 @@ build_replay_cmd() { # DATASET_CONFIGURATION_TIMEOUT at startup. Bump it in lockstep. export AIPERF_SERVICE_PROFILE_CONFIGURE_TIMEOUT=1800 REPLAY_CMD="$AIPERF_CLI profile --scenario inferencex-agentx-mvp" - REPLAY_CMD+=" --url http://localhost:$PORT" + if declare -p AIPERF_ENDPOINT_URLS &>/dev/null; then + local endpoint_url + local -a endpoint_urls + IFS=',' read -r -a endpoint_urls <<< "$AIPERF_ENDPOINT_URLS" + for endpoint_url in "${endpoint_urls[@]}"; do + if [ -z "$endpoint_url" ] || [[ "$endpoint_url" == *[[:space:]]* ]]; then + echo "ERROR: AIPERF_ENDPOINT_URLS must be a comma-separated list of non-empty URLs" >&2 + return 1 + fi + REPLAY_CMD+=" --url $endpoint_url" + done + else + REPLAY_CMD+=" --url http://localhost:$PORT" + fi REPLAY_CMD+=" --endpoint /v1/chat/completions" REPLAY_CMD+=" --endpoint-type chat" REPLAY_CMD+=" --streaming" diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index ad16a3683f..1559d4e24a 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -28,7 +28,6 @@ VLLM_CMD=( --host 0.0.0.0 --port "$PORT" --trust-remote-code - --load-format fastsafetensors --moe-backend "$VLLM_MOE_BACKEND" --gpu-memory-utilization 0.95 --enable-prefix-caching diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index a0eb020193..de954dd2a4 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1501,7 +1501,6 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" - - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 16 @@ -1522,7 +1521,6 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" - - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 16 @@ -1543,7 +1541,6 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" - - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 8 diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index dec9e63edb..f0f5e98a64 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -89,11 +89,28 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then trap 'exit 143' TERM allocated_nodelist=$(squeue -j "$job_id" -h -o %N) - head_node=$(scontrol show hostnames "$allocated_nodelist" | sed -n '1p') + allocated_nodes=$(scontrol show hostnames "$allocated_nodelist") + head_node=$(sed -n '1p' <<< "$allocated_nodes") if [[ -z "$head_node" ]]; then echo "Failed to resolve native multi-node head node" >&2 exit 1 fi + server_nodes="$head_node" + if [[ "$PREFILL_DP_ATTN" == "true" ]]; then + server_nodes="$allocated_nodes" + fi + endpoint_urls= + metrics_urls= + for server_node in $server_nodes; do + if [[ -n "$endpoint_urls" ]]; then + endpoint_urls+="," + metrics_urls+="," + fi + endpoint_urls+="http://$server_node:$PORT" + metrics_urls+="http://$server_node:$PORT/metrics" + done + export AIPERF_ENDPOINT_URLS="$endpoint_urls" + export AIPERF_SERVER_METRICS_URLS="$metrics_urls" srun --jobid="$job_id" --nodes=1 --ntasks=1 --nodelist="$head_node" bash -c " export ENROOT_CACHE_PATH=\$HOME/.cache/enroot @@ -130,7 +147,14 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then server_step_pid=$! for ((attempt = 1; attempt <= 720; attempt++)); do - if curl --output /dev/null --silent --fail "http://$head_node:$PORT/health"; then + servers_ready=true + for server_node in $server_nodes; do + if ! curl --output /dev/null --silent --fail "http://$server_node:$PORT/health"; then + servers_ready=false + break + fi + done + if [[ "$servers_ready" == "true" ]]; then break fi if ! kill -0 "$server_step_pid" 2>/dev/null; then From ec0c20ddfefde792208f0a30a2ceed7d27ee7dbd Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 20:09:37 -0500 Subject: [PATCH 10/62] fix(kimik3): align rendezvous host with Slurm rank zero --- runners/launch_h200-dgxc-slurm.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index f0f5e98a64..f3f36ff07e 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -90,7 +90,15 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then allocated_nodelist=$(squeue -j "$job_id" -h -o %N) allocated_nodes=$(scontrol show hostnames "$allocated_nodelist") - head_node=$(sed -n '1p' <<< "$allocated_nodes") + # Slurm task rank order is not guaranteed to match scontrol's hostname order. + head_node=$( + srun \ + --jobid="$job_id" \ + --nodes="$node_count" \ + --ntasks="$node_count" \ + --ntasks-per-node=1 \ + bash -c 'if [[ "$SLURM_PROCID" == "0" ]]; then hostname; fi' + ) if [[ -z "$head_node" ]]; then echo "Failed to resolve native multi-node head node" >&2 exit 1 From bbbbc3d1aa296c8a680c29ec345f589e64399a0c Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 20:49:31 -0500 Subject: [PATCH 11/62] fix(kimik3): provision full-context H200 topology --- .../multi_node/agentic/kimik3_fp4_vllm.sh | 7 ++++- configs/nvidia-master.yaml | 26 +++++++++---------- perf-changelog.yaml | 2 +- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 1559d4e24a..6083386931 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -18,6 +18,10 @@ for concurrency in "${CONCURRENCIES[@]}"; do MAX_CONCURRENCY="$concurrency" fi done +MAX_NUM_SEQS="$MAX_CONCURRENCY" +if [[ "$PREFILL_DP_ATTN" == "true" ]]; then + MAX_NUM_SEQS=$(((MAX_CONCURRENCY + WORLD_SIZE - 1) / WORLD_SIZE)) +fi export VLLM_ENGINE_READY_TIMEOUT_S=7200 export PYTHONNOUSERSITE=1 @@ -28,6 +32,7 @@ VLLM_CMD=( --host 0.0.0.0 --port "$PORT" --trust-remote-code + --load-format fastsafetensors --moe-backend "$VLLM_MOE_BACKEND" --gpu-memory-utilization 0.95 --enable-prefix-caching @@ -35,7 +40,7 @@ VLLM_CMD=( --tool-call-parser kimi_k3 --reasoning-parser kimi_k3 --language-model-only - --max-num-seqs "$MAX_CONCURRENCY" + --max-num-seqs "$MAX_NUM_SEQS" ) if [[ "$VLLM_DISABLE_FLASHINFER_AUTOTUNE" == "1" ]]; then diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index de954dd2a4..8a7d100a1d 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1467,7 +1467,7 @@ kimik2.5-int4-h200-vllm-agentic: - { tp: 8, kv-offloading: none, conc-list: [1, 2, 3, 4, 5, 6, 7] } - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: vllm-simple }, conc-list: [6, 7, 8, 9, 10, 11, 12, 13, 14] } -# Kimi K3 is a 2.8T MXFP4 MoE whose ~1.5 TB checkpoint needs two 8xH200 +# Kimi K3 is a 2.8T MXFP4 MoE whose full 1M context needs four 8xH200 # nodes. These are the three aggregated strategies from the official H200 # recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): # multi-node TP is latency-oriented, TEP is balanced, and DEP is @@ -1486,13 +1486,13 @@ kimik3-fp4-h200-vllm-agentic: scenarios: agentic-coding: - search-space: - # Latency-oriented: one TP16 engine spanning two H200 nodes. + # Latency-oriented: one TP32 engine spanning four H200 nodes. - spec-decoding: none kv-offloading: none conc-list: [1, 2, 4, 8] prefill: num-worker: 1 - tp: 16 + tp: 32 ep: 1 dp-attn: false additional-settings: @@ -1503,17 +1503,17 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 16 + tp: 32 ep: 1 dp-attn: false - # Balanced: the same cross-node TP16 engine with expert parallelism. + # Balanced: the same cross-node TP32 engine with expert parallelism. - spec-decoding: none kv-offloading: none conc-list: [4, 8, 16, 32] prefill: num-worker: 1 - tp: 16 - ep: 16 + tp: 32 + ep: 32 dp-attn: false additional-settings: - "NATIVE_MULTINODE=1" @@ -1523,17 +1523,17 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 16 - ep: 16 + tp: 32 + ep: 32 dp-attn: false - # Throughput-oriented: DEP16 across two nodes (eight local DP ranks each). + # Throughput-oriented: DEP32 across four nodes (eight local DP ranks each). - spec-decoding: none kv-offloading: none conc-list: [16, 32, 64, 128] prefill: - num-worker: 2 + num-worker: 4 tp: 8 - ep: 16 + ep: 32 dp-attn: true additional-settings: - "NATIVE_MULTINODE=1" @@ -1544,7 +1544,7 @@ kimik3-fp4-h200-vllm-agentic: decode: num-worker: 0 tp: 8 - ep: 16 + ep: 32 dp-attn: true # NOTE: At the time of submission, https://docs.vllm.ai/projects/recipes/en/latest/moonshotai/Kimi-K2.5.html diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 8a35ed209b..cfe90c803b 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5195,5 +5195,5 @@ - config-keys: - kimik3-fp4-h200-vllm-agentic description: - - "Add Day-0 Kimi K3 FP4 AgentX performance coverage on 2x8 H200 using the official vLLM H200 recipe: TP16 at concurrency 1-8, TEP16 at 4-32, and DEP16 at 16-128" + - "Add Day-0 Kimi K3 FP4 AgentX performance coverage on 4x8 H200 using the official vLLM H200 recipe: TP32 at concurrency 1-8, TEP32 at 4-32, and DEP32 at 16-128" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 From 428e72d9b679a87fa17665a591210fde68c89a88 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 20:54:29 -0500 Subject: [PATCH 12/62] fix(kimik3): stream H200 checkpoint loading --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 6083386931..8574e815cb 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -32,7 +32,6 @@ VLLM_CMD=( --host 0.0.0.0 --port "$PORT" --trust-remote-code - --load-format fastsafetensors --moe-backend "$VLLM_MOE_BACKEND" --gpu-memory-utilization 0.95 --enable-prefix-caching From 2325df78fe39fb0a4316d3c158fee152d4d1d1c2 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 21:41:13 -0500 Subject: [PATCH 13/62] fix(kimik3): fit full context with pipeline parallelism --- .../multi_node/agentic/kimik3_fp4_vllm.sh | 18 ++++++---- configs/nvidia-master.yaml | 34 +++++++++++-------- perf-changelog.yaml | 2 +- runners/launch_h200-dgxc-slurm.sh | 2 +- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 8574e815cb..f4ee91c550 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -20,7 +20,7 @@ for concurrency in "${CONCURRENCIES[@]}"; do done MAX_NUM_SEQS="$MAX_CONCURRENCY" if [[ "$PREFILL_DP_ATTN" == "true" ]]; then - MAX_NUM_SEQS=$(((MAX_CONCURRENCY + WORLD_SIZE - 1) / WORLD_SIZE)) + MAX_NUM_SEQS=$(((MAX_CONCURRENCY + PREFILL_NUM_WORKERS - 1) / PREFILL_NUM_WORKERS)) fi export VLLM_ENGINE_READY_TIMEOUT_S=7200 @@ -32,6 +32,8 @@ VLLM_CMD=( --host 0.0.0.0 --port "$PORT" --trust-remote-code + --load-format fastsafetensors + --attention-backend FLASHMLA --moe-backend "$VLLM_MOE_BACKEND" --gpu-memory-utilization 0.95 --enable-prefix-caching @@ -50,24 +52,28 @@ if [[ "$VLLM_DISABLE_CUSTOM_ALL_REDUCE" == "1" ]]; then fi if [[ "$PREFILL_DP_ATTN" == "true" ]]; then + LOCAL_DATA_PARALLEL_SIZE=$((MULTINODE_GPUS_PER_NODE / (PREFILL_TP * PREFILL_PP_SIZE))) VLLM_CMD+=( - --data-parallel-size "$WORLD_SIZE" - --data-parallel-size-local "$MULTINODE_GPUS_PER_NODE" + --tensor-parallel-size "$PREFILL_TP" + --pipeline-parallel-size "$PREFILL_PP_SIZE" + --data-parallel-size "$PREFILL_NUM_WORKERS" + --data-parallel-size-local "$LOCAL_DATA_PARALLEL_SIZE" --data-parallel-address "$MULTINODE_MASTER_ADDR" - --data-parallel-start-rank "$((MULTINODE_NODE_RANK * MULTINODE_GPUS_PER_NODE))" + --data-parallel-start-rank "$((MULTINODE_NODE_RANK * LOCAL_DATA_PARALLEL_SIZE))" --data-parallel-hybrid-lb ) if [ "$PREFILL_EP" -gt 1 ]; then VLLM_CMD+=(--enable-expert-parallel) fi elif [[ "$PREFILL_DP_ATTN" == "false" ]]; then - if [ "$PREFILL_TP" -ne "$WORLD_SIZE" ]; then - echo "Cross-node TP ($PREFILL_TP) must match the allocated world size ($WORLD_SIZE)" >&2 + if [ "$((PREFILL_TP * PREFILL_PP_SIZE))" -ne "$WORLD_SIZE" ]; then + echo "Cross-node TPxPP must match the allocated world size ($WORLD_SIZE)" >&2 exit 1 fi VLLM_CMD+=( --tensor-parallel-size "$PREFILL_TP" + --pipeline-parallel-size "$PREFILL_PP_SIZE" --nnodes "$MULTINODE_NODE_COUNT" --node-rank "$MULTINODE_NODE_RANK" --master-addr "$MULTINODE_MASTER_ADDR" diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 8a7d100a1d..fb30162772 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1486,13 +1486,14 @@ kimik3-fp4-h200-vllm-agentic: scenarios: agentic-coding: - search-space: - # Latency-oriented: one TP32 engine spanning four H200 nodes. + # Latency-oriented: one TP16/PP2 engine spanning four H200 nodes. - spec-decoding: none kv-offloading: none conc-list: [1, 2, 4, 8] prefill: num-worker: 1 - tp: 32 + tp: 16 + pp: 2 ep: 1 dp-attn: false additional-settings: @@ -1503,17 +1504,19 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 32 + tp: 16 + pp: 2 ep: 1 dp-attn: false - # Balanced: the same cross-node TP32 engine with expert parallelism. + # Balanced: the same TP16/PP2 engine with expert parallelism. - spec-decoding: none kv-offloading: none conc-list: [4, 8, 16, 32] prefill: num-worker: 1 - tp: 32 - ep: 32 + tp: 16 + pp: 2 + ep: 16 dp-attn: false additional-settings: - "NATIVE_MULTINODE=1" @@ -1523,17 +1526,19 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 32 - ep: 32 + tp: 16 + pp: 2 + ep: 16 dp-attn: false - # Throughput-oriented: DEP32 across four nodes (eight local DP ranks each). + # Throughput-oriented: DEP16/PP2 across four nodes. - spec-decoding: none kv-offloading: none conc-list: [16, 32, 64, 128] prefill: - num-worker: 4 - tp: 8 - ep: 32 + num-worker: 16 + tp: 1 + pp: 2 + ep: 16 dp-attn: true additional-settings: - "NATIVE_MULTINODE=1" @@ -1543,8 +1548,9 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 8 - ep: 32 + tp: 1 + pp: 2 + ep: 16 dp-attn: true # NOTE: At the time of submission, https://docs.vllm.ai/projects/recipes/en/latest/moonshotai/Kimi-K2.5.html diff --git a/perf-changelog.yaml b/perf-changelog.yaml index cfe90c803b..0002adb45a 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5195,5 +5195,5 @@ - config-keys: - kimik3-fp4-h200-vllm-agentic description: - - "Add Day-0 Kimi K3 FP4 AgentX performance coverage on 4x8 H200 using the official vLLM H200 recipe: TP32 at concurrency 1-8, TEP32 at 4-32, and DEP32 at 16-128" + - "Add Day-0 Kimi K3 FP4 AgentX performance coverage on 4x8 H200 using the official vLLM H200 recipe: TP16/PP2 at concurrency 1-8, TEP16/PP2 at 4-32, and DEP16/PP2 at 16-128" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index f3f36ff07e..62ba4877fc 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -32,7 +32,7 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then image_cache_dir="/data/gharunners/containers" server_log_dir="$GITHUB_WORKSPACE/multinode_server_logs" gpus_per_node=8 - gpu_count=$((PREFILL_NUM_WORKERS * PREFILL_TP)) + gpu_count=$((PREFILL_NUM_WORKERS * PREFILL_TP * PREFILL_PP_SIZE)) if (( gpu_count % gpus_per_node != 0 )); then echo "Native multi-node GPU count ($gpu_count) must use full 8xH200 nodes" >&2 exit 1 From e29e380c484bafc0b62d1c9d7674fa44ac057186 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 22:08:14 -0500 Subject: [PATCH 14/62] fix(kimik3): use supported model runner --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index f4ee91c550..d5efcff819 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -24,6 +24,7 @@ if [[ "$PREFILL_DP_ATTN" == "true" ]]; then fi export VLLM_ENGINE_READY_TIMEOUT_S=7200 +export VLLM_USE_V2_MODEL_RUNNER=1 export PYTHONNOUSERSITE=1 VLLM_CMD=( From 24fdf3f206d3256afb1c3817abde4ff4ead3603f Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 22:51:36 -0500 Subject: [PATCH 15/62] fix(h200): preserve server logs on cancellation --- .github/workflows/benchmark-multinode-tmpl.yml | 7 +++++-- runners/launch_h200-dgxc-slurm.sh | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmark-multinode-tmpl.yml b/.github/workflows/benchmark-multinode-tmpl.yml index 23f766c388..6ba39b2646 100644 --- a/.github/workflows/benchmark-multinode-tmpl.yml +++ b/.github/workflows/benchmark-multinode-tmpl.yml @@ -391,8 +391,11 @@ jobs: uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: multinode_server_logs_${{ env.RESULT_FILENAME }} - # multinode launchers package server logs into this tarball. - path: multinode_server_logs.tar.gz + # Native launchers also leave the live directory as a cancellation + # fallback when GitHub interrupts tarball creation. + path: | + multinode_server_logs.tar.gz + multinode_server_logs/** if-no-files-found: ignore - name: Upload agentic aggregated result diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 62ba4877fc..9057e508a4 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -77,6 +77,10 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then cleanup_native_multinode() { local exit_code=$? trap - EXIT INT TERM + # Preserve a snapshot before waiting on Slurm: GitHub cancellation may + # forcibly terminate the launcher before the server step exits. + tar czf "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" \ + -C "$server_log_dir" . 2>/dev/null || true kill "$server_step_pid" 2>/dev/null || true wait "$server_step_pid" 2>/dev/null || true tar czf "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" \ From 9baa292f8f3051618ec094f2fdc4cf0fbeafaadd Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 22:54:17 -0500 Subject: [PATCH 16/62] fix(kimik3): preserve full context with DCP --- .../multi_node/agentic/kimik3_fp4_vllm.sh | 7 +++-- configs/nvidia-master.yaml | 31 +++++++++++-------- perf-changelog.yaml | 2 +- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index d5efcff819..e4d3f98a42 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -24,6 +24,7 @@ if [[ "$PREFILL_DP_ATTN" == "true" ]]; then fi export VLLM_ENGINE_READY_TIMEOUT_S=7200 +export VLLM_FASTSAFETENSORS_QUEUE_SIZE=-1 export VLLM_USE_V2_MODEL_RUNNER=1 export PYTHONNOUSERSITE=1 @@ -34,9 +35,8 @@ VLLM_CMD=( --port "$PORT" --trust-remote-code --load-format fastsafetensors - --attention-backend FLASHMLA --moe-backend "$VLLM_MOE_BACKEND" - --gpu-memory-utilization 0.95 + --gpu-memory-utilization 0.99 --enable-prefix-caching --enable-auto-tool-choice --tool-call-parser kimi_k3 @@ -51,6 +51,9 @@ fi if [[ "$VLLM_DISABLE_CUSTOM_ALL_REDUCE" == "1" ]]; then VLLM_CMD+=(--disable-custom-all-reduce) fi +if [ "$PREFILL_DCP_SIZE" -gt 1 ]; then + VLLM_CMD+=(--decode-context-parallel-size "$PREFILL_DCP_SIZE") +fi if [[ "$PREFILL_DP_ATTN" == "true" ]]; then LOCAL_DATA_PARALLEL_SIZE=$((MULTINODE_GPUS_PER_NODE / (PREFILL_TP * PREFILL_PP_SIZE))) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index fb30162772..d4eb7a088d 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1467,12 +1467,13 @@ kimik2.5-int4-h200-vllm-agentic: - { tp: 8, kv-offloading: none, conc-list: [1, 2, 3, 4, 5, 6, 7] } - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: vllm-simple }, conc-list: [6, 7, 8, 9, 10, 11, 12, 13, 14] } -# Kimi K3 is a 2.8T MXFP4 MoE whose full 1M context needs four 8xH200 -# nodes. These are the three aggregated strategies from the official H200 +# Kimi K3 is a 2.8T MXFP4 MoE served on two 8xH200 nodes. +# These are the three aggregated strategies from the official H200 # recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): # multi-node TP is latency-oriented, TEP is balanced, and DEP is -# throughput-oriented. The runner owns Slurm/Pyxis; the in-container Kimi -# entrypoint only receives rank and rendezvous information. +# throughput-oriented. DCP preserves the default 1M context on the TP +# strategies without adding GPUs. The runner owns Slurm/Pyxis; the +# in-container Kimi entrypoint only receives rank and rendezvous information. # P/D disaggregation is intentionally deferred. kimik3-fp4-h200-vllm-agentic: image: vllm/vllm-openai:kimi-k3 @@ -1486,14 +1487,15 @@ kimik3-fp4-h200-vllm-agentic: scenarios: agentic-coding: - search-space: - # Latency-oriented: one TP16/PP2 engine spanning four H200 nodes. + # Latency-oriented: one TP16/DCP16 engine spanning two H200 nodes. - spec-decoding: none kv-offloading: none conc-list: [1, 2, 4, 8] prefill: num-worker: 1 tp: 16 - pp: 2 + pp: 1 + dcp-size: 16 ep: 1 dp-attn: false additional-settings: @@ -1505,17 +1507,19 @@ kimik3-fp4-h200-vllm-agentic: decode: num-worker: 0 tp: 16 - pp: 2 + pp: 1 + dcp-size: 16 ep: 1 dp-attn: false - # Balanced: the same TP16/PP2 engine with expert parallelism. + # Balanced: the same TP16/DCP16 engine with expert parallelism. - spec-decoding: none kv-offloading: none conc-list: [4, 8, 16, 32] prefill: num-worker: 1 tp: 16 - pp: 2 + pp: 1 + dcp-size: 16 ep: 16 dp-attn: false additional-settings: @@ -1527,17 +1531,18 @@ kimik3-fp4-h200-vllm-agentic: decode: num-worker: 0 tp: 16 - pp: 2 + pp: 1 + dcp-size: 16 ep: 16 dp-attn: false - # Throughput-oriented: DEP16/PP2 across four nodes. + # Throughput-oriented: DEP16 across two nodes. - spec-decoding: none kv-offloading: none conc-list: [16, 32, 64, 128] prefill: num-worker: 16 tp: 1 - pp: 2 + pp: 1 ep: 16 dp-attn: true additional-settings: @@ -1549,7 +1554,7 @@ kimik3-fp4-h200-vllm-agentic: decode: num-worker: 0 tp: 1 - pp: 2 + pp: 1 ep: 16 dp-attn: true diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 0002adb45a..bbe5859da9 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5195,5 +5195,5 @@ - config-keys: - kimik3-fp4-h200-vllm-agentic description: - - "Add Day-0 Kimi K3 FP4 AgentX performance coverage on 4x8 H200 using the official vLLM H200 recipe: TP16/PP2 at concurrency 1-8, TEP16/PP2 at 4-32, and DEP16/PP2 at 16-128" + - "Add Day-0 Kimi K3 FP4 AgentX performance coverage on 2x8 H200 from the official vLLM H200 recipe: TP16/DCP16 at concurrency 1-8, TEP16/DCP16 at 4-32, and DEP16 at 16-128" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 From 00acd46bc6e3af40d42955b23b4f3552505ad656 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 23:06:47 -0500 Subject: [PATCH 17/62] fix(kimik3): fit H200 startup memory budget --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index e4d3f98a42..1bba930147 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -36,7 +36,7 @@ VLLM_CMD=( --trust-remote-code --load-format fastsafetensors --moe-backend "$VLLM_MOE_BACKEND" - --gpu-memory-utilization 0.99 + --gpu-memory-utilization 0.982 --enable-prefix-caching --enable-auto-tool-choice --tool-call-parser kimi_k3 From 8e5f3092f882b2b4db9124525c55b53cafb6559d Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 23:18:41 -0500 Subject: [PATCH 18/62] chore(h200): name the vLLM server log clearly --- runners/launch_h200-dgxc-slurm.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 9057e508a4..80b381a370 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -155,7 +155,7 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then --export=ALL \ bash -c 'export MULTINODE_NODE_RANK="$SLURM_PROCID"; exec bash "$1"' \ bash "$server_script" \ - >"$server_log_dir/combined.log" 2>&1 & + >"$server_log_dir/server.log" 2>&1 & server_step_pid=$! for ((attempt = 1; attempt <= 720; attempt++)); do @@ -171,7 +171,7 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then fi if ! kill -0 "$server_step_pid" 2>/dev/null; then echo "Native multi-node server exited before becoming ready" >&2 - tail -n 200 "$server_log_dir/combined.log" >&2 || true + tail -n 200 "$server_log_dir/server.log" >&2 || true exit 1 fi sleep 10 From 8ddd1b920570704de6bed12ae95912e7c77a49c9 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 23:20:56 -0500 Subject: [PATCH 19/62] test(kimik3): reproduce pipeline serving path --- .../multi_node/agentic/kimik3_fp4_vllm.sh | 9 +++--- configs/nvidia-master.yaml | 31 ++++++++----------- perf-changelog.yaml | 2 +- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 1bba930147..500f510ac9 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -24,7 +24,6 @@ if [[ "$PREFILL_DP_ATTN" == "true" ]]; then fi export VLLM_ENGINE_READY_TIMEOUT_S=7200 -export VLLM_FASTSAFETENSORS_QUEUE_SIZE=-1 export VLLM_USE_V2_MODEL_RUNNER=1 export PYTHONNOUSERSITE=1 @@ -36,7 +35,7 @@ VLLM_CMD=( --trust-remote-code --load-format fastsafetensors --moe-backend "$VLLM_MOE_BACKEND" - --gpu-memory-utilization 0.982 + --gpu-memory-utilization 0.95 --enable-prefix-caching --enable-auto-tool-choice --tool-call-parser kimi_k3 @@ -45,15 +44,15 @@ VLLM_CMD=( --max-num-seqs "$MAX_NUM_SEQS" ) +if [ "$PREFILL_PP_SIZE" -gt 1 ]; then + VLLM_CMD+=(--attention-backend FLASHMLA) +fi if [[ "$VLLM_DISABLE_FLASHINFER_AUTOTUNE" == "1" ]]; then VLLM_CMD+=(--no-enable-flashinfer-autotune) fi if [[ "$VLLM_DISABLE_CUSTOM_ALL_REDUCE" == "1" ]]; then VLLM_CMD+=(--disable-custom-all-reduce) fi -if [ "$PREFILL_DCP_SIZE" -gt 1 ]; then - VLLM_CMD+=(--decode-context-parallel-size "$PREFILL_DCP_SIZE") -fi if [[ "$PREFILL_DP_ATTN" == "true" ]]; then LOCAL_DATA_PARALLEL_SIZE=$((MULTINODE_GPUS_PER_NODE / (PREFILL_TP * PREFILL_PP_SIZE))) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index d4eb7a088d..fb30162772 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1467,13 +1467,12 @@ kimik2.5-int4-h200-vllm-agentic: - { tp: 8, kv-offloading: none, conc-list: [1, 2, 3, 4, 5, 6, 7] } - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: vllm-simple }, conc-list: [6, 7, 8, 9, 10, 11, 12, 13, 14] } -# Kimi K3 is a 2.8T MXFP4 MoE served on two 8xH200 nodes. -# These are the three aggregated strategies from the official H200 +# Kimi K3 is a 2.8T MXFP4 MoE whose full 1M context needs four 8xH200 +# nodes. These are the three aggregated strategies from the official H200 # recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): # multi-node TP is latency-oriented, TEP is balanced, and DEP is -# throughput-oriented. DCP preserves the default 1M context on the TP -# strategies without adding GPUs. The runner owns Slurm/Pyxis; the -# in-container Kimi entrypoint only receives rank and rendezvous information. +# throughput-oriented. The runner owns Slurm/Pyxis; the in-container Kimi +# entrypoint only receives rank and rendezvous information. # P/D disaggregation is intentionally deferred. kimik3-fp4-h200-vllm-agentic: image: vllm/vllm-openai:kimi-k3 @@ -1487,15 +1486,14 @@ kimik3-fp4-h200-vllm-agentic: scenarios: agentic-coding: - search-space: - # Latency-oriented: one TP16/DCP16 engine spanning two H200 nodes. + # Latency-oriented: one TP16/PP2 engine spanning four H200 nodes. - spec-decoding: none kv-offloading: none conc-list: [1, 2, 4, 8] prefill: num-worker: 1 tp: 16 - pp: 1 - dcp-size: 16 + pp: 2 ep: 1 dp-attn: false additional-settings: @@ -1507,19 +1505,17 @@ kimik3-fp4-h200-vllm-agentic: decode: num-worker: 0 tp: 16 - pp: 1 - dcp-size: 16 + pp: 2 ep: 1 dp-attn: false - # Balanced: the same TP16/DCP16 engine with expert parallelism. + # Balanced: the same TP16/PP2 engine with expert parallelism. - spec-decoding: none kv-offloading: none conc-list: [4, 8, 16, 32] prefill: num-worker: 1 tp: 16 - pp: 1 - dcp-size: 16 + pp: 2 ep: 16 dp-attn: false additional-settings: @@ -1531,18 +1527,17 @@ kimik3-fp4-h200-vllm-agentic: decode: num-worker: 0 tp: 16 - pp: 1 - dcp-size: 16 + pp: 2 ep: 16 dp-attn: false - # Throughput-oriented: DEP16 across two nodes. + # Throughput-oriented: DEP16/PP2 across four nodes. - spec-decoding: none kv-offloading: none conc-list: [16, 32, 64, 128] prefill: num-worker: 16 tp: 1 - pp: 1 + pp: 2 ep: 16 dp-attn: true additional-settings: @@ -1554,7 +1549,7 @@ kimik3-fp4-h200-vllm-agentic: decode: num-worker: 0 tp: 1 - pp: 1 + pp: 2 ep: 16 dp-attn: true diff --git a/perf-changelog.yaml b/perf-changelog.yaml index bbe5859da9..21c8dd7650 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5195,5 +5195,5 @@ - config-keys: - kimik3-fp4-h200-vllm-agentic description: - - "Add Day-0 Kimi K3 FP4 AgentX performance coverage on 2x8 H200 from the official vLLM H200 recipe: TP16/DCP16 at concurrency 1-8, TEP16/DCP16 at 4-32, and DEP16 at 16-128" + - "Add Day-0 Kimi K3 FP4 AgentX performance coverage on 4x8 H200 from the official vLLM H200 recipe: TP16/PP2 at concurrency 1-8, TEP16/PP2 at 4-32, and DEP16/PP2 at 16-128" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 From a73f11068035533b21ffc33212552911587fb4ef Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 23:32:48 -0500 Subject: [PATCH 20/62] fix(kimik3): use two-node reference topologies --- configs/nvidia-master.yaml | 32 ++++++++++++++++---------------- perf-changelog.yaml | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index fb30162772..0d385cf78f 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1467,8 +1467,8 @@ kimik2.5-int4-h200-vllm-agentic: - { tp: 8, kv-offloading: none, conc-list: [1, 2, 3, 4, 5, 6, 7] } - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: vllm-simple }, conc-list: [6, 7, 8, 9, 10, 11, 12, 13, 14] } -# Kimi K3 is a 2.8T MXFP4 MoE whose full 1M context needs four 8xH200 -# nodes. These are the three aggregated strategies from the official H200 +# Kimi K3 is a 2.8T MXFP4 MoE served on two 8xH200 nodes. +# These are the three aggregated strategies from the official H200 # recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): # multi-node TP is latency-oriented, TEP is balanced, and DEP is # throughput-oriented. The runner owns Slurm/Pyxis; the in-container Kimi @@ -1486,13 +1486,13 @@ kimik3-fp4-h200-vllm-agentic: scenarios: agentic-coding: - search-space: - # Latency-oriented: one TP16/PP2 engine spanning four H200 nodes. + # Latency-oriented: one TP8/PP2 engine spanning two H200 nodes. - spec-decoding: none kv-offloading: none conc-list: [1, 2, 4, 8] prefill: num-worker: 1 - tp: 16 + tp: 8 pp: 2 ep: 1 dp-attn: false @@ -1504,20 +1504,20 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 16 + tp: 8 pp: 2 ep: 1 dp-attn: false - # Balanced: the same TP16/PP2 engine with expert parallelism. + # Balanced: TEP16 across two nodes (TP8 attention, DP2/EP16 MoE). - spec-decoding: none kv-offloading: none conc-list: [4, 8, 16, 32] prefill: - num-worker: 1 - tp: 16 - pp: 2 + num-worker: 2 + tp: 8 + pp: 1 ep: 16 - dp-attn: false + dp-attn: true additional-settings: - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" @@ -1526,18 +1526,18 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 16 - pp: 2 + tp: 8 + pp: 1 ep: 16 - dp-attn: false - # Throughput-oriented: DEP16/PP2 across four nodes. + dp-attn: true + # Throughput-oriented: DEP16 across two nodes. - spec-decoding: none kv-offloading: none conc-list: [16, 32, 64, 128] prefill: num-worker: 16 tp: 1 - pp: 2 + pp: 1 ep: 16 dp-attn: true additional-settings: @@ -1549,7 +1549,7 @@ kimik3-fp4-h200-vllm-agentic: decode: num-worker: 0 tp: 1 - pp: 2 + pp: 1 ep: 16 dp-attn: true diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 21c8dd7650..18944eb253 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5195,5 +5195,5 @@ - config-keys: - kimik3-fp4-h200-vllm-agentic description: - - "Add Day-0 Kimi K3 FP4 AgentX performance coverage on 4x8 H200 from the official vLLM H200 recipe: TP16/PP2 at concurrency 1-8, TEP16/PP2 at 4-32, and DEP16/PP2 at 16-128" + - "Add Day-0 Kimi K3 FP4 AgentX performance coverage and recipes on 2x8 H200 from the official vLLM recipe: TP8/PP2 at concurrency 1-8, TEP16 at 4-32, and DEP16 at 16-128" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 From 8cd634abda3a57c5489cb0cace8bc6cdb93d9c00 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 23:49:08 -0500 Subject: [PATCH 21/62] fix(h200): reuse host git for agentic clients --- runners/launch_h200-dgxc-slurm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 80b381a370..207dc4e98c 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -42,7 +42,7 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then client_script="benchmarks/multi_node/agentic_srt.sh" squash_file="$image_cache_dir/$(echo "$IMAGE" | sed 's/[\/:@#]/_/g').sqsh" lock_file="${squash_file}.lock" - container_mounts="$GITHUB_WORKSPACE:/workspace,$hf_cache_host_path:$hf_cache_container_path,$aiperf_cache_host_path:/aiperf_mmap_cache" + container_mounts="$GITHUB_WORKSPACE:/workspace,$hf_cache_host_path:$hf_cache_container_path,$aiperf_cache_host_path:/aiperf_mmap_cache,/usr/bin/git:/usr/bin/git,/usr/lib/git-core:/usr/lib/git-core" if [[ ! -d "$model_host_path" || ! -f "$server_script" ]]; then echo "Missing model or benchmark entrypoint: $model_host_path / $server_script" >&2 From e1f7d837a9bcf9ffa93e4e541191186103d729de Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 23:51:59 -0500 Subject: [PATCH 22/62] test(kimik3): probe two-node DCP serving --- .../multi_node/agentic/kimik3_fp4_vllm.sh | 3 +++ configs/nvidia-master.yaml | 24 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 500f510ac9..001e5a3049 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -53,6 +53,9 @@ fi if [[ "$VLLM_DISABLE_CUSTOM_ALL_REDUCE" == "1" ]]; then VLLM_CMD+=(--disable-custom-all-reduce) fi +if [ "$PREFILL_DCP_SIZE" -gt 1 ]; then + VLLM_CMD+=(--decode-context-parallel-size "$PREFILL_DCP_SIZE") +fi if [[ "$PREFILL_DP_ATTN" == "true" ]]; then LOCAL_DATA_PARALLEL_SIZE=$((MULTINODE_GPUS_PER_NODE / (PREFILL_TP * PREFILL_PP_SIZE))) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 0d385cf78f..a5a7fc0c7c 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1508,6 +1508,30 @@ kimik3-fp4-h200-vllm-agentic: pp: 2 ep: 1 dp-attn: false + # Bring-up probe: preserve full context with DCP across two nodes. + - spec-decoding: none + kv-offloading: none + conc-list: [3] + prefill: + num-worker: 1 + tp: 16 + pp: 1 + dcp-size: 16 + ep: 1 + dp-attn: false + additional-settings: + - "NATIVE_MULTINODE=1" + - "VLLM_MOE_BACKEND=marlin" + - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" + - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" + - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" + decode: + num-worker: 0 + tp: 16 + pp: 1 + dcp-size: 16 + ep: 1 + dp-attn: false # Balanced: TEP16 across two nodes (TP8 attention, DP2/EP16 MoE). - spec-decoding: none kv-offloading: none From 0335cd9467ca08e638675263c470d749acaed9ee Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Mon, 27 Jul 2026 23:56:35 -0500 Subject: [PATCH 23/62] test(kimik3): probe two-node TEP serving --- .../multi_node/agentic/kimik3_fp4_vllm.sh | 4 --- configs/nvidia-master.yaml | 26 +------------------ 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 001e5a3049..a0501abe47 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -53,10 +53,6 @@ fi if [[ "$VLLM_DISABLE_CUSTOM_ALL_REDUCE" == "1" ]]; then VLLM_CMD+=(--disable-custom-all-reduce) fi -if [ "$PREFILL_DCP_SIZE" -gt 1 ]; then - VLLM_CMD+=(--decode-context-parallel-size "$PREFILL_DCP_SIZE") -fi - if [[ "$PREFILL_DP_ATTN" == "true" ]]; then LOCAL_DATA_PARALLEL_SIZE=$((MULTINODE_GPUS_PER_NODE / (PREFILL_TP * PREFILL_PP_SIZE))) VLLM_CMD+=( diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index a5a7fc0c7c..f06b1c073d 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1508,34 +1508,10 @@ kimik3-fp4-h200-vllm-agentic: pp: 2 ep: 1 dp-attn: false - # Bring-up probe: preserve full context with DCP across two nodes. - - spec-decoding: none - kv-offloading: none - conc-list: [3] - prefill: - num-worker: 1 - tp: 16 - pp: 1 - dcp-size: 16 - ep: 1 - dp-attn: false - additional-settings: - - "NATIVE_MULTINODE=1" - - "VLLM_MOE_BACKEND=marlin" - - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" - decode: - num-worker: 0 - tp: 16 - pp: 1 - dcp-size: 16 - ep: 1 - dp-attn: false # Balanced: TEP16 across two nodes (TP8 attention, DP2/EP16 MoE). - spec-decoding: none kv-offloading: none - conc-list: [4, 8, 16, 32] + conc-list: [3] prefill: num-worker: 2 tp: 8 From 08d7400354ca3b6f481a244d2dff3c32d56bb04c Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 00:01:59 -0500 Subject: [PATCH 24/62] fix(kimik3): stream TEP and DEP weight loading --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index a0501abe47..a094d8bca9 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -27,13 +27,18 @@ export VLLM_ENGINE_READY_TIMEOUT_S=7200 export VLLM_USE_V2_MODEL_RUNNER=1 export PYTHONNOUSERSITE=1 +LOAD_FORMAT=fastsafetensors +if [[ "$PREFILL_DP_ATTN" == "true" ]]; then + LOAD_FORMAT=auto +fi + VLLM_CMD=( vllm serve "$MODEL_PATH" --served-model-name "$MODEL" --host 0.0.0.0 --port "$PORT" --trust-remote-code - --load-format fastsafetensors + --load-format "$LOAD_FORMAT" --moe-backend "$VLLM_MOE_BACKEND" --gpu-memory-utilization 0.95 --enable-prefix-caching From ccb01fa5de03004cf2755d399efa0e2d2e92c5b4 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 00:12:07 -0500 Subject: [PATCH 25/62] fix(h200): expose all local DP endpoints --- runners/launch_h200-dgxc-slurm.sh | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 207dc4e98c..7f265b8f7a 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -108,21 +108,23 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then exit 1 fi server_nodes="$head_node" + server_ports_per_node=1 if [[ "$PREFILL_DP_ATTN" == "true" ]]; then server_nodes="$allocated_nodes" + server_ports_per_node=$((gpus_per_node / (PREFILL_TP * PREFILL_PP_SIZE))) fi - endpoint_urls= - metrics_urls= + server_urls=() + metrics_urls=() for server_node in $server_nodes; do - if [[ -n "$endpoint_urls" ]]; then - endpoint_urls+="," - metrics_urls+="," - fi - endpoint_urls+="http://$server_node:$PORT" - metrics_urls+="http://$server_node:$PORT/metrics" + for ((local_dp_rank = 0; local_dp_rank < server_ports_per_node; local_dp_rank++)); do + server_port=$((PORT + local_dp_rank)) + server_urls+=("http://$server_node:$server_port") + metrics_urls+=("http://$server_node:$server_port/metrics") + done done - export AIPERF_ENDPOINT_URLS="$endpoint_urls" - export AIPERF_SERVER_METRICS_URLS="$metrics_urls" + AIPERF_ENDPOINT_URLS=$(IFS=,; echo "${server_urls[*]}") + AIPERF_SERVER_METRICS_URLS=$(IFS=,; echo "${metrics_urls[*]}") + export AIPERF_ENDPOINT_URLS AIPERF_SERVER_METRICS_URLS srun --jobid="$job_id" --nodes=1 --ntasks=1 --nodelist="$head_node" bash -c " export ENROOT_CACHE_PATH=\$HOME/.cache/enroot @@ -160,8 +162,8 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then for ((attempt = 1; attempt <= 720; attempt++)); do servers_ready=true - for server_node in $server_nodes; do - if ! curl --output /dev/null --silent --fail "http://$server_node:$PORT/health"; then + for server_url in "${server_urls[@]}"; do + if ! curl --output /dev/null --silent --fail "$server_url/health"; then servers_ready=false break fi From 9609bca7040f17c84c4a80499c90f1cffd0f3602 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 00:14:59 -0500 Subject: [PATCH 26/62] test(kimik3): probe full-context TP16 serving --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 7 +++---- configs/nvidia-master.yaml | 12 ++++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index a094d8bca9..3517f587af 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -40,7 +40,9 @@ VLLM_CMD=( --trust-remote-code --load-format "$LOAD_FORMAT" --moe-backend "$VLLM_MOE_BACKEND" - --gpu-memory-utilization 0.95 + --kv-cache-dtype fp8 + --gpu-memory-utilization 0.99 + --attention-config '{"use_prefill_query_quantization":true}' --enable-prefix-caching --enable-auto-tool-choice --tool-call-parser kimi_k3 @@ -49,9 +51,6 @@ VLLM_CMD=( --max-num-seqs "$MAX_NUM_SEQS" ) -if [ "$PREFILL_PP_SIZE" -gt 1 ]; then - VLLM_CMD+=(--attention-backend FLASHMLA) -fi if [[ "$VLLM_DISABLE_FLASHINFER_AUTOTUNE" == "1" ]]; then VLLM_CMD+=(--no-enable-flashinfer-autotune) fi diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index f06b1c073d..55ecf6e572 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1486,14 +1486,14 @@ kimik3-fp4-h200-vllm-agentic: scenarios: agentic-coding: - search-space: - # Latency-oriented: one TP8/PP2 engine spanning two H200 nodes. + # Latency-oriented: one TP16 engine spanning two H200 nodes. - spec-decoding: none kv-offloading: none - conc-list: [1, 2, 4, 8] + conc-list: [5] prefill: num-worker: 1 - tp: 8 - pp: 2 + tp: 16 + pp: 1 ep: 1 dp-attn: false additional-settings: @@ -1504,8 +1504,8 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 8 - pp: 2 + tp: 16 + pp: 1 ep: 1 dp-attn: false # Balanced: TEP16 across two nodes (TP8 attention, DP2/EP16 MoE). From e5cdcbbe316c3bd22c74af3db43c335414b98550 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 00:19:14 -0500 Subject: [PATCH 27/62] fix(kimik3): leave room for distributed startup --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 3517f587af..4719fbfcba 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -41,7 +41,7 @@ VLLM_CMD=( --load-format "$LOAD_FORMAT" --moe-backend "$VLLM_MOE_BACKEND" --kv-cache-dtype fp8 - --gpu-memory-utilization 0.99 + --gpu-memory-utilization 0.985 --attention-config '{"use_prefill_query_quantization":true}' --enable-prefix-caching --enable-auto-tool-choice From 0fda2ca34e1d8e20ae573c1e1ab103cb0c291b21 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 00:24:03 -0500 Subject: [PATCH 28/62] fix(kimik3): stream all multi-node weight loads --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 4719fbfcba..91d730354f 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -27,18 +27,13 @@ export VLLM_ENGINE_READY_TIMEOUT_S=7200 export VLLM_USE_V2_MODEL_RUNNER=1 export PYTHONNOUSERSITE=1 -LOAD_FORMAT=fastsafetensors -if [[ "$PREFILL_DP_ATTN" == "true" ]]; then - LOAD_FORMAT=auto -fi - VLLM_CMD=( vllm serve "$MODEL_PATH" --served-model-name "$MODEL" --host 0.0.0.0 --port "$PORT" --trust-remote-code - --load-format "$LOAD_FORMAT" + --load-format auto --moe-backend "$VLLM_MOE_BACKEND" --kv-cache-dtype fp8 --gpu-memory-utilization 0.985 From b92ce484a051545f6201fefd0b624433499249b2 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 00:28:42 -0500 Subject: [PATCH 29/62] fix(h200): stop failed engines during readiness --- runners/launch_h200-dgxc-slurm.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 7f265b8f7a..248c4862fa 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -176,6 +176,11 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then tail -n 200 "$server_log_dir/server.log" >&2 || true exit 1 fi + if grep -q "Engine core initialization failed" "$server_log_dir/server.log"; then + echo "Native multi-node engine failed before becoming ready" >&2 + tail -n 200 "$server_log_dir/server.log" >&2 + exit 1 + fi sleep 10 done if (( attempt > 720 )); then From 2b8c47f4d2e3ca0329109ba5a5b20309cd98d44a Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 00:29:19 -0500 Subject: [PATCH 30/62] test(kimik3): probe four-node DP16 serving --- configs/nvidia-master.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 55ecf6e572..a3f6f9339d 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1467,7 +1467,7 @@ kimik2.5-int4-h200-vllm-agentic: - { tp: 8, kv-offloading: none, conc-list: [1, 2, 3, 4, 5, 6, 7] } - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: vllm-simple }, conc-list: [6, 7, 8, 9, 10, 11, 12, 13, 14] } -# Kimi K3 is a 2.8T MXFP4 MoE served on two 8xH200 nodes. +# Kimi K3 is a 2.8T MXFP4 MoE served on 8xH200 nodes. # These are the three aggregated strategies from the official H200 # recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): # multi-node TP is latency-oriented, TEP is balanced, and DEP is @@ -1530,15 +1530,15 @@ kimik3-fp4-h200-vllm-agentic: pp: 1 ep: 16 dp-attn: true - # Throughput-oriented: DEP16 across two nodes. + # Throughput-oriented: TP2 with DP16/EP32 across four nodes. - spec-decoding: none kv-offloading: none conc-list: [16, 32, 64, 128] prefill: num-worker: 16 - tp: 1 + tp: 2 pp: 1 - ep: 16 + ep: 32 dp-attn: true additional-settings: - "NATIVE_MULTINODE=1" @@ -1548,9 +1548,9 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 1 + tp: 2 pp: 1 - ep: 16 + ep: 32 dp-attn: true # NOTE: At the time of submission, https://docs.vllm.ai/projects/recipes/en/latest/moonshotai/Kimi-K2.5.html From 18e2b3f064e58ef8266e0e65488995e1c5a155a4 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 00:32:04 -0500 Subject: [PATCH 31/62] test(kimik3): run PP with the V1 model runner --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 6 ++++++ configs/nvidia-master.yaml | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 91d730354f..541b9c3b11 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -25,6 +25,9 @@ fi export VLLM_ENGINE_READY_TIMEOUT_S=7200 export VLLM_USE_V2_MODEL_RUNNER=1 +if [ "$PREFILL_PP_SIZE" -gt 1 ]; then + export VLLM_USE_V2_MODEL_RUNNER=0 +fi export PYTHONNOUSERSITE=1 VLLM_CMD=( @@ -46,6 +49,9 @@ VLLM_CMD=( --max-num-seqs "$MAX_NUM_SEQS" ) +if [ "$PREFILL_PP_SIZE" -gt 1 ]; then + VLLM_CMD+=(--attention-backend FLASHMLA) +fi if [[ "$VLLM_DISABLE_FLASHINFER_AUTOTUNE" == "1" ]]; then VLLM_CMD+=(--no-enable-flashinfer-autotune) fi diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index a3f6f9339d..4c98c70cdd 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1486,14 +1486,14 @@ kimik3-fp4-h200-vllm-agentic: scenarios: agentic-coding: - search-space: - # Latency-oriented: one TP16 engine spanning two H200 nodes. + # Latency-oriented: one TP8/PP2 engine spanning two H200 nodes. - spec-decoding: none kv-offloading: none conc-list: [5] prefill: num-worker: 1 - tp: 16 - pp: 1 + tp: 8 + pp: 2 ep: 1 dp-attn: false additional-settings: @@ -1504,8 +1504,8 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 16 - pp: 1 + tp: 8 + pp: 2 ep: 1 dp-attn: false # Balanced: TEP16 across two nodes (TP8 attention, DP2/EP16 MoE). From b7e58f3d651e23affde5deb393800b0ac5f99269 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 00:35:44 -0500 Subject: [PATCH 32/62] fix(kimik3): allow distributed worker overhead --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 541b9c3b11..2ffa2f5875 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -39,7 +39,7 @@ VLLM_CMD=( --load-format auto --moe-backend "$VLLM_MOE_BACKEND" --kv-cache-dtype fp8 - --gpu-memory-utilization 0.985 + --gpu-memory-utilization 0.97 --attention-config '{"use_prefill_query_quantization":true}' --enable-prefix-caching --enable-auto-tool-choice From b3b628db5ab742ae00502b73877d0e96ddd199b5 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 00:41:06 -0500 Subject: [PATCH 33/62] perf(kimik3): use fast loading for PP --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 2ffa2f5875..a70ff9022c 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -30,13 +30,18 @@ if [ "$PREFILL_PP_SIZE" -gt 1 ]; then fi export PYTHONNOUSERSITE=1 +LOAD_FORMAT=auto +if [ "$PREFILL_PP_SIZE" -gt 1 ]; then + LOAD_FORMAT=fastsafetensors +fi + VLLM_CMD=( vllm serve "$MODEL_PATH" --served-model-name "$MODEL" --host 0.0.0.0 --port "$PORT" --trust-remote-code - --load-format auto + --load-format "$LOAD_FORMAT" --moe-backend "$VLLM_MOE_BACKEND" --kv-cache-dtype fp8 --gpu-memory-utilization 0.97 From f2d1243306ac93ebd409fb52f3d9682797fafbf7 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 00:54:48 -0500 Subject: [PATCH 34/62] fix(kimik3): use bf16 kv cache for PP --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index a70ff9022c..98e23ec3fc 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -43,9 +43,7 @@ VLLM_CMD=( --trust-remote-code --load-format "$LOAD_FORMAT" --moe-backend "$VLLM_MOE_BACKEND" - --kv-cache-dtype fp8 --gpu-memory-utilization 0.97 - --attention-config '{"use_prefill_query_quantization":true}' --enable-prefix-caching --enable-auto-tool-choice --tool-call-parser kimi_k3 From 83c9ca5238e8115495ce3323f1350a18f06a83f1 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 01:07:23 -0500 Subject: [PATCH 35/62] fix(kimik3): reserve PP runtime memory --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index 98e23ec3fc..c515ea3803 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -43,7 +43,7 @@ VLLM_CMD=( --trust-remote-code --load-format "$LOAD_FORMAT" --moe-backend "$VLLM_MOE_BACKEND" - --gpu-memory-utilization 0.97 + --gpu-memory-utilization 0.95 --enable-prefix-caching --enable-auto-tool-choice --tool-call-parser kimi_k3 From 5fc99b016c93f57abdd6851ea24d334a2d6806ba Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 01:19:11 -0500 Subject: [PATCH 36/62] perf(kimik3): add PP to EP strategies --- configs/nvidia-master.yaml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 4c98c70cdd..863caecede 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1508,15 +1508,15 @@ kimik3-fp4-h200-vllm-agentic: pp: 2 ep: 1 dp-attn: false - # Balanced: TEP16 across two nodes (TP8 attention, DP2/EP16 MoE). + # Balanced: TP4/PP2 with DP2/EP8 across two H200 nodes. - spec-decoding: none kv-offloading: none conc-list: [3] prefill: num-worker: 2 - tp: 8 - pp: 1 - ep: 16 + tp: 4 + pp: 2 + ep: 8 dp-attn: true additional-settings: - "NATIVE_MULTINODE=1" @@ -1526,19 +1526,19 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 8 - pp: 1 - ep: 16 + tp: 4 + pp: 2 + ep: 8 dp-attn: true - # Throughput-oriented: TP2 with DP16/EP32 across four nodes. + # Throughput-oriented: TP1/PP2 with DP16/EP16 across four H200 nodes. - spec-decoding: none kv-offloading: none conc-list: [16, 32, 64, 128] prefill: num-worker: 16 - tp: 2 - pp: 1 - ep: 32 + tp: 1 + pp: 2 + ep: 16 dp-attn: true additional-settings: - "NATIVE_MULTINODE=1" @@ -1548,9 +1548,9 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 2 - pp: 1 - ep: 32 + tp: 1 + pp: 2 + ep: 16 dp-attn: true # NOTE: At the time of submission, https://docs.vllm.ai/projects/recipes/en/latest/moonshotai/Kimi-K2.5.html From a65e0b9bb54f59b6ae5d45d0a96b59b36a7b9c08 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 01:31:46 -0500 Subject: [PATCH 37/62] fix(kimik3): reserve topology workspace --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 3 ++- configs/nvidia-master.yaml | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index c515ea3803..a1d8df4c00 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -43,7 +43,8 @@ VLLM_CMD=( --trust-remote-code --load-format "$LOAD_FORMAT" --moe-backend "$VLLM_MOE_BACKEND" - --gpu-memory-utilization 0.95 + --gpu-memory-utilization "$VLLM_GPU_MEMORY_UTILIZATION" + --max-num-batched-tokens "$VLLM_MAX_NUM_BATCHED_TOKENS" --enable-prefix-caching --enable-auto-tool-choice --tool-call-parser kimi_k3 diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 863caecede..f449607edc 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1499,6 +1499,8 @@ kimik3-fp4-h200-vllm-agentic: additional-settings: - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" + - "VLLM_GPU_MEMORY_UTILIZATION=0.95" + - "VLLM_MAX_NUM_BATCHED_TOKENS=8192" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" @@ -1521,6 +1523,8 @@ kimik3-fp4-h200-vllm-agentic: additional-settings: - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" + - "VLLM_GPU_MEMORY_UTILIZATION=0.90" + - "VLLM_MAX_NUM_BATCHED_TOKENS=4096" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" @@ -1543,6 +1547,8 @@ kimik3-fp4-h200-vllm-agentic: additional-settings: - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" + - "VLLM_GPU_MEMORY_UTILIZATION=0.95" + - "VLLM_MAX_NUM_BATCHED_TOKENS=2048" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" From f2090e767ad7fedb4f7ae9e5e221ddef68fda933 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 01:33:28 -0500 Subject: [PATCH 38/62] fix(kimik3): reduce latency prefill chunk --- 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 f449607edc..f290d2f450 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1500,7 +1500,7 @@ kimik3-fp4-h200-vllm-agentic: - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" - "VLLM_GPU_MEMORY_UTILIZATION=0.95" - - "VLLM_MAX_NUM_BATCHED_TOKENS=8192" + - "VLLM_MAX_NUM_BATCHED_TOKENS=4096" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" From adc1109456ba08cf113fadaa35c998c5fd32168e Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 01:37:48 -0500 Subject: [PATCH 39/62] fix(kimik3): align H200 overrides with official recipe --- benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh | 1 - configs/nvidia-master.yaml | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh index a1d8df4c00..97b326b2a9 100755 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh @@ -45,7 +45,6 @@ VLLM_CMD=( --moe-backend "$VLLM_MOE_BACKEND" --gpu-memory-utilization "$VLLM_GPU_MEMORY_UTILIZATION" --max-num-batched-tokens "$VLLM_MAX_NUM_BATCHED_TOKENS" - --enable-prefix-caching --enable-auto-tool-choice --tool-call-parser kimi_k3 --reasoning-parser kimi_k3 diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index f290d2f450..7bd86a13cc 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1504,6 +1504,7 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" + - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 8 @@ -1528,6 +1529,7 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" + - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 4 @@ -1552,6 +1554,7 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" + - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 1 From d33f8445cacfbd6ea4db884f81c13d7589b3282c Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 01:42:38 -0500 Subject: [PATCH 40/62] fix(kimik3): disable SM100-only tail fusion on H200 --- configs/nvidia-master.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 7bd86a13cc..f290d2f450 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1504,7 +1504,6 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" - - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 8 @@ -1529,7 +1528,6 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" - - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 4 @@ -1554,7 +1552,6 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" - - "VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION=1" decode: num-worker: 0 tp: 1 From a4c259b55cfb7e432b054a0441d38d316aad3ebb Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 01:55:49 -0500 Subject: [PATCH 41/62] fix(kimik3): use one shared API port per DP node --- runners/launch_h200-dgxc-slurm.sh | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 248c4862fa..fb28d4d435 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -108,19 +108,14 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then exit 1 fi server_nodes="$head_node" - server_ports_per_node=1 if [[ "$PREFILL_DP_ATTN" == "true" ]]; then server_nodes="$allocated_nodes" - server_ports_per_node=$((gpus_per_node / (PREFILL_TP * PREFILL_PP_SIZE))) fi server_urls=() metrics_urls=() for server_node in $server_nodes; do - for ((local_dp_rank = 0; local_dp_rank < server_ports_per_node; local_dp_rank++)); do - server_port=$((PORT + local_dp_rank)) - server_urls+=("http://$server_node:$server_port") - metrics_urls+=("http://$server_node:$server_port/metrics") - done + server_urls+=("http://$server_node:$PORT") + metrics_urls+=("http://$server_node:$PORT/metrics") done AIPERF_ENDPOINT_URLS=$(IFS=,; echo "${server_urls[*]}") AIPERF_SERVER_METRICS_URLS=$(IFS=,; echo "${metrics_urls[*]}") From deae74effe2dede07c8fe3bbab818ff9bf2976f5 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 02:08:24 -0500 Subject: [PATCH 42/62] fix(kimik3): leave throughput prefill headroom --- 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 f290d2f450..203eafa04c 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1547,7 +1547,7 @@ kimik3-fp4-h200-vllm-agentic: additional-settings: - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" - - "VLLM_GPU_MEMORY_UTILIZATION=0.95" + - "VLLM_GPU_MEMORY_UTILIZATION=0.90" - "VLLM_MAX_NUM_BATCHED_TOKENS=2048" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" From d0eefabe420ffdbf677b8e6d459bba679bf5e360 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 02:14:22 -0500 Subject: [PATCH 43/62] perf(kimik3): restore Day 0 sweep ranges --- configs/nvidia-master.yaml | 6 +++--- perf-changelog.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 203eafa04c..1041642108 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1467,7 +1467,7 @@ kimik2.5-int4-h200-vllm-agentic: - { tp: 8, kv-offloading: none, conc-list: [1, 2, 3, 4, 5, 6, 7] } - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: vllm-simple }, conc-list: [6, 7, 8, 9, 10, 11, 12, 13, 14] } -# Kimi K3 is a 2.8T MXFP4 MoE served on 8xH200 nodes. +# Kimi K3 is a 2.8T MXFP4 MoE served on H200 nodes. # These are the three aggregated strategies from the official H200 # recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): # multi-node TP is latency-oriented, TEP is balanced, and DEP is @@ -1489,7 +1489,7 @@ kimik3-fp4-h200-vllm-agentic: # Latency-oriented: one TP8/PP2 engine spanning two H200 nodes. - spec-decoding: none kv-offloading: none - conc-list: [5] + conc-list: [1, 2, 4, 8] prefill: num-worker: 1 tp: 8 @@ -1513,7 +1513,7 @@ kimik3-fp4-h200-vllm-agentic: # Balanced: TP4/PP2 with DP2/EP8 across two H200 nodes. - spec-decoding: none kv-offloading: none - conc-list: [3] + conc-list: [4, 8, 16, 32] prefill: num-worker: 2 tp: 4 diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 18944eb253..525e60eea7 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5195,5 +5195,5 @@ - config-keys: - kimik3-fp4-h200-vllm-agentic description: - - "Add Day-0 Kimi K3 FP4 AgentX performance coverage and recipes on 2x8 H200 from the official vLLM recipe: TP8/PP2 at concurrency 1-8, TEP16 at 4-32, and DEP16 at 16-128" + - "Add Day-0 Kimi K3 FP4 AgentX performance coverage and H200 recipes based on the official vLLM recipe" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 From 6e98eed175412af83780d735c011fbb5a6a606c6 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 02:28:36 -0500 Subject: [PATCH 44/62] fix(kimik3): preserve throughput activation headroom --- 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 1041642108..881376f273 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1547,7 +1547,7 @@ kimik3-fp4-h200-vllm-agentic: additional-settings: - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" - - "VLLM_GPU_MEMORY_UTILIZATION=0.90" + - "VLLM_GPU_MEMORY_UTILIZATION=0.875" - "VLLM_MAX_NUM_BATCHED_TOKENS=2048" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" From 7c2bcd4cc5f3ed3d3778d9414fa70fbf10f553cf Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 02:45:03 -0500 Subject: [PATCH 45/62] fix(h200): guard cleanup before server startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid referencing an unset server process ID so early native multi-node failures still cancel their Slurm allocation and preserve logs.\n\n中文:避免在服务进程启动前引用未设置的 PID,确保原生多节点任务提前失败时仍能取消 Slurm 分配并保留日志。 --- runners/launch_h200-dgxc-slurm.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index fb28d4d435..54ff2a186b 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -74,6 +74,7 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then exit 1 fi + server_step_pid="" cleanup_native_multinode() { local exit_code=$? trap - EXIT INT TERM @@ -81,8 +82,10 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then # forcibly terminate the launcher before the server step exits. tar czf "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" \ -C "$server_log_dir" . 2>/dev/null || true - kill "$server_step_pid" 2>/dev/null || true - wait "$server_step_pid" 2>/dev/null || true + if [[ -n "$server_step_pid" ]]; then + kill "$server_step_pid" 2>/dev/null || true + wait "$server_step_pid" 2>/dev/null || true + fi tar czf "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" \ -C "$server_log_dir" . 2>/dev/null || true scancel "$job_id" 2>/dev/null || true From f99af81b68d1b7dde6f2ce81eac9cd99f2d24bf7 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 02:52:28 -0500 Subject: [PATCH 46/62] fix(h200): snapshot native server logs during runs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Atomically refresh the server log tarball while native multi-node jobs run so cancellation still leaves an uploadable artifact, including e2e workflows dispatched from main.\n\n中文:原生多节点任务运行期间以原子方式刷新服务日志压缩包,确保任务被取消时仍有可上传产物,也覆盖从 main 分派的 e2e 工作流。 --- runners/launch_h200-dgxc-slurm.sh | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index 54ff2a186b..f089c8362d 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -74,20 +74,28 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then exit 1 fi + snapshot_native_logs() { + local snapshot_path="$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" + local snapshot_tmp="${snapshot_path}.${BASHPID}.tmp" + tar czf "$snapshot_tmp" -C "$server_log_dir" . 2>/dev/null && + mv "$snapshot_tmp" "$snapshot_path" || true + } + server_step_pid="" + log_snapshot_pid="" cleanup_native_multinode() { local exit_code=$? trap - EXIT INT TERM - # Preserve a snapshot before waiting on Slurm: GitHub cancellation may - # forcibly terminate the launcher before the server step exits. - tar czf "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" \ - -C "$server_log_dir" . 2>/dev/null || true + if [[ -n "$log_snapshot_pid" ]]; then + kill "$log_snapshot_pid" 2>/dev/null || true + wait "$log_snapshot_pid" 2>/dev/null || true + fi + snapshot_native_logs if [[ -n "$server_step_pid" ]]; then kill "$server_step_pid" 2>/dev/null || true wait "$server_step_pid" 2>/dev/null || true fi - tar czf "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" \ - -C "$server_log_dir" . 2>/dev/null || true + snapshot_native_logs scancel "$job_id" 2>/dev/null || true exit "$exit_code" } @@ -157,6 +165,13 @@ if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then bash "$server_script" \ >"$server_log_dir/server.log" 2>&1 & server_step_pid=$! + ( + while kill -0 "$server_step_pid" 2>/dev/null; do + snapshot_native_logs + sleep 30 + done + ) & + log_snapshot_pid=$! for ((attempt = 1; attempt <= 720; attempt++)); do servers_ready=true From 724ad15d99dd5213e90830e797d23391d79dc6e2 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 02:54:16 -0500 Subject: [PATCH 47/62] fix(kimik3): reduce throughput prefill workspace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lower the throughput chunked-prefill token budget to 1024 after the c128 burst exhausted CUDA memory with two requests totaling 2048 scheduled tokens. Keep the default full model length and the full-context KV cache unchanged.\n\n中文:c128 突发测试中两个请求合计调度 2048 个 token 时耗尽 CUDA 显存,因此将吞吐配置的分块预填充 token 预算降至 1024;默认完整模型长度和完整上下文 KV cache 均保持不变。 --- 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 881376f273..d9364e8417 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1548,7 +1548,7 @@ kimik3-fp4-h200-vllm-agentic: - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" - "VLLM_GPU_MEMORY_UTILIZATION=0.875" - - "VLLM_MAX_NUM_BATCHED_TOKENS=2048" + - "VLLM_MAX_NUM_BATCHED_TOKENS=1024" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" From 8abfa19cba8d6831902668e811f3fd0751beb910 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 03:08:17 -0500 Subject: [PATCH 48/62] fix(kimik3): preserve throughput collective headroom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the throughput topology GPU memory utilization to 0.85 after the c128 burst showed a 2.82 GB collective allocation with insufficient free device memory. The 1024-token prefill profile still leaves 1.48M KV tokens at 0.875, so this preserves the full 1M context while reserving runtime workspace. 中文:将吞吐拓扑的 GPU 显存利用率降至 0.85。c128 突发测试显示,2.82 GB 的集合通信分配因设备可用显存不足而失败;1024-token 预填充配置在 0.875 下仍有 148 万 KV token,因此该调整在保留完整 100 万上下文能力的同时,为运行时工作区预留足够显存。 --- 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 d9364e8417..c4e1459a1a 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1547,7 +1547,7 @@ kimik3-fp4-h200-vllm-agentic: additional-settings: - "NATIVE_MULTINODE=1" - "VLLM_MOE_BACKEND=marlin" - - "VLLM_GPU_MEMORY_UTILIZATION=0.875" + - "VLLM_GPU_MEMORY_UTILIZATION=0.85" - "VLLM_MAX_NUM_BATCHED_TOKENS=1024" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" From 2c2d6ded8433355a87c2fd48609185e376a4287a Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 07:53:38 -0500 Subject: [PATCH 49/62] fix(kimik3): allow long throughput warmup drains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let the c64 and c128 AgentX cache-pressure requests drain for up to one hour before treating warmup as failed. The official c64 run kept making progress with a healthy server but exceeded the previous 30-minute client deadline. 中文:将 c64 和 c128 AgentX 缓存压力请求的预热排空时限延长至一小时。官方 c64 运行期间服务端保持健康且持续推进,但超过了原有 30 分钟客户端时限。 --- configs/nvidia-master.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index c4e1459a1a..b3dfbfee4d 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1549,6 +1549,7 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_MOE_BACKEND=marlin" - "VLLM_GPU_MEMORY_UTILIZATION=0.85" - "VLLM_MAX_NUM_BATCHED_TOKENS=1024" + - "AGENTIC_WARMUP_GRACE_PERIOD=3600" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" From 572b85b43d0aa36bd9db12025bdbe76595f41d2b Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 11:19:41 -0500 Subject: [PATCH 50/62] fix(kimik3): cap H200 throughput concurrency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep the verified c16 and c32 throughput points and remove the ineffective warmup-drain extension. Each DP replica reports only 1.16 full-context requests of KV capacity, while c64 and c128 fail to drain long AgentX requests without server errors. 中文:将 H200 吞吐量扫描限制在已验证通过的 c16 和 c32,并移除无效的预热排空超时延长。每个 DP 副本上报的 KV 容量仅相当于 1.16 个完整上下文请求;c64 和 c128 的 AgentX 长请求无法及时排空,但服务端未出现错误。 --- configs/nvidia-master.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index b3dfbfee4d..c2e1752f8f 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1537,7 +1537,7 @@ kimik3-fp4-h200-vllm-agentic: # Throughput-oriented: TP1/PP2 with DP16/EP16 across four H200 nodes. - spec-decoding: none kv-offloading: none - conc-list: [16, 32, 64, 128] + conc-list: [16, 32] prefill: num-worker: 16 tp: 1 @@ -1549,7 +1549,6 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_MOE_BACKEND=marlin" - "VLLM_GPU_MEMORY_UTILIZATION=0.85" - "VLLM_MAX_NUM_BATCHED_TOKENS=1024" - - "AGENTIC_WARMUP_GRACE_PERIOD=3600" - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" From caa2e206e0af26729e39fa27023347f3968f4377 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 12:38:34 -0500 Subject: [PATCH 51/62] fix(kimik3): use KV-safe throughput concurrency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Limit the DP16 throughput profile to c16, matching one full-context AgentX session per replica. The c32 retry completed 161 of 162 warmup requests but missed the drain deadline, confirming that two sessions per replica are flaky with only 1.16x full-context KV capacity. 中文:将 DP16 吞吐量配置限制为 c16,使每个副本仅承载一个完整上下文的 AgentX 会话。c32 重试在预热阶段完成了 162 个请求中的 161 个,但仍超过排空期限;在每个副本只有 1.16 倍完整上下文 KV 容量时,每副本两个会话存在不稳定性。 --- 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 c2e1752f8f..489617e2c5 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1537,7 +1537,7 @@ kimik3-fp4-h200-vllm-agentic: # Throughput-oriented: TP1/PP2 with DP16/EP16 across four H200 nodes. - spec-decoding: none kv-offloading: none - conc-list: [16, 32] + conc-list: [16] prefill: num-worker: 16 tp: 1 From 3e273968d2fccb3e53ffc0536cd3a77a9d5f1e2f Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 12:58:23 -0500 Subject: [PATCH 52/62] fix(kimik3): add throughput tensor parallel headroom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use TP2/PP2 with DP8/EP16 for the H200 throughput strategy after TP1/PP2 exhausted runtime memory on a full-context warmup request. Keep the four-node allocation and c16 validation point unchanged. 中文:将 H200 吞吐量策略调整为 TP2/PP2 + DP8/EP16。TP1/PP2 在全上下文预热请求中耗尽了运行时显存;本次修改保留四节点分配和 c16 验证点,同时通过张量并行为运行时预留显存余量。 --- configs/nvidia-master.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 489617e2c5..56119885f3 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1534,13 +1534,13 @@ kimik3-fp4-h200-vllm-agentic: pp: 2 ep: 8 dp-attn: true - # Throughput-oriented: TP1/PP2 with DP16/EP16 across four H200 nodes. + # Throughput-oriented: TP2/PP2 with DP8/EP16 across four H200 nodes. - spec-decoding: none kv-offloading: none conc-list: [16] prefill: - num-worker: 16 - tp: 1 + num-worker: 8 + tp: 2 pp: 2 ep: 16 dp-attn: true @@ -1554,7 +1554,7 @@ kimik3-fp4-h200-vllm-agentic: - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" decode: num-worker: 0 - tp: 1 + tp: 2 pp: 2 ep: 16 dp-attn: true From 2d0629d8690beb8dc4039be6c4ad3eb4c23a8400 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 17:25:54 -0500 Subject: [PATCH 53/62] refactor(kimik3): use srt-slurm direct vLLM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move H200 Kimi K3 multi-node orchestration into pinned srt-slurm direct-vLLM recipes while retaining the latency, balanced, and throughput profiles. Bundle all srt-slurm logs on normal exit, failure, and cancellation. 中文:将 H200 Kimi K3 多节点编排迁移到固定版本的 srt-slurm 直接 vLLM 配方,同时保留延迟、均衡和吞吐量三类配置。正常退出、失败和取消时均打包全部 srt-slurm 日志。 --- .../workflows/benchmark-multinode-tmpl.yml | 7 +- benchmarks/benchmark_lib.sh | 15 +- .../multi_node/agentic/kimik3_fp4_vllm.sh | 109 ------- ...200-tp2pp2-dp8ep16-throughput-agentic.yaml | 75 +++++ ...g-h200-tp4pp2-dp2ep8-balanced-agentic.yaml | 75 +++++ .../agg-h200-tp8pp2-latency-agentic.yaml | 74 +++++ configs/nvidia-master.yaml | 28 +- runners/launch_h200-dgxc-slurm.sh | 277 +++--------------- 8 files changed, 267 insertions(+), 393 deletions(-) delete mode 100755 benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh create mode 100644 benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml create mode 100644 benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml create mode 100644 benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml diff --git a/.github/workflows/benchmark-multinode-tmpl.yml b/.github/workflows/benchmark-multinode-tmpl.yml index 6ba39b2646..23f766c388 100644 --- a/.github/workflows/benchmark-multinode-tmpl.yml +++ b/.github/workflows/benchmark-multinode-tmpl.yml @@ -391,11 +391,8 @@ jobs: uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: multinode_server_logs_${{ env.RESULT_FILENAME }} - # Native launchers also leave the live directory as a cancellation - # fallback when GitHub interrupts tarball creation. - path: | - multinode_server_logs.tar.gz - multinode_server_logs/** + # multinode launchers package server logs into this tarball. + path: multinode_server_logs.tar.gz if-no-files-found: ignore - name: Upload agentic aggregated result diff --git a/benchmarks/benchmark_lib.sh b/benchmarks/benchmark_lib.sh index 3554f3c448..c5e6fb2c86 100644 --- a/benchmarks/benchmark_lib.sh +++ b/benchmarks/benchmark_lib.sh @@ -1766,20 +1766,7 @@ build_replay_cmd() { # DATASET_CONFIGURATION_TIMEOUT at startup. Bump it in lockstep. export AIPERF_SERVICE_PROFILE_CONFIGURE_TIMEOUT=1800 REPLAY_CMD="$AIPERF_CLI profile --scenario inferencex-agentx-mvp" - if declare -p AIPERF_ENDPOINT_URLS &>/dev/null; then - local endpoint_url - local -a endpoint_urls - IFS=',' read -r -a endpoint_urls <<< "$AIPERF_ENDPOINT_URLS" - for endpoint_url in "${endpoint_urls[@]}"; do - if [ -z "$endpoint_url" ] || [[ "$endpoint_url" == *[[:space:]]* ]]; then - echo "ERROR: AIPERF_ENDPOINT_URLS must be a comma-separated list of non-empty URLs" >&2 - return 1 - fi - REPLAY_CMD+=" --url $endpoint_url" - done - else - REPLAY_CMD+=" --url http://localhost:$PORT" - fi + REPLAY_CMD+=" --url http://localhost:$PORT" REPLAY_CMD+=" --endpoint /v1/chat/completions" REPLAY_CMD+=" --endpoint-type chat" REPLAY_CMD+=" --streaming" diff --git a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh b/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh deleted file mode 100755 index 97b326b2a9..0000000000 --- a/benchmarks/multi_node/agentic/kimik3_fp4_vllm.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -set -x - -# Scheduler- and hardware-independent aggregated vLLM server for Kimi K3 MXFP4. -# -# The benchmark configuration selects one of the official aggregate strategies: -# https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200 -# -# The runner supplies node ranks, rendezvous, and local GPU count. -# This script only translates the requested TP/EP/DP topology into vLLM flags. - -WORLD_SIZE=$((MULTINODE_NODE_COUNT * MULTINODE_GPUS_PER_NODE)) -read -r -a CONCURRENCIES <<< "$CONC_LIST" -MAX_CONCURRENCY=0 -for concurrency in "${CONCURRENCIES[@]}"; do - if [ "$concurrency" -gt "$MAX_CONCURRENCY" ]; then - MAX_CONCURRENCY="$concurrency" - fi -done -MAX_NUM_SEQS="$MAX_CONCURRENCY" -if [[ "$PREFILL_DP_ATTN" == "true" ]]; then - MAX_NUM_SEQS=$(((MAX_CONCURRENCY + PREFILL_NUM_WORKERS - 1) / PREFILL_NUM_WORKERS)) -fi - -export VLLM_ENGINE_READY_TIMEOUT_S=7200 -export VLLM_USE_V2_MODEL_RUNNER=1 -if [ "$PREFILL_PP_SIZE" -gt 1 ]; then - export VLLM_USE_V2_MODEL_RUNNER=0 -fi -export PYTHONNOUSERSITE=1 - -LOAD_FORMAT=auto -if [ "$PREFILL_PP_SIZE" -gt 1 ]; then - LOAD_FORMAT=fastsafetensors -fi - -VLLM_CMD=( - vllm serve "$MODEL_PATH" - --served-model-name "$MODEL" - --host 0.0.0.0 - --port "$PORT" - --trust-remote-code - --load-format "$LOAD_FORMAT" - --moe-backend "$VLLM_MOE_BACKEND" - --gpu-memory-utilization "$VLLM_GPU_MEMORY_UTILIZATION" - --max-num-batched-tokens "$VLLM_MAX_NUM_BATCHED_TOKENS" - --enable-auto-tool-choice - --tool-call-parser kimi_k3 - --reasoning-parser kimi_k3 - --language-model-only - --max-num-seqs "$MAX_NUM_SEQS" -) - -if [ "$PREFILL_PP_SIZE" -gt 1 ]; then - VLLM_CMD+=(--attention-backend FLASHMLA) -fi -if [[ "$VLLM_DISABLE_FLASHINFER_AUTOTUNE" == "1" ]]; then - VLLM_CMD+=(--no-enable-flashinfer-autotune) -fi -if [[ "$VLLM_DISABLE_CUSTOM_ALL_REDUCE" == "1" ]]; then - VLLM_CMD+=(--disable-custom-all-reduce) -fi -if [[ "$PREFILL_DP_ATTN" == "true" ]]; then - LOCAL_DATA_PARALLEL_SIZE=$((MULTINODE_GPUS_PER_NODE / (PREFILL_TP * PREFILL_PP_SIZE))) - VLLM_CMD+=( - --tensor-parallel-size "$PREFILL_TP" - --pipeline-parallel-size "$PREFILL_PP_SIZE" - --data-parallel-size "$PREFILL_NUM_WORKERS" - --data-parallel-size-local "$LOCAL_DATA_PARALLEL_SIZE" - --data-parallel-address "$MULTINODE_MASTER_ADDR" - --data-parallel-start-rank "$((MULTINODE_NODE_RANK * LOCAL_DATA_PARALLEL_SIZE))" - --data-parallel-hybrid-lb - ) - if [ "$PREFILL_EP" -gt 1 ]; then - VLLM_CMD+=(--enable-expert-parallel) - fi -elif [[ "$PREFILL_DP_ATTN" == "false" ]]; then - if [ "$((PREFILL_TP * PREFILL_PP_SIZE))" -ne "$WORLD_SIZE" ]; then - echo "Cross-node TPxPP must match the allocated world size ($WORLD_SIZE)" >&2 - exit 1 - fi - - VLLM_CMD+=( - --tensor-parallel-size "$PREFILL_TP" - --pipeline-parallel-size "$PREFILL_PP_SIZE" - --nnodes "$MULTINODE_NODE_COUNT" - --node-rank "$MULTINODE_NODE_RANK" - --master-addr "$MULTINODE_MASTER_ADDR" - ) - if [ "$PREFILL_EP" -gt 1 ]; then - VLLM_CMD+=(--enable-expert-parallel) - fi - if [[ "$VLLM_DISABLE_FUSED_ALLREDUCE_RMS" == "1" ]]; then - VLLM_CMD+=(-cc.pass_config.fuse_allreduce_rms=False) - fi - if [ "$MULTINODE_NODE_RANK" -gt 0 ]; then - VLLM_CMD+=(--headless) - fi -else - echo "PREFILL_DP_ATTN must be true or false, got: $PREFILL_DP_ATTN" >&2 - exit 1 -fi - -printf 'Kimi K3 rank %s command: ' "$MULTINODE_NODE_RANK" -printf '%q ' "${VLLM_CMD[@]}" -printf '\n' - -exec "${VLLM_CMD[@]}" diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml new file mode 100644 index 0000000000..368b1012e5 --- /dev/null +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml @@ -0,0 +1,75 @@ +name: "kimik3-vllm-agg-h200-tp2pp2-dp8ep16-throughput-agentic" + +model: + path: "kimik3" + container: "vllm/vllm-openai:kimi-k3" + precision: "fp4" + +dynamo: + install: false + +slurm: + time_limit: "8:00:00" + +health_check: + max_attempts: 720 + interval_seconds: 10 + +resources: + gpu_type: "h200" + gpus_per_node: 8 + agg_nodes: 4 + agg_workers: 1 + gpus_per_agg: 32 + +frontend: + type: vllm + enable_multiple_frontends: false + +backend: + type: vllm + connector: null + aggregated_environment: + GLOO_SOCKET_IFNAME: "eth0" + NCCL_SOCKET_IFNAME: "eth0" + NCCL_CUMEM_ENABLE: "1" + PYTHONNOUSERSITE: "1" + VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" + VLLM_ENGINE_READY_TIMEOUT_S: "7200" + VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" + VLLM_USE_V2_MODEL_RUNNER: "0" + vllm_config: + aggregated: + served-model-name: "moonshotai/Kimi-K3" + tensor-parallel-size: 2 + pipeline-parallel-size: 2 + data-parallel-size: 8 + enable-expert-parallel: true + trust-remote-code: true + load-format: fastsafetensors + moe-backend: marlin + attention-backend: FLASHMLA + gpu-memory-utilization: 0.85 + max-num-seqs: 2 + max-num-batched-tokens: 1024 + no-enable-flashinfer-autotune: true + disable-custom-all-reduce: true + enable-auto-tool-choice: true + tool-call-parser: kimi_k3 + reasoning-parser: kimi_k3 + language-model-only: true + +srun_options: + 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" + IS_MULTINODE: "true" + AIPERF_DATASET_MMAP_CACHE_DIR: "/aiperf_mmap_cache" + HF_HUB_CACHE: "/hf_hub_cache" + WEKA_LOADER_OVERRIDE: "semianalysis_cc_traces_weka_062126" diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml new file mode 100644 index 0000000000..8aac76543e --- /dev/null +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml @@ -0,0 +1,75 @@ +name: "kimik3-vllm-agg-h200-tp4pp2-dp2ep8-balanced-agentic" + +model: + path: "kimik3" + container: "vllm/vllm-openai:kimi-k3" + precision: "fp4" + +dynamo: + install: false + +slurm: + time_limit: "8:00:00" + +health_check: + max_attempts: 720 + interval_seconds: 10 + +resources: + gpu_type: "h200" + gpus_per_node: 8 + agg_nodes: 2 + agg_workers: 1 + gpus_per_agg: 16 + +frontend: + type: vllm + enable_multiple_frontends: false + +backend: + type: vllm + connector: null + aggregated_environment: + GLOO_SOCKET_IFNAME: "eth0" + NCCL_SOCKET_IFNAME: "eth0" + NCCL_CUMEM_ENABLE: "1" + PYTHONNOUSERSITE: "1" + VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" + VLLM_ENGINE_READY_TIMEOUT_S: "7200" + VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" + VLLM_USE_V2_MODEL_RUNNER: "0" + vllm_config: + aggregated: + served-model-name: "moonshotai/Kimi-K3" + tensor-parallel-size: 4 + pipeline-parallel-size: 2 + data-parallel-size: 2 + enable-expert-parallel: true + trust-remote-code: true + load-format: fastsafetensors + moe-backend: marlin + attention-backend: FLASHMLA + gpu-memory-utilization: 0.90 + max-num-seqs: 16 + max-num-batched-tokens: 4096 + no-enable-flashinfer-autotune: true + disable-custom-all-reduce: true + enable-auto-tool-choice: true + tool-call-parser: kimi_k3 + reasoning-parser: kimi_k3 + language-model-only: true + +srun_options: + 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" + IS_MULTINODE: "true" + AIPERF_DATASET_MMAP_CACHE_DIR: "/aiperf_mmap_cache" + HF_HUB_CACHE: "/hf_hub_cache" + WEKA_LOADER_OVERRIDE: "semianalysis_cc_traces_weka_062126" diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml new file mode 100644 index 0000000000..00ed795e6f --- /dev/null +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml @@ -0,0 +1,74 @@ +name: "kimik3-vllm-agg-h200-tp8pp2-latency-agentic" + +model: + path: "kimik3" + container: "vllm/vllm-openai:kimi-k3" + precision: "fp4" + +dynamo: + install: false + +slurm: + time_limit: "8:00:00" + +health_check: + max_attempts: 720 + interval_seconds: 10 + +resources: + gpu_type: "h200" + gpus_per_node: 8 + agg_nodes: 2 + agg_workers: 1 + gpus_per_agg: 16 + +frontend: + type: vllm + enable_multiple_frontends: false + +backend: + type: vllm + connector: null + aggregated_environment: + GLOO_SOCKET_IFNAME: "eth0" + NCCL_SOCKET_IFNAME: "eth0" + NCCL_CUMEM_ENABLE: "1" + PYTHONNOUSERSITE: "1" + VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" + VLLM_ENGINE_READY_TIMEOUT_S: "7200" + VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" + VLLM_USE_V2_MODEL_RUNNER: "0" + vllm_config: + aggregated: + served-model-name: "moonshotai/Kimi-K3" + tensor-parallel-size: 8 + pipeline-parallel-size: 2 + trust-remote-code: true + load-format: fastsafetensors + moe-backend: marlin + attention-backend: FLASHMLA + gpu-memory-utilization: 0.95 + max-num-seqs: 8 + max-num-batched-tokens: 4096 + compilation-config: '{"pass_config":{"fuse_allreduce_rms":false}}' + no-enable-flashinfer-autotune: true + disable-custom-all-reduce: true + enable-auto-tool-choice: true + tool-call-parser: kimi_k3 + reasoning-parser: kimi_k3 + language-model-only: true + +srun_options: + 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" + IS_MULTINODE: "true" + AIPERF_DATASET_MMAP_CACHE_DIR: "/aiperf_mmap_cache" + HF_HUB_CACHE: "/hf_hub_cache" + WEKA_LOADER_OVERRIDE: "semianalysis_cc_traces_weka_062126" diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 56119885f3..e96b461614 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1471,8 +1471,8 @@ kimik2.5-int4-h200-vllm-agentic: # These are the three aggregated strategies from the official H200 # recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): # multi-node TP is latency-oriented, TEP is balanced, and DEP is -# throughput-oriented. The runner owns Slurm/Pyxis; the in-container Kimi -# entrypoint only receives rank and rendezvous information. +# throughput-oriented. The H200 runner supplies cluster paths while +# srt-slurm owns allocation, direct vLLM startup, readiness, and log capture. # P/D disaggregation is intentionally deferred. kimik3-fp4-h200-vllm-agentic: image: vllm/vllm-openai:kimi-k3 @@ -1497,13 +1497,7 @@ kimik3-fp4-h200-vllm-agentic: ep: 1 dp-attn: false additional-settings: - - "NATIVE_MULTINODE=1" - - "VLLM_MOE_BACKEND=marlin" - - "VLLM_GPU_MEMORY_UTILIZATION=0.95" - - "VLLM_MAX_NUM_BATCHED_TOKENS=4096" - - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml" decode: num-worker: 0 tp: 8 @@ -1521,13 +1515,7 @@ kimik3-fp4-h200-vllm-agentic: ep: 8 dp-attn: true additional-settings: - - "NATIVE_MULTINODE=1" - - "VLLM_MOE_BACKEND=marlin" - - "VLLM_GPU_MEMORY_UTILIZATION=0.90" - - "VLLM_MAX_NUM_BATCHED_TOKENS=4096" - - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml" decode: num-worker: 0 tp: 4 @@ -1545,13 +1533,7 @@ kimik3-fp4-h200-vllm-agentic: ep: 16 dp-attn: true additional-settings: - - "NATIVE_MULTINODE=1" - - "VLLM_MOE_BACKEND=marlin" - - "VLLM_GPU_MEMORY_UTILIZATION=0.85" - - "VLLM_MAX_NUM_BATCHED_TOKENS=1024" - - "VLLM_DISABLE_FLASHINFER_AUTOTUNE=1" - - "VLLM_DISABLE_CUSTOM_ALL_REDUCE=1" - - "VLLM_DISABLE_FUSED_ALLREDUCE_RMS=1" + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml" decode: num-worker: 0 tp: 2 diff --git a/runners/launch_h200-dgxc-slurm.sh b/runners/launch_h200-dgxc-slurm.sh index f089c8362d..29c77b13cd 100755 --- a/runners/launch_h200-dgxc-slurm.sh +++ b/runners/launch_h200-dgxc-slurm.sh @@ -7,219 +7,7 @@ SLURM_ACCOUNT="sa-shared" set -x -# Native multi-node vLLM: keep Slurm/Pyxis on the host and pass only rank and -# rendezvous information to the hardware-independent benchmark entrypoint. -if [[ "$IS_MULTINODE" == "true" && "$NATIVE_MULTINODE" == "1" ]]; then - if [[ "$IS_AGENTIC" != "1" || "$FRAMEWORK" != "vllm" ]]; then - echo "Native multi-node H200 currently supports AgentX vLLM jobs" >&2 - exit 1 - fi - - case "$MODEL_PREFIX/$PRECISION" in - kimik3/fp4) - model_host_path="/models/gharunners/hf-hub-cache/Kimi-K3" - export MODEL_PATH="/models/hf-hub-cache/Kimi-K3" - ;; - *) - echo "No native multi-node model mapping for $MODEL_PREFIX/$PRECISION on H200 DGXC" >&2 - exit 1 - ;; - esac - - hf_cache_host_path="/models/gharunners/hf-hub-cache" - hf_cache_container_path="/models/hf-hub-cache" - aiperf_cache_host_path="/home/sa-shared/gharunners/ai-perf-cache" - image_cache_dir="/data/gharunners/containers" - server_log_dir="$GITHUB_WORKSPACE/multinode_server_logs" - gpus_per_node=8 - gpu_count=$((PREFILL_NUM_WORKERS * PREFILL_TP * PREFILL_PP_SIZE)) - if (( gpu_count % gpus_per_node != 0 )); then - echo "Native multi-node GPU count ($gpu_count) must use full 8xH200 nodes" >&2 - exit 1 - fi - node_count=$((gpu_count / gpus_per_node)) - server_script="benchmarks/multi_node/${SCENARIO_SUBDIR}${MODEL_PREFIX}_${PRECISION}_${FRAMEWORK}.sh" - client_script="benchmarks/multi_node/agentic_srt.sh" - squash_file="$image_cache_dir/$(echo "$IMAGE" | sed 's/[\/:@#]/_/g').sqsh" - lock_file="${squash_file}.lock" - container_mounts="$GITHUB_WORKSPACE:/workspace,$hf_cache_host_path:$hf_cache_container_path,$aiperf_cache_host_path:/aiperf_mmap_cache,/usr/bin/git:/usr/bin/git,/usr/lib/git-core:/usr/lib/git-core" - - if [[ ! -d "$model_host_path" || ! -f "$server_script" ]]; then - echo "Missing model or benchmark entrypoint: $model_host_path / $server_script" >&2 - exit 1 - fi - mkdir -p "$aiperf_cache_host_path" "$image_cache_dir" "$server_log_dir" - - export PORT=8888 - export HF_HUB_CACHE="$hf_cache_container_path" - export AIPERF_DATASET_MMAP_CACHE_DIR="/aiperf_mmap_cache" - export INFMAX_CONTAINER_WORKSPACE="/workspace" - export RESULT_DIR="/workspace/LOGS/agentic" - export GLOO_SOCKET_IFNAME=eth0 - export NCCL_SOCKET_IFNAME=eth0 - - salloc \ - --partition="$SLURM_PARTITION" \ - --account="$SLURM_ACCOUNT" \ - --nodes="$node_count" \ - --ntasks-per-node=1 \ - --gres="gpu:$gpus_per_node" \ - --exclusive \ - --time=240 \ - --no-shell \ - --job-name="$RUNNER_NAME" - job_id=$(squeue --name="$RUNNER_NAME" -u "$USER" -h -o %A | sed -n '1p') - if [[ -z "$job_id" ]]; then - echo "Failed to resolve native multi-node Slurm allocation" >&2 - exit 1 - fi - - snapshot_native_logs() { - local snapshot_path="$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" - local snapshot_tmp="${snapshot_path}.${BASHPID}.tmp" - tar czf "$snapshot_tmp" -C "$server_log_dir" . 2>/dev/null && - mv "$snapshot_tmp" "$snapshot_path" || true - } - - server_step_pid="" - log_snapshot_pid="" - cleanup_native_multinode() { - local exit_code=$? - trap - EXIT INT TERM - if [[ -n "$log_snapshot_pid" ]]; then - kill "$log_snapshot_pid" 2>/dev/null || true - wait "$log_snapshot_pid" 2>/dev/null || true - fi - snapshot_native_logs - if [[ -n "$server_step_pid" ]]; then - kill "$server_step_pid" 2>/dev/null || true - wait "$server_step_pid" 2>/dev/null || true - fi - snapshot_native_logs - scancel "$job_id" 2>/dev/null || true - exit "$exit_code" - } - trap cleanup_native_multinode EXIT - trap 'exit 130' INT - trap 'exit 143' TERM - - allocated_nodelist=$(squeue -j "$job_id" -h -o %N) - allocated_nodes=$(scontrol show hostnames "$allocated_nodelist") - # Slurm task rank order is not guaranteed to match scontrol's hostname order. - head_node=$( - srun \ - --jobid="$job_id" \ - --nodes="$node_count" \ - --ntasks="$node_count" \ - --ntasks-per-node=1 \ - bash -c 'if [[ "$SLURM_PROCID" == "0" ]]; then hostname; fi' - ) - if [[ -z "$head_node" ]]; then - echo "Failed to resolve native multi-node head node" >&2 - exit 1 - fi - server_nodes="$head_node" - if [[ "$PREFILL_DP_ATTN" == "true" ]]; then - server_nodes="$allocated_nodes" - fi - server_urls=() - metrics_urls=() - for server_node in $server_nodes; do - server_urls+=("http://$server_node:$PORT") - metrics_urls+=("http://$server_node:$PORT/metrics") - done - AIPERF_ENDPOINT_URLS=$(IFS=,; echo "${server_urls[*]}") - AIPERF_SERVER_METRICS_URLS=$(IFS=,; echo "${metrics_urls[*]}") - export AIPERF_ENDPOINT_URLS AIPERF_SERVER_METRICS_URLS - - srun --jobid="$job_id" --nodes=1 --ntasks=1 --nodelist="$head_node" bash -c " - export ENROOT_CACHE_PATH=\$HOME/.cache/enroot - mkdir -p \$ENROOT_CACHE_PATH - exec 9>'$lock_file' - flock -w 1800 9 - if ! unsquashfs -l '$squash_file' >/dev/null 2>&1; then - rm -f '$squash_file' - enroot import -o '$squash_file' 'docker://${IMAGE//#//}' - fi - " - - export MULTINODE_NODE_COUNT="$node_count" - export MULTINODE_GPUS_PER_NODE="$gpus_per_node" - export MULTINODE_MASTER_ADDR="$head_node" - - # shellcheck disable=SC2016 # SLURM_PROCID is created inside each srun task. - srun \ - --jobid="$job_id" \ - --nodes="$node_count" \ - --ntasks="$node_count" \ - --ntasks-per-node=1 \ - --kill-on-bad-exit=1 \ - --container-image="$squash_file" \ - --container-mounts="$container_mounts" \ - --no-container-mount-home \ - --container-remap-root \ - --container-workdir=/workspace \ - --no-container-entrypoint \ - --export=ALL \ - bash -c 'export MULTINODE_NODE_RANK="$SLURM_PROCID"; exec bash "$1"' \ - bash "$server_script" \ - >"$server_log_dir/server.log" 2>&1 & - server_step_pid=$! - ( - while kill -0 "$server_step_pid" 2>/dev/null; do - snapshot_native_logs - sleep 30 - done - ) & - log_snapshot_pid=$! - - for ((attempt = 1; attempt <= 720; attempt++)); do - servers_ready=true - for server_url in "${server_urls[@]}"; do - if ! curl --output /dev/null --silent --fail "$server_url/health"; then - servers_ready=false - break - fi - done - if [[ "$servers_ready" == "true" ]]; then - break - fi - if ! kill -0 "$server_step_pid" 2>/dev/null; then - echo "Native multi-node server exited before becoming ready" >&2 - tail -n 200 "$server_log_dir/server.log" >&2 || true - exit 1 - fi - if grep -q "Engine core initialization failed" "$server_log_dir/server.log"; then - echo "Native multi-node engine failed before becoming ready" >&2 - tail -n 200 "$server_log_dir/server.log" >&2 - exit 1 - fi - sleep 10 - done - if (( attempt > 720 )); then - echo "Native multi-node server did not become ready within 7200 seconds" >&2 - exit 1 - fi - - set +e - srun \ - --jobid="$job_id" \ - --overlap \ - --nodes=1 \ - --ntasks=1 \ - --nodelist="$head_node" \ - --container-image="$squash_file" \ - --container-mounts="$container_mounts" \ - --no-container-mount-home \ - --container-remap-root \ - --container-workdir=/workspace \ - --no-container-entrypoint \ - --export=ALL,MULTINODE_NODE_RANK=0 \ - bash "$client_script" - client_rc=$? - set -e - exit "$client_rc" -fi +source "$(dirname "${BASH_SOURCE[0]}")/slurm_utils.sh" if [[ "$IS_MULTINODE" == "true" ]]; then @@ -243,8 +31,16 @@ if [[ "$IS_MULTINODE" == "true" ]]; then echo "Unsupported model prefix/precision for dynamo-trt: $MODEL_PREFIX/$PRECISION" exit 1 fi + elif [[ $FRAMEWORK == "vllm" ]]; then + if [[ $MODEL_PREFIX == "kimik3" && $PRECISION == "fp4" ]]; then + export MODEL_PATH="/models/gharunners/hf-hub-cache/Kimi-K3" + export SRT_SLURM_MODEL_PREFIX="kimik3" + else + echo "Unsupported model prefix/precision for vllm: $MODEL_PREFIX/$PRECISION" + exit 1 + fi else - echo "Unsupported framework: $FRAMEWORK. Supported frameworks are: dynamo-trt, dynamo-sglang" + echo "Unsupported framework: $FRAMEWORK. Supported frameworks are: dynamo-trt, dynamo-sglang, vllm" exit 1 fi @@ -255,8 +51,14 @@ if [[ "$IS_MULTINODE" == "true" ]]; then rm -rf "$SRT_REPO_DIR" fi - # TODO(CJQ): make first class upon srt-slurm upstream refactor - if [[ "$IS_AGENTIC" == "1" ]]; then + if [[ $IS_AGENTIC == "1" && $FRAMEWORK == "vllm" && $MODEL_PREFIX == "kimik3" ]]; then + git clone https://github.com/functionstackx/srt-slurm-nv.git "$SRT_REPO_DIR" + cd "$SRT_REPO_DIR" + git checkout df5baa93f4caf5169dea2a4236ad2cc742fe40e7 + mkdir -p recipes/vllm/kimi-k3/agentic + cp -rT "$GITHUB_WORKSPACE/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic" \ + recipes/vllm/kimi-k3/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 @@ -291,6 +93,9 @@ if [[ "$IS_MULTINODE" == "true" ]]; then # TRT-LLM container mapping - convert IMAGE to srt-slurm format (nvcr.io/ -> nvcr.io#) CONTAINER_KEY=$(echo "$IMAGE" | sed 's|nvcr.io/|nvcr.io#|') SQUASH_FILE="/data/containers/$(echo "$IMAGE" | sed 's|nvcr.io/||' | sed 's/[\/:@#]/+/g').sqsh" + elif [[ $FRAMEWORK == "vllm" ]]; then + CONTAINER_KEY="$IMAGE" + SQUASH_FILE="/data/gharunners/containers/$(echo "$IMAGE" | sed 's/[\/:@#]/_/g').sqsh" fi export ISL="$ISL" @@ -299,6 +104,15 @@ if [[ "$IS_MULTINODE" == "true" ]]; then # Create srtslurm.yaml for srtctl (used by both frameworks) SRTCTL_ROOT="${GITHUB_WORKSPACE}/${SRT_REPO_DIR}" + DEFAULT_MOUNTS_BLOCK="" + if [[ "$IS_AGENTIC" == "1" ]]; then + AIPERF_MMAP_CACHE_HOST_PATH="/home/sa-shared/gharunners/ai-perf-cache" + HF_HUB_CACHE_HOST_PATH="/models/gharunners/hf-hub-cache" + mkdir -p "$AIPERF_MMAP_CACHE_HOST_PATH" + DEFAULT_MOUNTS_BLOCK="default_mounts: + ${AIPERF_MMAP_CACHE_HOST_PATH}: /aiperf_mmap_cache + ${HF_HUB_CACHE_HOST_PATH}: /hf_hub_cache" + fi echo "Creating srtslurm.yaml configuration..." cat > srtslurm.yaml </dev/null || true; exit "$rc"' EXIT INT TERM HUP - # Wait for log file to appear (also check job is still alive) - while ! ls "$LOG_FILE" &>/dev/null; do - if ! squeue -j "$JOB_ID" --noheader 2>/dev/null | grep -q "$JOB_ID"; then - echo "ERROR: Job $JOB_ID failed before creating log file" - scontrol show job "$JOB_ID" - exit 1 - fi - echo "Waiting for JOB_ID $JOB_ID to begin and $LOG_FILE to appear..." - sleep 5 - done - - # Poll for job completion in background - ( - while squeue -j "$JOB_ID" --noheader 2>/dev/null | grep -q "$JOB_ID"; do - sleep 10 - done - ) & - POLL_PID=$! - - echo "Tailing LOG_FILE: $LOG_FILE" - - # Stream the log file until job completes (-F follows by name, polls instead of inotify for NFS) - tail -F -s 2 -n+1 "$LOG_FILE" --pid=$POLL_PID 2>/dev/null - - wait $POLL_PID + stream_slurm_job_log "$JOB_ID" "$LOG_FILE" || exit 1 set -x @@ -408,7 +201,7 @@ EOF echo "Found logs directory: $LOGS_DIR" cp -r "$LOGS_DIR" "$GITHUB_WORKSPACE/LOGS" - tar czf "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" -C "$LOGS_DIR" . + bundle_server_logs "$LOGS_DIR" "$GITHUB_WORKSPACE/multinode_server_logs.tar.gz" if [[ "${EVAL_ONLY:-false}" != "true" ]]; then # Find all result subdirectories From 8ee6ab3fc68c8749f47d04bee6ba841b8cbfbdd8 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 17:34:10 -0500 Subject: [PATCH 54/62] fix(kimik3): disable SM100 tail fusion on H200 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the K3 latent-MoE tail fusion environment setting from all H200 srt-slurm recipes. Live validation showed vLLM rejects this SM100-only optimization on H200 before weight loading. 中文:从所有 H200 srt-slurm 配方中移除 K3 潜在混合专家尾部融合环境变量。实际验证表明,该优化仅支持 SM100,vLLM 在 H200 上会在权重加载前拒绝启动。 --- .../agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml | 1 - .../kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml | 1 - .../vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml | 1 - 3 files changed, 3 deletions(-) diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml index 368b1012e5..a0934d13ac 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml @@ -34,7 +34,6 @@ backend: NCCL_SOCKET_IFNAME: "eth0" NCCL_CUMEM_ENABLE: "1" PYTHONNOUSERSITE: "1" - VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" VLLM_USE_V2_MODEL_RUNNER: "0" diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml index 8aac76543e..9edf3b8316 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml @@ -34,7 +34,6 @@ backend: NCCL_SOCKET_IFNAME: "eth0" NCCL_CUMEM_ENABLE: "1" PYTHONNOUSERSITE: "1" - VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" VLLM_USE_V2_MODEL_RUNNER: "0" diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml index 00ed795e6f..73895caeb3 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml @@ -34,7 +34,6 @@ backend: NCCL_SOCKET_IFNAME: "eth0" NCCL_CUMEM_ENABLE: "1" PYTHONNOUSERSITE: "1" - VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" VLLM_USE_V2_MODEL_RUNNER: "0" From 7ccb00e7ec9c45ef2d5d04042448de84819143d3 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 28 Jul 2026 17:47:28 -0500 Subject: [PATCH 55/62] perf(kimik3): add high-concurrency KV offload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable prefix caching for the H200 AgentX recipes and add c32, c64, and c128 DEP points backed by vLLM SimpleCPUOffloadConnector. Size the host tier from the standard 80% runner DRAM budget at 154.25 GB per rank. 中文:为 H200 AgentX 配方启用前缀缓存,并新增由 vLLM SimpleCPUOffloadConnector 支持的 c32、c64 和 c128 DEP 测试点。按照 runner 标准的 80% 主机内存预算,为每个 rank 分配 154.25 GB 的主机 KV 缓存。 --- ...200-tp2pp2-dp8ep16-throughput-agentic.yaml | 1 + ...00-tp2pp2-dp8ep16-vllm-simple-agentic.yaml | 77 +++++++++++++++++++ ...g-h200-tp4pp2-dp2ep8-balanced-agentic.yaml | 1 + .../agg-h200-tp8pp2-latency-agentic.yaml | 1 + configs/nvidia-master.yaml | 22 +++++- perf-changelog.yaml | 2 +- 6 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml index a0934d13ac..657eb3361b 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml @@ -51,6 +51,7 @@ backend: gpu-memory-utilization: 0.85 max-num-seqs: 2 max-num-batched-tokens: 1024 + enable-prefix-caching: true no-enable-flashinfer-autotune: true disable-custom-all-reduce: true enable-auto-tool-choice: true diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml new file mode 100644 index 0000000000..300c675a23 --- /dev/null +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml @@ -0,0 +1,77 @@ +name: "kimik3-vllm-agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic" + +model: + path: "kimik3" + container: "vllm/vllm-openai:kimi-k3" + precision: "fp4" + +dynamo: + install: false + +slurm: + time_limit: "8:00:00" + +health_check: + max_attempts: 720 + interval_seconds: 10 + +resources: + gpu_type: "h200" + gpus_per_node: 8 + agg_nodes: 4 + agg_workers: 1 + gpus_per_agg: 32 + +frontend: + type: vllm + enable_multiple_frontends: false + +backend: + type: vllm + connector: null + aggregated_environment: + GLOO_SOCKET_IFNAME: "eth0" + NCCL_SOCKET_IFNAME: "eth0" + NCCL_CUMEM_ENABLE: "1" + PYTHONHASHSEED: "42" + PYTHONNOUSERSITE: "1" + VLLM_ENGINE_READY_TIMEOUT_S: "7200" + VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" + VLLM_USE_V2_MODEL_RUNNER: "0" + vllm_config: + aggregated: + served-model-name: "moonshotai/Kimi-K3" + tensor-parallel-size: 2 + pipeline-parallel-size: 2 + data-parallel-size: 8 + enable-expert-parallel: true + trust-remote-code: true + load-format: fastsafetensors + moe-backend: marlin + attention-backend: FLASHMLA + gpu-memory-utilization: 0.85 + max-num-seqs: 16 + max-num-batched-tokens: 1024 + enable-prefix-caching: true + kv-transfer-config: '{"kv_connector":"SimpleCPUOffloadConnector","kv_role":"kv_both","kv_connector_extra_config":{"cpu_bytes_to_use_per_rank":154250000000,"lazy_offload":false}}' + no-enable-flashinfer-autotune: true + disable-custom-all-reduce: true + enable-auto-tool-choice: true + tool-call-parser: kimi_k3 + reasoning-parser: kimi_k3 + language-model-only: true + +srun_options: + 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" + IS_MULTINODE: "true" + AIPERF_DATASET_MMAP_CACHE_DIR: "/aiperf_mmap_cache" + HF_HUB_CACHE: "/hf_hub_cache" + WEKA_LOADER_OVERRIDE: "semianalysis_cc_traces_weka_062126" diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml index 9edf3b8316..b832e6d6f0 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml @@ -51,6 +51,7 @@ backend: gpu-memory-utilization: 0.90 max-num-seqs: 16 max-num-batched-tokens: 4096 + enable-prefix-caching: true no-enable-flashinfer-autotune: true disable-custom-all-reduce: true enable-auto-tool-choice: true diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml index 73895caeb3..9768e11dfd 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml @@ -49,6 +49,7 @@ backend: gpu-memory-utilization: 0.95 max-num-seqs: 8 max-num-batched-tokens: 4096 + enable-prefix-caching: true compilation-config: '{"pass_config":{"fuse_allreduce_rms":false}}' no-enable-flashinfer-autotune: true disable-custom-all-reduce: true diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index e96b461614..a9bc20749f 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1485,7 +1485,8 @@ kimik3-fp4-h200-vllm-agentic: disagg: false scenarios: agentic-coding: - - search-space: + - dram-utilization: 0.80 + search-space: # Latency-oriented: one TP8/PP2 engine spanning two H200 nodes. - spec-decoding: none kv-offloading: none @@ -1540,6 +1541,25 @@ kimik3-fp4-h200-vllm-agentic: pp: 2 ep: 16 dp-attn: true + # High-concurrency DEP with vLLM's host-DRAM KV tier. + - spec-decoding: none + kv-offloading: dram + kv-offload-backend: { name: vllm-simple } + conc-list: [32, 64, 128] + prefill: + num-worker: 8 + tp: 2 + pp: 2 + ep: 16 + dp-attn: true + additional-settings: + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml" + decode: + num-worker: 0 + tp: 2 + pp: 2 + ep: 16 + dp-attn: true # NOTE: At the time of submission, https://docs.vllm.ai/projects/recipes/en/latest/moonshotai/Kimi-K2.5.html # does not have a B300-specific recipe, so this config reuses the existing diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 525e60eea7..8fa8318c36 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5195,5 +5195,5 @@ - config-keys: - kimik3-fp4-h200-vllm-agentic description: - - "Add Day-0 Kimi K3 FP4 AgentX performance coverage and H200 recipes based on the official vLLM recipe" + - "Add Day-0 Kimi K3 FP4 AgentX H200 performance recipes based on the official vLLM recipe, including vLLM simple KV offload for high-concurrency DEP" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 From ec22d4bf4b0cd9b178196e74e9d9b8ef5ab55687 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Wed, 29 Jul 2026 00:06:51 -0500 Subject: [PATCH 56/62] perf(kimik3): densify H200 concurrency sweep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expand the latency, balanced, GPU DEP, and vLLM simple offload ladders to 49 points concentrated around concurrency 8-24, with the frontier capped at 32. 中文:将延迟、均衡、GPU DEP 和 vLLM simple KV 卸载的并发扫描扩展为 49 个点,重点覆盖并发 8–24,并将最高并发限制为 32。 --- configs/nvidia-master.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index a9bc20749f..06dd309f68 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1490,7 +1490,7 @@ kimik3-fp4-h200-vllm-agentic: # Latency-oriented: one TP8/PP2 engine spanning two H200 nodes. - spec-decoding: none kv-offloading: none - conc-list: [1, 2, 4, 8] + conc-list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] prefill: num-worker: 1 tp: 8 @@ -1508,7 +1508,7 @@ kimik3-fp4-h200-vllm-agentic: # Balanced: TP4/PP2 with DP2/EP8 across two H200 nodes. - spec-decoding: none kv-offloading: none - conc-list: [4, 8, 16, 32] + conc-list: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24] prefill: num-worker: 2 tp: 4 @@ -1526,7 +1526,7 @@ kimik3-fp4-h200-vllm-agentic: # Throughput-oriented: TP2/PP2 with DP8/EP16 across four H200 nodes. - spec-decoding: none kv-offloading: none - conc-list: [16] + conc-list: [8, 10, 12, 14, 16, 18, 20, 22, 24] prefill: num-worker: 8 tp: 2 @@ -1545,7 +1545,7 @@ kimik3-fp4-h200-vllm-agentic: - spec-decoding: none kv-offloading: dram kv-offload-backend: { name: vllm-simple } - conc-list: [32, 64, 128] + conc-list: [8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32] prefill: num-worker: 8 tp: 2 From 4c9dcdfa160735740b05873007c5e280501e40ac Mon Sep 17 00:00:00 2001 From: Cameron Quilici Date: Wed, 29 Jul 2026 13:57:57 -0500 Subject: [PATCH 57/62] Update perf-changelog.yaml --- perf-changelog.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 8fa8318c36..6a45a7f38c 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5197,3 +5197,4 @@ description: - "Add Day-0 Kimi K3 FP4 AgentX H200 performance recipes based on the official vLLM recipe, including vLLM simple KV offload for high-concurrency DEP" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 + From 1737359fd80dc997a964ec19ecc5ccd0a85bf75a Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Wed, 29 Jul 2026 14:43:15 -0500 Subject: [PATCH 58/62] perf(kimik3): enable DSpark on H200 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use DSpark level 2 with probabilistic drafting and synthetic golden-AL acceptance across the H200 latency, balanced, throughput, and SimpleCPU-offload profiles. 中文:在 H200 延迟、均衡、吞吐量及 SimpleCPU 卸载配置中启用 DSpark level 2,采用 probabilistic 草稿采样,并按黄金 AL 模拟接受长度。 --- ...-h200-tp2pp2-dp8ep16-throughput-agentic.yaml | 5 +++++ ...h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml | 5 +++++ ...agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml | 5 +++++ .../agg-h200-tp8pp2-latency-agentic.yaml | 6 +++++- configs/nvidia-master.yaml | 17 ++++++++++------- perf-changelog.yaml | 2 +- 6 files changed, 31 insertions(+), 9 deletions(-) diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml index 657eb3361b..762863d418 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml @@ -31,9 +31,12 @@ backend: connector: null aggregated_environment: GLOO_SOCKET_IFNAME: "eth0" + HF_HUB_CACHE: "/hf_hub_cache" + HUGGINGFACE_HUB_CACHE: "/hf_hub_cache" NCCL_SOCKET_IFNAME: "eth0" NCCL_CUMEM_ENABLE: "1" PYTHONNOUSERSITE: "1" + TRANSFORMERS_CACHE: "/hf_hub_cache" VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" VLLM_USE_V2_MODEL_RUNNER: "0" @@ -51,6 +54,8 @@ backend: gpu-memory-utilization: 0.85 max-num-seqs: 2 max-num-batched-tokens: 1024 + speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' + compilation-config: '{"cudagraph_capture_sizes":[3,6]}' enable-prefix-caching: true no-enable-flashinfer-autotune: true disable-custom-all-reduce: true diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml index 300c675a23..039b14666e 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml @@ -31,10 +31,13 @@ backend: connector: null aggregated_environment: GLOO_SOCKET_IFNAME: "eth0" + HF_HUB_CACHE: "/hf_hub_cache" + HUGGINGFACE_HUB_CACHE: "/hf_hub_cache" NCCL_SOCKET_IFNAME: "eth0" NCCL_CUMEM_ENABLE: "1" PYTHONHASHSEED: "42" PYTHONNOUSERSITE: "1" + TRANSFORMERS_CACHE: "/hf_hub_cache" VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" VLLM_USE_V2_MODEL_RUNNER: "0" @@ -52,6 +55,8 @@ backend: gpu-memory-utilization: 0.85 max-num-seqs: 16 max-num-batched-tokens: 1024 + speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' + compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48]}' enable-prefix-caching: true kv-transfer-config: '{"kv_connector":"SimpleCPUOffloadConnector","kv_role":"kv_both","kv_connector_extra_config":{"cpu_bytes_to_use_per_rank":154250000000,"lazy_offload":false}}' no-enable-flashinfer-autotune: true diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml index b832e6d6f0..ddd8eab821 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml @@ -31,9 +31,12 @@ backend: connector: null aggregated_environment: GLOO_SOCKET_IFNAME: "eth0" + HF_HUB_CACHE: "/hf_hub_cache" + HUGGINGFACE_HUB_CACHE: "/hf_hub_cache" NCCL_SOCKET_IFNAME: "eth0" NCCL_CUMEM_ENABLE: "1" PYTHONNOUSERSITE: "1" + TRANSFORMERS_CACHE: "/hf_hub_cache" VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" VLLM_USE_V2_MODEL_RUNNER: "0" @@ -51,6 +54,8 @@ backend: gpu-memory-utilization: 0.90 max-num-seqs: 16 max-num-batched-tokens: 4096 + speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' + compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48]}' enable-prefix-caching: true no-enable-flashinfer-autotune: true disable-custom-all-reduce: true diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml index 9768e11dfd..f685226ed5 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml @@ -31,9 +31,12 @@ backend: connector: null aggregated_environment: GLOO_SOCKET_IFNAME: "eth0" + HF_HUB_CACHE: "/hf_hub_cache" + HUGGINGFACE_HUB_CACHE: "/hf_hub_cache" NCCL_SOCKET_IFNAME: "eth0" NCCL_CUMEM_ENABLE: "1" PYTHONNOUSERSITE: "1" + TRANSFORMERS_CACHE: "/hf_hub_cache" VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" VLLM_USE_V2_MODEL_RUNNER: "0" @@ -49,8 +52,9 @@ backend: gpu-memory-utilization: 0.95 max-num-seqs: 8 max-num-batched-tokens: 4096 + speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' enable-prefix-caching: true - compilation-config: '{"pass_config":{"fuse_allreduce_rms":false}}' + compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12,15,18,21,24],"pass_config":{"fuse_allreduce_rms":false}}' no-enable-flashinfer-autotune: true disable-custom-all-reduce: true enable-auto-tool-choice: true diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 06dd309f68..53626d7a9d 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1471,9 +1471,12 @@ kimik2.5-int4-h200-vllm-agentic: # These are the three aggregated strategies from the official H200 # recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): # multi-node TP is latency-oriented, TEP is balanced, and DEP is -# throughput-oriented. The H200 runner supplies cluster paths while -# srt-slurm owns allocation, direct vLLM startup, readiness, and log capture. -# P/D disaggregation is intentionally deferred. +# throughput-oriented. All profiles use Kimi K3 DSpark level 2 with +# probabilistic drafting and synthetic acceptance pinned to golden AL 2.51. +# The existing `mtp` matrix label covers speculative-decoding methods; the +# checked-in recipes select DSpark explicitly. The H200 runner supplies +# cluster paths while srt-slurm owns allocation, direct vLLM startup, +# readiness, and log capture. P/D disaggregation is intentionally deferred. kimik3-fp4-h200-vllm-agentic: image: vllm/vllm-openai:kimi-k3 model: moonshotai/Kimi-K3 @@ -1488,7 +1491,7 @@ kimik3-fp4-h200-vllm-agentic: - dram-utilization: 0.80 search-space: # Latency-oriented: one TP8/PP2 engine spanning two H200 nodes. - - spec-decoding: none + - spec-decoding: mtp kv-offloading: none conc-list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] prefill: @@ -1506,7 +1509,7 @@ kimik3-fp4-h200-vllm-agentic: ep: 1 dp-attn: false # Balanced: TP4/PP2 with DP2/EP8 across two H200 nodes. - - spec-decoding: none + - spec-decoding: mtp kv-offloading: none conc-list: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24] prefill: @@ -1524,7 +1527,7 @@ kimik3-fp4-h200-vllm-agentic: ep: 8 dp-attn: true # Throughput-oriented: TP2/PP2 with DP8/EP16 across four H200 nodes. - - spec-decoding: none + - spec-decoding: mtp kv-offloading: none conc-list: [8, 10, 12, 14, 16, 18, 20, 22, 24] prefill: @@ -1542,7 +1545,7 @@ kimik3-fp4-h200-vllm-agentic: ep: 16 dp-attn: true # High-concurrency DEP with vLLM's host-DRAM KV tier. - - spec-decoding: none + - spec-decoding: mtp kv-offloading: dram kv-offload-backend: { name: vllm-simple } conc-list: [8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32] diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 6a45a7f38c..514f7882a6 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5195,6 +5195,6 @@ - config-keys: - kimik3-fp4-h200-vllm-agentic description: - - "Add Day-0 Kimi K3 FP4 AgentX H200 performance recipes based on the official vLLM recipe, including vLLM simple KV offload for high-concurrency DEP" + - "Add Day-0 Kimi K3 FP4 AgentX H200 DSpark performance recipes based on the official vLLM recipe, including vLLM simple KV offload for high-concurrency DEP" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 From 5c03d8fbce581069cd455e4d989d42a794dacddb Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Wed, 29 Jul 2026 15:26:34 -0500 Subject: [PATCH 59/62] fix(kimik3): replace PP with pure H200 topologies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use four-node TP32, TEP32, and DEP32 layouts so DSpark does not require unsupported pipeline parallelism. 中文:将流水线并行替换为四节点 TP32、TEP32 与 DEP32 拓扑,避免 DSpark 依赖当前不受支持的 PP。 --- ...=> agg-h200-dep32-throughput-agentic.yaml} | 9 ++- ...> agg-h200-dep32-vllm-simple-agentic.yaml} | 9 ++- ...l => agg-h200-tep32-balanced-agentic.yaml} | 12 ++-- ...aml => agg-h200-tp32-latency-agentic.yaml} | 13 ++-- configs/nvidia-master.yaml | 60 ++++++++----------- 5 files changed, 45 insertions(+), 58 deletions(-) rename benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/{agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml => agg-h200-dep32-throughput-agentic.yaml} (91%) rename benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/{agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml => agg-h200-dep32-vllm-simple-agentic.yaml} (92%) rename benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/{agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml => agg-h200-tep32-balanced-agentic.yaml} (90%) rename benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/{agg-h200-tp8pp2-latency-agentic.yaml => agg-h200-tp32-latency-agentic.yaml} (89%) diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-throughput-agentic.yaml similarity index 91% rename from benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml rename to benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-throughput-agentic.yaml index 762863d418..d1afec56c0 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-throughput-agentic.yaml @@ -1,4 +1,4 @@ -name: "kimik3-vllm-agg-h200-tp2pp2-dp8ep16-throughput-agentic" +name: "kimik3-vllm-agg-h200-dep32-throughput-agentic" model: path: "kimik3" @@ -43,15 +43,14 @@ backend: vllm_config: aggregated: served-model-name: "moonshotai/Kimi-K3" - tensor-parallel-size: 2 - pipeline-parallel-size: 2 - data-parallel-size: 8 + tensor-parallel-size: 1 + data-parallel-size: 32 enable-expert-parallel: true trust-remote-code: true load-format: fastsafetensors moe-backend: marlin attention-backend: FLASHMLA - gpu-memory-utilization: 0.85 + gpu-memory-utilization: 0.95 max-num-seqs: 2 max-num-batched-tokens: 1024 speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-vllm-simple-agentic.yaml similarity index 92% rename from benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml rename to benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-vllm-simple-agentic.yaml index 039b14666e..7bd4717d45 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-vllm-simple-agentic.yaml @@ -1,4 +1,4 @@ -name: "kimik3-vllm-agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic" +name: "kimik3-vllm-agg-h200-dep32-vllm-simple-agentic" model: path: "kimik3" @@ -44,15 +44,14 @@ backend: vllm_config: aggregated: served-model-name: "moonshotai/Kimi-K3" - tensor-parallel-size: 2 - pipeline-parallel-size: 2 - data-parallel-size: 8 + tensor-parallel-size: 1 + data-parallel-size: 32 enable-expert-parallel: true trust-remote-code: true load-format: fastsafetensors moe-backend: marlin attention-backend: FLASHMLA - gpu-memory-utilization: 0.85 + gpu-memory-utilization: 0.95 max-num-seqs: 16 max-num-batched-tokens: 1024 speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tep32-balanced-agentic.yaml similarity index 90% rename from benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml rename to benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tep32-balanced-agentic.yaml index ddd8eab821..cec3ab4f17 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tep32-balanced-agentic.yaml @@ -1,4 +1,4 @@ -name: "kimik3-vllm-agg-h200-tp4pp2-dp2ep8-balanced-agentic" +name: "kimik3-vllm-agg-h200-tep32-balanced-agentic" model: path: "kimik3" @@ -18,9 +18,9 @@ health_check: resources: gpu_type: "h200" gpus_per_node: 8 - agg_nodes: 2 + agg_nodes: 4 agg_workers: 1 - gpus_per_agg: 16 + gpus_per_agg: 32 frontend: type: vllm @@ -43,15 +43,13 @@ backend: vllm_config: aggregated: served-model-name: "moonshotai/Kimi-K3" - tensor-parallel-size: 4 - pipeline-parallel-size: 2 - data-parallel-size: 2 + tensor-parallel-size: 32 enable-expert-parallel: true trust-remote-code: true load-format: fastsafetensors moe-backend: marlin attention-backend: FLASHMLA - gpu-memory-utilization: 0.90 + gpu-memory-utilization: 0.95 max-num-seqs: 16 max-num-batched-tokens: 4096 speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp32-latency-agentic.yaml similarity index 89% rename from benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml rename to benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp32-latency-agentic.yaml index f685226ed5..4010fd7e00 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp32-latency-agentic.yaml @@ -1,4 +1,4 @@ -name: "kimik3-vllm-agg-h200-tp8pp2-latency-agentic" +name: "kimik3-vllm-agg-h200-tp32-latency-agentic" model: path: "kimik3" @@ -18,9 +18,9 @@ health_check: resources: gpu_type: "h200" gpus_per_node: 8 - agg_nodes: 2 + agg_nodes: 4 agg_workers: 1 - gpus_per_agg: 16 + gpus_per_agg: 32 frontend: type: vllm @@ -43,18 +43,17 @@ backend: vllm_config: aggregated: served-model-name: "moonshotai/Kimi-K3" - tensor-parallel-size: 8 - pipeline-parallel-size: 2 + tensor-parallel-size: 32 trust-remote-code: true load-format: fastsafetensors moe-backend: marlin attention-backend: FLASHMLA gpu-memory-utilization: 0.95 - max-num-seqs: 8 + max-num-seqs: 16 max-num-batched-tokens: 4096 speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' enable-prefix-caching: true - compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12,15,18,21,24],"pass_config":{"fuse_allreduce_rms":false}}' + compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48],"pass_config":{"fuse_allreduce_rms":false}}' no-enable-flashinfer-autotune: true disable-custom-all-reduce: true enable-auto-tool-choice: true diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index 53626d7a9d..ab2545dc59 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1490,59 +1490,53 @@ kimik3-fp4-h200-vllm-agentic: agentic-coding: - dram-utilization: 0.80 search-space: - # Latency-oriented: one TP8/PP2 engine spanning two H200 nodes. + # Latency-oriented: one TP32 engine spanning four H200 nodes. - spec-decoding: mtp kv-offloading: none conc-list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] prefill: num-worker: 1 - tp: 8 - pp: 2 + tp: 32 ep: 1 dp-attn: false additional-settings: - - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp8pp2-latency-agentic.yaml" + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp32-latency-agentic.yaml" decode: num-worker: 0 - tp: 8 - pp: 2 + tp: 32 ep: 1 dp-attn: false - # Balanced: TP4/PP2 with DP2/EP8 across two H200 nodes. + # Balanced: one TP32/EP32 engine spanning four H200 nodes. - spec-decoding: mtp kv-offloading: none conc-list: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24] prefill: - num-worker: 2 - tp: 4 - pp: 2 - ep: 8 - dp-attn: true + num-worker: 1 + tp: 32 + ep: 32 + dp-attn: false additional-settings: - - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp4pp2-dp2ep8-balanced-agentic.yaml" + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tep32-balanced-agentic.yaml" decode: num-worker: 0 - tp: 4 - pp: 2 - ep: 8 - dp-attn: true - # Throughput-oriented: TP2/PP2 with DP8/EP16 across four H200 nodes. + tp: 32 + ep: 32 + dp-attn: false + # Throughput-oriented: DP32/EP32 across four H200 nodes. - spec-decoding: mtp kv-offloading: none conc-list: [8, 10, 12, 14, 16, 18, 20, 22, 24] prefill: - num-worker: 8 - tp: 2 - pp: 2 - ep: 16 + num-worker: 32 + tp: 1 + ep: 32 dp-attn: true additional-settings: - - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-throughput-agentic.yaml" + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-dep32-throughput-agentic.yaml" decode: num-worker: 0 - tp: 2 - pp: 2 - ep: 16 + tp: 1 + ep: 32 dp-attn: true # High-concurrency DEP with vLLM's host-DRAM KV tier. - spec-decoding: mtp @@ -1550,18 +1544,16 @@ kimik3-fp4-h200-vllm-agentic: kv-offload-backend: { name: vllm-simple } conc-list: [8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32] prefill: - num-worker: 8 - tp: 2 - pp: 2 - ep: 16 + num-worker: 32 + tp: 1 + ep: 32 dp-attn: true additional-settings: - - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp2pp2-dp8ep16-vllm-simple-agentic.yaml" + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-dep32-vllm-simple-agentic.yaml" decode: num-worker: 0 - tp: 2 - pp: 2 - ep: 16 + tp: 1 + ep: 32 dp-attn: true # NOTE: At the time of submission, https://docs.vllm.ai/projects/recipes/en/latest/moonshotai/Kimi-K2.5.html From 631fa8a9cc8b55a536121eadda00dce037373245 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Wed, 29 Jul 2026 16:51:46 -0500 Subject: [PATCH 60/62] perf(kimik3): use fit-safe H200 hybrid topologies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace pure TP32, TEP32, and DEP32 profiles that cannot preserve the native 1M context with four-node TP16/DP2/EP32 and TP8/DP4/EP32 profiles. Align DSpark with the official K7 probabilistic/block recipe and retain SimpleCPU KV offload for the high-concurrency arm. 中文:将无法保留原生 1M 上下文的纯 TP32、TEP32 和 DEP32 配置替换为四节点 TP16/DP2/EP32 与 TP8/DP4/EP32 配置;DSpark 对齐官方 K7 probabilistic/block 方案,并为高并发配置保留 SimpleCPU KV 卸载。 --- ...agg-h200-tp16dp2ep32-latency-agentic.yaml} | 20 ++++-- ...agg-h200-tp8dp4ep32-balanced-agentic.yaml} | 24 +++++-- ...g-h200-tp8dp4ep32-throughput-agentic.yaml} | 19 ++++-- ...-h200-tp8dp4ep32-vllm-simple-agentic.yaml} | 22 ++++-- configs/nvidia-master.yaml | 67 ++++++++++--------- perf-changelog.yaml | 2 +- 6 files changed, 99 insertions(+), 55 deletions(-) rename benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/{agg-h200-dep32-throughput-agentic.yaml => agg-h200-tp16dp2ep32-latency-agentic.yaml} (76%) rename benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/{agg-h200-tp32-latency-agentic.yaml => agg-h200-tp8dp4ep32-balanced-agentic.yaml} (74%) rename benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/{agg-h200-tep32-balanced-agentic.yaml => agg-h200-tp8dp4ep32-throughput-agentic.yaml} (80%) rename benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/{agg-h200-dep32-vllm-simple-agentic.yaml => agg-h200-tp8dp4ep32-vllm-simple-agentic.yaml} (80%) diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-throughput-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp16dp2ep32-latency-agentic.yaml similarity index 76% rename from benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-throughput-agentic.yaml rename to benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp16dp2ep32-latency-agentic.yaml index d1afec56c0..fa1c4c1c7f 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-throughput-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp16dp2ep32-latency-agentic.yaml @@ -1,10 +1,19 @@ -name: "kimik3-vllm-agg-h200-dep32-throughput-agentic" +name: "kimik3-vllm-agg-h200-tp16dp2ep32-latency-agentic" model: path: "kimik3" container: "vllm/vllm-openai:kimi-k3" precision: "fp4" +identity: + model: + repo: "moonshotai/Kimi-K3" + revision: "9f62e4e9fffbd0a83ddd60e1c209d828994b3569" + container: + image: "vllm/vllm-openai:kimi-k3" + frameworks: + vllm: "0.1.dev19262+gb6bbf29dd.d20260727" + dynamo: install: false @@ -39,12 +48,13 @@ backend: TRANSFORMERS_CACHE: "/hf_hub_cache" VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" + VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" VLLM_USE_V2_MODEL_RUNNER: "0" vllm_config: aggregated: served-model-name: "moonshotai/Kimi-K3" - tensor-parallel-size: 1 - data-parallel-size: 32 + tensor-parallel-size: 16 + data-parallel-size: 2 enable-expert-parallel: true trust-remote-code: true load-format: fastsafetensors @@ -53,9 +63,9 @@ backend: gpu-memory-utilization: 0.95 max-num-seqs: 2 max-num-batched-tokens: 1024 - speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' - compilation-config: '{"cudagraph_capture_sizes":[3,6]}' + speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":7,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"block"}' enable-prefix-caching: true + compilation-config: '{"cudagraph_capture_sizes":[3,6],"pass_config":{"fuse_allreduce_rms":false}}' no-enable-flashinfer-autotune: true disable-custom-all-reduce: true enable-auto-tool-choice: true diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp32-latency-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-balanced-agentic.yaml similarity index 74% rename from benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp32-latency-agentic.yaml rename to benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-balanced-agentic.yaml index 4010fd7e00..d03bebd5af 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp32-latency-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-balanced-agentic.yaml @@ -1,10 +1,19 @@ -name: "kimik3-vllm-agg-h200-tp32-latency-agentic" +name: "kimik3-vllm-agg-h200-tp8dp4ep32-balanced-agentic" model: path: "kimik3" container: "vllm/vllm-openai:kimi-k3" precision: "fp4" +identity: + model: + repo: "moonshotai/Kimi-K3" + revision: "9f62e4e9fffbd0a83ddd60e1c209d828994b3569" + container: + image: "vllm/vllm-openai:kimi-k3" + frameworks: + vllm: "0.1.dev19262+gb6bbf29dd.d20260727" + dynamo: install: false @@ -39,21 +48,24 @@ backend: TRANSFORMERS_CACHE: "/hf_hub_cache" VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" + VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" VLLM_USE_V2_MODEL_RUNNER: "0" vllm_config: aggregated: served-model-name: "moonshotai/Kimi-K3" - tensor-parallel-size: 32 + tensor-parallel-size: 8 + data-parallel-size: 4 + enable-expert-parallel: true trust-remote-code: true load-format: fastsafetensors moe-backend: marlin attention-backend: FLASHMLA gpu-memory-utilization: 0.95 - max-num-seqs: 16 - max-num-batched-tokens: 4096 - speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' + max-num-seqs: 8 + max-num-batched-tokens: 2048 + speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":7,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"block"}' + compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12]}' enable-prefix-caching: true - compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48],"pass_config":{"fuse_allreduce_rms":false}}' no-enable-flashinfer-autotune: true disable-custom-all-reduce: true enable-auto-tool-choice: true diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tep32-balanced-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-throughput-agentic.yaml similarity index 80% rename from benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tep32-balanced-agentic.yaml rename to benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-throughput-agentic.yaml index cec3ab4f17..b48d561e5f 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tep32-balanced-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-throughput-agentic.yaml @@ -1,10 +1,19 @@ -name: "kimik3-vllm-agg-h200-tep32-balanced-agentic" +name: "kimik3-vllm-agg-h200-tp8dp4ep32-throughput-agentic" model: path: "kimik3" container: "vllm/vllm-openai:kimi-k3" precision: "fp4" +identity: + model: + repo: "moonshotai/Kimi-K3" + revision: "9f62e4e9fffbd0a83ddd60e1c209d828994b3569" + container: + image: "vllm/vllm-openai:kimi-k3" + frameworks: + vllm: "0.1.dev19262+gb6bbf29dd.d20260727" + dynamo: install: false @@ -39,11 +48,13 @@ backend: TRANSFORMERS_CACHE: "/hf_hub_cache" VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" + VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" VLLM_USE_V2_MODEL_RUNNER: "0" vllm_config: aggregated: served-model-name: "moonshotai/Kimi-K3" - tensor-parallel-size: 32 + tensor-parallel-size: 8 + data-parallel-size: 4 enable-expert-parallel: true trust-remote-code: true load-format: fastsafetensors @@ -52,8 +63,8 @@ backend: gpu-memory-utilization: 0.95 max-num-seqs: 16 max-num-batched-tokens: 4096 - speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' - compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48]}' + speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":7,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"block"}' + compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12,15,18,21,24]}' enable-prefix-caching: true no-enable-flashinfer-autotune: true disable-custom-all-reduce: true diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-vllm-simple-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-vllm-simple-agentic.yaml similarity index 80% rename from benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-vllm-simple-agentic.yaml rename to benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-vllm-simple-agentic.yaml index 7bd4717d45..2b0905673a 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-dep32-vllm-simple-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-vllm-simple-agentic.yaml @@ -1,10 +1,19 @@ -name: "kimik3-vllm-agg-h200-dep32-vllm-simple-agentic" +name: "kimik3-vllm-agg-h200-tp8dp4ep32-vllm-simple-agentic" model: path: "kimik3" container: "vllm/vllm-openai:kimi-k3" precision: "fp4" +identity: + model: + repo: "moonshotai/Kimi-K3" + revision: "9f62e4e9fffbd0a83ddd60e1c209d828994b3569" + container: + image: "vllm/vllm-openai:kimi-k3" + frameworks: + vllm: "0.1.dev19262+gb6bbf29dd.d20260727" + dynamo: install: false @@ -40,12 +49,13 @@ backend: TRANSFORMERS_CACHE: "/hf_hub_cache" VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" + VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" VLLM_USE_V2_MODEL_RUNNER: "0" vllm_config: aggregated: served-model-name: "moonshotai/Kimi-K3" - tensor-parallel-size: 1 - data-parallel-size: 32 + tensor-parallel-size: 8 + data-parallel-size: 4 enable-expert-parallel: true trust-remote-code: true load-format: fastsafetensors @@ -53,9 +63,9 @@ backend: attention-backend: FLASHMLA gpu-memory-utilization: 0.95 max-num-seqs: 16 - max-num-batched-tokens: 1024 - speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":2,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"synthetic","synthetic_acceptance_length":2.51}' - compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48]}' + max-num-batched-tokens: 4096 + speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":7,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"block"}' + compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12,15,18,21,24,27,30,33]}' enable-prefix-caching: true kv-transfer-config: '{"kv_connector":"SimpleCPUOffloadConnector","kv_role":"kv_both","kv_connector_extra_config":{"cpu_bytes_to_use_per_rank":154250000000,"lazy_offload":false}}' no-enable-flashinfer-autotune: true diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index b69ddd3002..d656491397 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1468,11 +1468,12 @@ kimik2.5-int4-h200-vllm-agentic: - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: vllm-simple }, conc-list: [6, 7, 8, 9, 10, 11, 12, 13, 14] } # Kimi K3 is a 2.8T MXFP4 MoE served on H200 nodes. -# These are the three aggregated strategies from the official H200 +# These are the three aggregated strategy classes from the official H200 # recipe (https://recipes.vllm.ai/moonshotai/Kimi-K3?hardware=h200): -# multi-node TP is latency-oriented, TEP is balanced, and DEP is -# throughput-oriented. All profiles use Kimi K3 DSpark level 2 with -# probabilistic drafting and synthetic acceptance pinned to golden AL 2.51. +# Wider TP is latency-oriented, while progressively wider DP is balanced or +# throughput-oriented. EP32 keeps the model shards within HBM and preserves +# the native 1M context on four H200 nodes. All profiles use the official +# Kimi K3 DSpark K7 probabilistic/block recipe. # The existing `mtp` matrix label covers speculative-decoding methods; the # checked-in recipes select DSpark explicitly. The H200 runner supplies # cluster paths while srt-slurm owns allocation, direct vLLM startup, @@ -1490,69 +1491,69 @@ kimik3-fp4-h200-vllm-agentic: agentic-coding: - dram-utilization: 0.80 search-space: - # Latency-oriented: one TP32 engine spanning four H200 nodes. + # Latency-oriented: TP16 x DP2 with EP32 across four H200 nodes. - spec-decoding: mtp kv-offloading: none - conc-list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + conc-list: [1, 2, 3, 4, 5, 6, 7, 8, 10, 12] prefill: - num-worker: 1 - tp: 32 - ep: 1 - dp-attn: false + num-worker: 2 + tp: 16 + ep: 32 + dp-attn: true additional-settings: - - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp32-latency-agentic.yaml" + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp16dp2ep32-latency-agentic.yaml" decode: num-worker: 0 - tp: 32 - ep: 1 - dp-attn: false - # Balanced: one TP32/EP32 engine spanning four H200 nodes. + tp: 16 + ep: 32 + dp-attn: true + # Balanced: TP8 x DP4 with EP32 across four H200 nodes. - spec-decoding: mtp kv-offloading: none - conc-list: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24] + conc-list: [1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16] prefill: - num-worker: 1 - tp: 32 + num-worker: 4 + tp: 8 ep: 32 - dp-attn: false + dp-attn: true additional-settings: - - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tep32-balanced-agentic.yaml" + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-balanced-agentic.yaml" decode: num-worker: 0 - tp: 32 + tp: 8 ep: 32 - dp-attn: false - # Throughput-oriented: DP32/EP32 across four H200 nodes. + dp-attn: true + # Throughput-oriented: TP8 x DP4 with EP32 across four H200 nodes. - spec-decoding: mtp kv-offloading: none - conc-list: [8, 10, 12, 14, 16, 18, 20, 22, 24] + conc-list: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24] prefill: - num-worker: 32 - tp: 1 + num-worker: 4 + tp: 8 ep: 32 dp-attn: true additional-settings: - - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-dep32-throughput-agentic.yaml" + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-throughput-agentic.yaml" decode: num-worker: 0 - tp: 1 + tp: 8 ep: 32 dp-attn: true - # High-concurrency DEP with vLLM's host-DRAM KV tier. + # High-concurrency hybrid TP/DEP/EP with vLLM's host-DRAM KV tier. - spec-decoding: mtp kv-offloading: dram kv-offload-backend: { name: vllm-simple } conc-list: [8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32] prefill: - num-worker: 32 - tp: 1 + num-worker: 4 + tp: 8 ep: 32 dp-attn: true additional-settings: - - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-dep32-vllm-simple-agentic.yaml" + - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-vllm-simple-agentic.yaml" decode: num-worker: 0 - tp: 1 + tp: 8 ep: 32 dp-attn: true diff --git a/perf-changelog.yaml b/perf-changelog.yaml index fddd509dae..e2858b6eb1 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5234,5 +5234,5 @@ - config-keys: - kimik3-fp4-h200-vllm-agentic description: - - "Add Day-0 Kimi K3 FP4 AgentX H200 DSpark performance recipes based on the official vLLM recipe, including vLLM simple KV offload for high-concurrency DEP" + - "Add Day-0 Kimi K3 FP4 AgentX H200 performance recipes from the official vLLM guidance, using fit-safe TP/DP/EP topologies with optional SimpleCPU KV offload" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2353 From d451287c39e51dea96fa6cc5a4d282fab10a2c4c Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Wed, 29 Jul 2026 16:52:37 -0500 Subject: [PATCH 61/62] perf(kimik3): remove duplicate H200 throughput arm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the GPU-resident TP8/DP4/EP32 profile as the balanced regime and reserve the SimpleCPU variant for high-concurrency throughput, avoiding duplicate experiment names. 中文:将 GPU 常驻的 TP8/DP4/EP32 配置作为均衡场景,并仅在高并发吞吐场景使用 SimpleCPU 变体,避免生成重复的实验名称。 --- ...gg-h200-tp8dp4ep32-throughput-agentic.yaml | 89 ------------------- configs/nvidia-master.yaml | 18 +--- 2 files changed, 1 insertion(+), 106 deletions(-) delete mode 100644 benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-throughput-agentic.yaml diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-throughput-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-throughput-agentic.yaml deleted file mode 100644 index b48d561e5f..0000000000 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-throughput-agentic.yaml +++ /dev/null @@ -1,89 +0,0 @@ -name: "kimik3-vllm-agg-h200-tp8dp4ep32-throughput-agentic" - -model: - path: "kimik3" - container: "vllm/vllm-openai:kimi-k3" - precision: "fp4" - -identity: - model: - repo: "moonshotai/Kimi-K3" - revision: "9f62e4e9fffbd0a83ddd60e1c209d828994b3569" - container: - image: "vllm/vllm-openai:kimi-k3" - frameworks: - vllm: "0.1.dev19262+gb6bbf29dd.d20260727" - -dynamo: - install: false - -slurm: - time_limit: "8:00:00" - -health_check: - max_attempts: 720 - interval_seconds: 10 - -resources: - gpu_type: "h200" - gpus_per_node: 8 - agg_nodes: 4 - agg_workers: 1 - gpus_per_agg: 32 - -frontend: - type: vllm - enable_multiple_frontends: false - -backend: - type: vllm - connector: null - aggregated_environment: - GLOO_SOCKET_IFNAME: "eth0" - HF_HUB_CACHE: "/hf_hub_cache" - HUGGINGFACE_HUB_CACHE: "/hf_hub_cache" - NCCL_SOCKET_IFNAME: "eth0" - NCCL_CUMEM_ENABLE: "1" - PYTHONNOUSERSITE: "1" - TRANSFORMERS_CACHE: "/hf_hub_cache" - VLLM_ENGINE_READY_TIMEOUT_S: "7200" - VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" - VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" - VLLM_USE_V2_MODEL_RUNNER: "0" - vllm_config: - aggregated: - served-model-name: "moonshotai/Kimi-K3" - tensor-parallel-size: 8 - data-parallel-size: 4 - enable-expert-parallel: true - trust-remote-code: true - load-format: fastsafetensors - moe-backend: marlin - attention-backend: FLASHMLA - gpu-memory-utilization: 0.95 - max-num-seqs: 16 - max-num-batched-tokens: 4096 - speculative-config: '{"method":"dspark","model":"Inferact/Kimi-K3-DSpark","num_speculative_tokens":7,"attention_backend":"FLASHINFER_MLA","draft_sample_method":"probabilistic","rejection_sample_method":"block"}' - compilation-config: '{"cudagraph_capture_sizes":[3,6,9,12,15,18,21,24]}' - enable-prefix-caching: true - no-enable-flashinfer-autotune: true - disable-custom-all-reduce: true - enable-auto-tool-choice: true - tool-call-parser: kimi_k3 - reasoning-parser: kimi_k3 - language-model-only: true - -srun_options: - 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" - IS_MULTINODE: "true" - AIPERF_DATASET_MMAP_CACHE_DIR: "/aiperf_mmap_cache" - HF_HUB_CACHE: "/hf_hub_cache" - WEKA_LOADER_OVERRIDE: "semianalysis_cc_traces_weka_062126" diff --git a/configs/nvidia-master.yaml b/configs/nvidia-master.yaml index d656491397..468b794115 100644 --- a/configs/nvidia-master.yaml +++ b/configs/nvidia-master.yaml @@ -1523,23 +1523,7 @@ kimik3-fp4-h200-vllm-agentic: tp: 8 ep: 32 dp-attn: true - # Throughput-oriented: TP8 x DP4 with EP32 across four H200 nodes. - - spec-decoding: mtp - kv-offloading: none - conc-list: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24] - prefill: - num-worker: 4 - tp: 8 - ep: 32 - dp-attn: true - additional-settings: - - "CONFIG_FILE=recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-throughput-agentic.yaml" - decode: - num-worker: 0 - tp: 8 - ep: 32 - dp-attn: true - # High-concurrency hybrid TP/DEP/EP with vLLM's host-DRAM KV tier. + # Throughput-oriented hybrid TP/DEP/EP with vLLM's host-DRAM KV tier. - spec-decoding: mtp kv-offloading: dram kv-offload-backend: { name: vllm-simple } From 9c8643cd1cf8c084476655fbc9100bf685649d70 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Wed, 29 Jul 2026 17:00:42 -0500 Subject: [PATCH 62/62] perf(kimik3): enable Model Runner V2 on H200 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable the V2 model runner consistently across the latency, balanced, and throughput H200 recipes, matching the official Kimi-K3 recipe guidance. 中文:在 H200 的延迟、均衡和吞吐量配置中统一启用 Model Runner V2,与 Kimi-K3 官方配方保持一致。 --- .../kimi-k3/agentic/agg-h200-tp16dp2ep32-latency-agentic.yaml | 2 +- .../kimi-k3/agentic/agg-h200-tp8dp4ep32-balanced-agentic.yaml | 2 +- .../agentic/agg-h200-tp8dp4ep32-vllm-simple-agentic.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp16dp2ep32-latency-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp16dp2ep32-latency-agentic.yaml index fa1c4c1c7f..5382c3885f 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp16dp2ep32-latency-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp16dp2ep32-latency-agentic.yaml @@ -49,7 +49,7 @@ backend: VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" - VLLM_USE_V2_MODEL_RUNNER: "0" + VLLM_USE_V2_MODEL_RUNNER: "1" vllm_config: aggregated: served-model-name: "moonshotai/Kimi-K3" diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-balanced-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-balanced-agentic.yaml index d03bebd5af..95bfae7da1 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-balanced-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-balanced-agentic.yaml @@ -49,7 +49,7 @@ backend: VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" - VLLM_USE_V2_MODEL_RUNNER: "0" + VLLM_USE_V2_MODEL_RUNNER: "1" vllm_config: aggregated: served-model-name: "moonshotai/Kimi-K3" diff --git a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-vllm-simple-agentic.yaml b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-vllm-simple-agentic.yaml index 2b0905673a..02dc6fc61c 100644 --- a/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-vllm-simple-agentic.yaml +++ b/benchmarks/multi_node/srt-slurm-recipes/vllm/kimi-k3/agentic/agg-h200-tp8dp4ep32-vllm-simple-agentic.yaml @@ -50,7 +50,7 @@ backend: VLLM_ENGINE_READY_TIMEOUT_S: "7200" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS: "1800" VLLM_ENABLE_K3_LATENT_MOE_TAIL_FUSION: "1" - VLLM_USE_V2_MODEL_RUNNER: "0" + VLLM_USE_V2_MODEL_RUNNER: "1" vllm_config: aggregated: served-model-name: "moonshotai/Kimi-K3"