From c5aa5684e81bf9d82f56fff221dd3288d83bf087 Mon Sep 17 00:00:00 2001 From: Hyukjoon Lee Date: Thu, 9 Jul 2026 10:47:57 +0900 Subject: [PATCH 01/19] agentx: kimik2.7 fp4 mi355x agentic smoke (none + lmcache) Adds the kimik2.7 fp4 agentic trace-replay recipe (kimik2.7_fp4_mi355x.sh, KV_OFFLOADING none + dram/lmcache) and the kimik2.7-fp4-mi355x-vllm-agentic config key on cluster:mi355x-amds (tp4 conc32, none + lmcache). Recipe clones LMCache to /opt/lmcache-src so the CI checkout never trips over root-owned build artifacts. --- .../agentic/kimik2.7_fp4_mi355x.sh | 244 ++++++++++++++++++ configs/amd-master.yaml | 16 ++ 2 files changed, 260 insertions(+) create mode 100755 benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh diff --git a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh new file mode 100755 index 0000000000..e9edb59029 --- /dev/null +++ b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh @@ -0,0 +1,244 @@ +#!/usr/bin/env bash +set -euo pipefail +set -x + +# Agentic trace replay benchmark for Kimi-K2.7 FP4 on MI355X using vLLM. +# +# Variant of kimik2.7_fp4_mi355x.sh that supports TWO KV configs: +# KV_OFFLOADING=none -> GPU KV only +# KV_OFFLOADING=dram KV_OFFLOAD_BACKEND=lmcache -> LMCache MP server + connector +# +# Required env vars: +# MODEL, TP, CONC, KV_OFFLOADING, TOTAL_CPU_DRAM_GB, RESULT_DIR, DURATION, EP_SIZE + + +source "$(dirname "$0")/../../benchmark_lib.sh" + +check_env_vars MODEL TP CONC KV_OFFLOADING TOTAL_CPU_DRAM_GB RESULT_DIR DURATION EP_SIZE + +if [[ -n "${SLURM_JOB_ID:-}" ]]; then + echo "JOB $SLURM_JOB_ID running on ${SLURMD_NODENAME:-unknown}" +fi + +# ROCR/HIP visibility for vLLM 0.14+ +if [ -n "${ROCR_VISIBLE_DEVICES:-}" ]; then + export HIP_VISIBLE_DEVICES="$ROCR_VISIBLE_DEVICES" +fi + +# `hf download` creates the target dir if missing and is itself idempotent. +# When MODEL_PATH is unset (stand-alone runs), fall back to the HF_HUB_CACHE +# Either way, MODEL_PATH is what the server is launched with. +if [[ -n "${MODEL_PATH:-}" ]]; then + if [[ ! -d "$MODEL_PATH" || -z "$(ls -A "$MODEL_PATH" 2>/dev/null)" ]]; then + hf download "$MODEL" --local-dir "$MODEL_PATH" + fi +else + hf download "$MODEL" + export MODEL_PATH="$MODEL" +fi +rocm-smi || true +amd-smi || true + +# ---- Resolve traces and install deps ---------------------------------------- +resolve_trace_source +install_agentic_deps + +# Install amd-quark for MXFP4 (manual install due to ROCm vLLM bug) +pip install amd-quark + +# Disable AITER RMSNorm for TP < 8 due to accuracy issues +if [ "${TP}" -lt 8 ]; then + export VLLM_ROCM_USE_AITER_RMSNORM=0 +fi +# Workaround for MEC FW <177 RCCL memory reclaim issue +version=$(rocm-smi --showfw 2>/dev/null | grep MEC | head -n 1 | awk '{print $NF}') +if [[ "$version" == "" || ${version:-0} -lt 177 ]]; then + export HSA_NO_SCRATCH_RECLAIM=1 +fi + +export VLLM_ROCM_USE_AITER=1 +export VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4 +# Avoid intermittent symm_mem all-reduce rendezvous hang at engine init on +# MI35x nodes (see KIMIK27_CONC64_LMCACHE_RUNBOOK error #4). +export VLLM_ALLREDUCE_USE_SYMM_MEM="${VLLM_ALLREDUCE_USE_SYMM_MEM:-0}" + +# ---- Server config ---------------------------------------------------------- +SERVER_LOG="$RESULT_DIR/server.log" +LMCACHE_LOG="$RESULT_DIR/lmcache_server.log" +mkdir -p "$RESULT_DIR" + +OFFLOAD_ARGS=() +PREFIX_CACHE_ARGS=() + +# ---- LMCache config --------------------------------------------------------- +LMCACHE_PID="" + +cleanup_lmcache_server() { + if [[ -n "$LMCACHE_PID" ]] && kill -0 "$LMCACHE_PID" 2>/dev/null; then + kill "$LMCACHE_PID" 2>/dev/null || true + wait "$LMCACHE_PID" 2>/dev/null || true + fi +} +trap cleanup_lmcache_server EXIT + +wait_for_lmcache_ready() { + { set +x; } 2>/dev/null + local attempts="${LMCACHE_READY_ATTEMPTS:-120}" + local tail_pid="" + + while [ ! -f "$LMCACHE_LOG" ]; do + if [[ -n "$LMCACHE_PID" ]] && ! kill -0 "$LMCACHE_PID" 2>/dev/null; then + echo "LMCache server died before creating log file. Exiting." >&2 + exit 1 + fi + sleep 1 + done + + tail -f -n +1 "$LMCACHE_LOG" & + tail_pid=$! + + for ((i = 1; i <= attempts; i++)); do + if curl --output /dev/null --silent --fail "http://127.0.0.1:${LMCACHE_HTTP_PORT}/healthcheck"; then + kill "$tail_pid" 2>/dev/null || true + wait "$tail_pid" 2>/dev/null || true + return 0 + fi + if [[ -n "$LMCACHE_PID" ]] && ! kill -0 "$LMCACHE_PID" 2>/dev/null; then + echo "LMCache server died before becoming healthy. Log follows:" >&2 + kill "$tail_pid" 2>/dev/null || true + wait "$tail_pid" 2>/dev/null || true + cat "$LMCACHE_LOG" >&2 || true + exit 1 + fi + sleep 1 + done + + echo "Timed out waiting for LMCache server healthcheck. Log follows:" >&2 + kill "$tail_pid" 2>/dev/null || true + wait "$tail_pid" 2>/dev/null || true + cat "$LMCACHE_LOG" >&2 || true + exit 1 +} + +# Resolve the effective offload backend. When KV_OFFLOADING=none there is no +# backend; when dram, KV_OFFLOAD_BACKEND selects native vs lmcache. +if [[ "$KV_OFFLOADING" == "none" ]]; then + OFFLOAD_MODE="none" +else + OFFLOAD_MODE="${KV_OFFLOAD_BACKEND:?KV_OFFLOAD_BACKEND required when KV_OFFLOADING=dram}" +fi + +case "$OFFLOAD_MODE" in + none) + OFFLOAD_ARGS=(--no-enable-prefix-caching) + ;; + lmcache) + unset VLLM_USE_SIMPLE_KV_OFFLOAD + + # Build LMCache against ROCm if the connector isn't already importable + # (prebuilt kimi-lmcache images already ship it). Clone to a + # container-local dir (NOT the bind-mounted /workspace) so the CI + # checkout's `clean: true` never trips over root-owned build artifacts + # on the next job. Pin a ref for reproducibility. + if ! python3 -c "import lmcache.integration.vllm.lmcache_mp_connector" >/dev/null 2>&1; then + LMCACHE_SRC_DIR="${LMCACHE_SRC_DIR:-/opt/lmcache-src}" + LMCACHE_GIT_REF="${LMCACHE_GIT_REF:-aaf7c0d3}" + rm -rf "$LMCACHE_SRC_DIR" + git clone https://github.com/LMCache/LMCache.git "$LMCACHE_SRC_DIR" + ( cd "$LMCACHE_SRC_DIR" + git checkout "$LMCACHE_GIT_REF" + pip install -r requirements/build.txt + CXX=hipcc BUILD_WITH_HIP=1 pip install -e . --no-build-isolation ) + python3 -c "import lmcache.integration.vllm.lmcache_mp_connector" >/dev/null + fi + + LMCACHE_HOST="${LMCACHE_HOST:-127.0.0.1}" + LMCACHE_PORT="${LMCACHE_PORT:-5555}" + LMCACHE_HTTP_PORT="${LMCACHE_HTTP_PORT:-8080}" + LMCACHE_CONNECT_HOST="${LMCACHE_CONNECT_HOST:-tcp://$LMCACHE_HOST}" + # Let the external MP server own the whole CPU KV pool. The requested + # budget is TOTAL_CPU_DRAM_GB, but LMCache's L1 is SHM-backed: if L1 > + # /dev/shm free it silently disables SHM and falls back to the slow + # pickle path (crashes at load — see kimik27 CI shm-overflow note). + # Cap L1 to 90% of current /dev/shm free space so SHM stays enabled. + SHM_FREE_GB=$(df -BG --output=avail /dev/shm 2>/dev/null | tail -1 | tr -dc '0-9') + SHM_CAP_GB=$(( SHM_FREE_GB * 90 / 100 )) + LMCACHE_L1_SIZE_GB="${LMCACHE_L1_SIZE_GB:-$TOTAL_CPU_DRAM_GB}" + if [ -n "$SHM_CAP_GB" ] && [ "$SHM_CAP_GB" -gt 0 ] && [ "$LMCACHE_L1_SIZE_GB" -gt "$SHM_CAP_GB" ]; then + echo "Capping LMCACHE_L1_SIZE_GB $LMCACHE_L1_SIZE_GB -> $SHM_CAP_GB to fit /dev/shm (${SHM_FREE_GB}G free)" + LMCACHE_L1_SIZE_GB="$SHM_CAP_GB" + fi + LMCACHE_L1_INIT_SIZE_GB="${LMCACHE_L1_INIT_SIZE_GB:-20}" + LMCACHE_L1_READ_TTL_SECONDS="${LMCACHE_L1_READ_TTL_SECONDS:-7200}" + LMCACHE_CHUNK_SIZE="${LMCACHE_CHUNK_SIZE:-256}" + LMCACHE_MAX_WORKERS="${LMCACHE_MAX_WORKERS:-$((TP * 2))}" + export PYTHONHASHSEED="${PYTHONHASHSEED:-0}" + export LMCACHE_BLOCKING_TIMEOUT_SECS=60 + + echo "Starting LMCache MP server..." + LMCACHE_CMD=( + lmcache server + --host "$LMCACHE_HOST" + --port "$LMCACHE_PORT" + --http-host "$LMCACHE_HOST" + --http-port "$LMCACHE_HTTP_PORT" + --l1-size-gb "$LMCACHE_L1_SIZE_GB" + --l1-init-size-gb "$LMCACHE_L1_INIT_SIZE_GB" + --l1-read-ttl-seconds "$LMCACHE_L1_READ_TTL_SECONDS" + --chunk-size "$LMCACHE_CHUNK_SIZE" + --max-workers "$LMCACHE_MAX_WORKERS" + --eviction-policy LRU + ) + printf '%q ' "${LMCACHE_CMD[@]}" > "$RESULT_DIR/lmcache_command.txt" + printf '\n' >> "$RESULT_DIR/lmcache_command.txt" + "${LMCACHE_CMD[@]}" > "$LMCACHE_LOG" 2>&1 & + LMCACHE_PID=$! + echo "LMCache server PID: $LMCACHE_PID" + wait_for_lmcache_ready + + OFFLOAD_ARGS=( + --kv-transfer-config + "{\"kv_connector\":\"LMCacheMPConnector\",\"kv_connector_module_path\":\"lmcache.integration.vllm.lmcache_mp_connector\",\"kv_role\":\"kv_both\",\"kv_connector_extra_config\":{\"lmcache.mp.host\":\"$LMCACHE_CONNECT_HOST\",\"lmcache.mp.port\":$LMCACHE_PORT}}" + ) + ;; + *) + echo "Error: unsupported KV_OFFLOAD_BACKEND '$OFFLOAD_MODE' (expected: lmcache)" >&2 + exit 1 + ;; +esac + +EP_ARGS=() +if [ "$EP_SIZE" -gt 1 ]; then + EP_ARGS=(--enable-expert-parallel) +fi + +echo "Starting vllm server..." +export PYTHONNOUSERSITE=1 + +{ set +x; } 2>/dev/null +VLLM_CMD=( + vllm serve "$MODEL_PATH" --served-model-name "$MODEL" + --host 0.0.0.0 + --port "$PORT" + --tensor-parallel-size="$TP" + "${EP_ARGS[@]}" + --gpu-memory-utilization 0.90 + --block-size=1 + --trust-remote-code + --max-num-seqs "$CONC" + --mm-encoder-tp-mode data + "${PREFIX_CACHE_ARGS[@]}" + "${OFFLOAD_ARGS[@]}" +) +printf '%q ' "${VLLM_CMD[@]}" | tee "$RESULT_DIR/vllm_command.txt" +printf '\n' | tee -a "$RESULT_DIR/vllm_command.txt" +"${VLLM_CMD[@]}" > "$SERVER_LOG" 2>&1 & +SERVER_PID=$! +echo "Server PID: $SERVER_PID" + +wait_for_server_ready --port "$PORT" --server-log "$SERVER_LOG" --server-pid "$SERVER_PID" + +# ---- Run benchmark ---------------------------------------------------------- +build_replay_cmd "$RESULT_DIR" + +run_agentic_replay_and_write_outputs "$RESULT_DIR" diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index ac4e276906..1ffe91dd42 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -548,6 +548,22 @@ kimik2.5-fp4-mi355x-vllm-agentic: - { tp: 4, kv-offloading: none, conc-list: [16, 24, 32, 40] } - { tp: 4, kv-offloading: dram, kv-offload-backend: { name: vllm-native }, conc-list: [16, 24, 32, 40] } +kimik2.7-fp4-mi355x-vllm-agentic: + image: vllm/vllm-openai-rocm:v0.24.0 + model: amd/Kimi-K2.7-Code-MXFP4 + model-prefix: kimik2.7 + runner: cluster:mi355x-amds + precision: fp4 + framework: vllm + multinode: false + scenarios: + agentic-coding: + - dram-utilization: 0.80 + search-space: + - { tp: 4, kv-offloading: none, conc-list: [32] } + - { tp: 4, kv-offloading: dram, kv-offload-backend: lmcache, conc-list: [32] } + + kimik2.5-fp4-mi355x-atom: image: rocm/atom:rocm7.2.4_ubuntu24.04_py3.12_pytorch_release_2.10.0_atom0.1.4_202607091539 model: amd/Kimi-K2.5-MXFP4 From 8c41780a6ed2160bd335d1cec6745733a2f4d124 Mon Sep 17 00:00:00 2001 From: Hyukjoon Lee Date: Thu, 9 Jul 2026 11:39:39 +0900 Subject: [PATCH 02/19] agentx: keep prefix caching ON in kimik2.7 none cell The none case previously passed --no-enable-prefix-caching, which disables the on-GPU prefix cache entirely, not just DRAM offload. That crippled the no-offload baseline (no reuse even within HBM) and made lmcache look artificially good. Leave prefix caching at vLLM's default (ON) so none is an honest GPU-only-KV baseline, apples-to-apples vs lmcache. Matches the kimik2.5 / dsv4 agentic recipes. --- benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh index e9edb59029..b9a197a9b7 100755 --- a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh +++ b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh @@ -130,7 +130,12 @@ fi case "$OFFLOAD_MODE" in none) - OFFLOAD_ARGS=(--no-enable-prefix-caching) + # GPU-only KV, no DRAM offload. Leave prefix caching at vLLM's + # default (ON) so this is an honest no-offload baseline that still + # reuses shared prefixes on-GPU — apples-to-apples vs the lmcache + # cell, which extends that same reuse into DRAM. (Matches the + # kimik2.5 / dsv4 agentic recipes.) + PREFIX_CACHE_ARGS=(--enable-prefix-caching) ;; lmcache) unset VLLM_USE_SIMPLE_KV_OFFLOAD From 450695c9e6caaaaa76e52ad8a6d8e734d3b31df4 Mon Sep 17 00:00:00 2001 From: Hyukjoon Lee Date: Thu, 9 Jul 2026 12:44:42 +0900 Subject: [PATCH 03/19] agentx: add conc64 to kimik2.7 agentic search-space (none + lmcache) --- configs/amd-master.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index 1ffe91dd42..2bc4dde7f9 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -560,8 +560,8 @@ kimik2.7-fp4-mi355x-vllm-agentic: agentic-coding: - dram-utilization: 0.80 search-space: - - { tp: 4, kv-offloading: none, conc-list: [32] } - - { tp: 4, kv-offloading: dram, kv-offload-backend: lmcache, conc-list: [32] } + - { tp: 4, kv-offloading: none, conc-list: [32, 64] } + - { tp: 4, kv-offloading: dram, kv-offload-backend: lmcache, conc-list: [32, 64] } kimik2.5-fp4-mi355x-atom: From 4075e6ca29906cd7a7cb8f8f5f1617be33790645 Mon Sep 17 00:00:00 2001 From: Hyukjoon Lee Date: Thu, 9 Jul 2026 15:29:18 +0900 Subject: [PATCH 04/19] agentx: kimik2.7 full-sweep search-space + perf-changelog Set the kimik2.7-fp4-mi355x-vllm-agentic sweep to conc [1,4,8,16,32,48] for both none and dram/LMCache at TP4, dram-utilization 0.80. Add the corresponding perf-changelog entry (pr-link placeholder to fill on PR open). --- configs/amd-master.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index 2bc4dde7f9..9fb80fdcce 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -560,8 +560,8 @@ kimik2.7-fp4-mi355x-vllm-agentic: agentic-coding: - dram-utilization: 0.80 search-space: - - { tp: 4, kv-offloading: none, conc-list: [32, 64] } - - { tp: 4, kv-offloading: dram, kv-offload-backend: lmcache, conc-list: [32, 64] } + - { tp: 4, kv-offloading: none, conc-list: [1, 4, 8, 16, 32, 48] } + - { tp: 4, kv-offloading: dram, kv-offload-backend: lmcache, conc-list: [1, 4, 8, 16, 32, 48] } kimik2.5-fp4-mi355x-atom: From 8970c9a66385c869ee307e3d71be25c7f1ae4341 Mon Sep 17 00:00:00 2001 From: Hyukjoon Lee Date: Thu, 9 Jul 2026 15:29:39 +0900 Subject: [PATCH 05/19] agentx: restore perf-changelog with kimik2.7 entry Previous commit accidentally dropped perf-changelog.yaml (blob too large for inline arg). Restore it with the kimik2.7-fp4-mi355x-vllm-agentic entry appended. --- perf-changelog.yaml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/perf-changelog.yaml b/perf-changelog.yaml index ce40c69397..0277085f49 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -4992,7 +4992,6 @@ - "LMCache MP server (lmcache_driven transfer mode) + LMCacheMPConnector per PR #2153/#2231; L1 pool derated to 75% of TOTAL_CPU_DRAM_GB; PYTORCH_ALLOC_CONF=expandable_segments:True dropped on the lmcache arms only (VMM allocations cannot be CUDA-IPC-exported to the LMCache server, same failure mode as cuMem on B200); gpu-memory-utilization 0.92 on lmcache DEP8 (matches the official DEP8 derate) and 0.94 on lmcache TP4/DEP4 (at 0.96 the PR #2232 bring-up sweeps hit torch-pool, DeepGEMM-JIT, and cuBLAS-workspace OOMs; 23 lmcache points validated green in runs 29463061871/29535333851 after the derate)" - "LMCache ladders offset the official arms: TP4 +4 conc [32, 36, 40, 44] vs SimpleCPU [28, 32, 36, 40]; DEP4 +4 conc [36, 44, 52, 60, 68, 76] vs SimpleCPU [32, 40, 48, 56, 64, 72]; DEP8 +8 conc capped at 208 [72, 104, 120, 136, 152, 168, 184, 200] vs GPU-resident [64, 96, 112, 128, 144, 160, 176, 192, 224]" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2232 - - config-keys: - dsv4-fp4-b200-vllm-agentic @@ -5003,3 +5002,20 @@ - "LMCache MP server (lmcache_driven transfer mode) + LMCacheMPConnector per PR #2153; L1 pool derated to 75% of TOTAL_CPU_DRAM_GB; --enable-cumem-allocator dropped on the lmcache arm only (cuMem/VMM allocations cannot be CUDA-IPC-exported to the LMCache server)" - "LMCache TP8 points mirror the vllm-simple ladder (conc [8, 12, 16]); LMCache DEP8 points mirror the Mooncake ladder (conc [12, 20, 28, 36, 44, 52, 60, 68, 76]) for a like-for-like backend comparison; the PR #2231 bring-up sweep validated the recipe across DEP8 conc 8-80 (peak ~25.7k total tok/s/GPU at conc 72, 96-98% cache hit)" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2231 + +- config-keys: + - kimik2.7-fp4-mi355x-vllm-agentic + description: + - "Add Kimi-K2.7-Code-MXFP4 agentic-coding config on MI355X (runner: cluster:mi355x-amds) via vLLM v0.24.0, TP4" + - "Sweep KV-offloading none (conc [1,4,8]) vs dram/LMCache (conc [16,32]); LMCache MP server + LMCacheMPConnector, dram-utilization 0.80" + - "Recipe benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh clones LMCache to container-local /opt/lmcache-src (pinned) so CI checkout never trips over root-owned build artifacts" + pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2126 + +- config-keys: + - kimik2.7-fp4-mi355x-vllm-agentic + description: + - "Move the agentic-coding sweep from TP4 to TP8 and compare three KV tiers on the agentic trace: GPU-only (none) at conc [4,8], and dram/LMCache + dram/Mooncake at conc [16,32,48] (3600s trace replay)" + - "TP4 was GPU-KV-capacity bound: the ~121 GiB pool held only ~12 resident ~90k-token contexts, so throughput plateaued (~160 tok/s) and requests preempted/thrashed from conc16 up. GPU-only still collapses under load at TP8, so it is swept only at low conc; the dram offload backends carry the high-conc range" + - "Add a Mooncake KV-offload backend to the recipe (embedded MooncakeStoreConnector store). Built from source for ROCm via Mooncake's build_wheel.sh and pip-installed so the mooncake package lands in site-packages and is importable from the vLLM worker subprocesses (a bare make install left workers unable to import it)" + - "Adds optional per-scenario 'duration' override to the agentic-coding config schema (defaults to 3600s when unset)" + pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2126 From 5b20d870c61653ef96c899b1892d3f654164cd2e Mon Sep 17 00:00:00 2001 From: Hyukjoon Lee Date: Thu, 9 Jul 2026 15:49:27 +0900 Subject: [PATCH 06/19] agentx: adjust kimik2.7 agentic sweep top conc 48 -> 42 --- configs/amd-master.yaml | 4 ++-- perf-changelog.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index 9fb80fdcce..831927e1dc 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -560,8 +560,8 @@ kimik2.7-fp4-mi355x-vllm-agentic: agentic-coding: - dram-utilization: 0.80 search-space: - - { tp: 4, kv-offloading: none, conc-list: [1, 4, 8, 16, 32, 48] } - - { tp: 4, kv-offloading: dram, kv-offload-backend: lmcache, conc-list: [1, 4, 8, 16, 32, 48] } + - { tp: 4, kv-offloading: none, conc-list: [1, 4, 8, 16, 32, 42] } + - { tp: 4, kv-offloading: dram, kv-offload-backend: lmcache, conc-list: [1, 4, 8, 16, 32, 42] } kimik2.5-fp4-mi355x-atom: diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 0277085f49..b7b6a54da7 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5006,8 +5006,8 @@ - config-keys: - kimik2.7-fp4-mi355x-vllm-agentic description: - - "Add Kimi-K2.7-Code-MXFP4 agentic-coding config on MI355X (runner: cluster:mi355x-amds) via vLLM v0.24.0, TP4" - - "Sweep KV-offloading none (conc [1,4,8]) vs dram/LMCache (conc [16,32]); LMCache MP server + LMCacheMPConnector, dram-utilization 0.80" + - "Add Kimi-K2.7-Code-MXFP4 agentic-coding config on MI355X (cluster:gbt350docker->mi355x-amds) via vLLM v0.24.0, TP4" + - "Sweep KV-offloading none vs dram/LMCache at conc [1,4,8,16,32,42]; LMCache MP server + LMCacheMPConnector, dram-utilization 0.80" - "Recipe benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh clones LMCache to container-local /opt/lmcache-src (pinned) so CI checkout never trips over root-owned build artifacts" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2126 From 2846e86c49f0d90a7566616d79488f6d81334491 Mon Sep 17 00:00:00 2001 From: Hyukjoon Lee Date: Thu, 9 Jul 2026 16:23:02 +0900 Subject: [PATCH 07/19] agentx: reshape kimik2.7 sweep to Pareto frontier + address review - Frontier-only sweep: none [1,4,8] (low conc, fits GPU HBM) + lmcache [16,32] (above the KV cliff). Drops dominated/cliff points per review. - Fix recipe header: 'Variant of kimik2.5_fp4_mi355x.sh' (was self-referential) - perf-changelog: correct runner (cluster:mi355x-amds) and conc lists --- benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh | 2 +- configs/amd-master.yaml | 4 ++-- perf-changelog.yaml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh index b9a197a9b7..10184a18ba 100755 --- a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh +++ b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh @@ -4,7 +4,7 @@ set -x # Agentic trace replay benchmark for Kimi-K2.7 FP4 on MI355X using vLLM. # -# Variant of kimik2.7_fp4_mi355x.sh that supports TWO KV configs: +# Variant of kimik2.5_fp4_mi355x.sh that supports TWO KV configs: # KV_OFFLOADING=none -> GPU KV only # KV_OFFLOADING=dram KV_OFFLOAD_BACKEND=lmcache -> LMCache MP server + connector # diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index 831927e1dc..e4e6d93d1f 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -560,8 +560,8 @@ kimik2.7-fp4-mi355x-vllm-agentic: agentic-coding: - dram-utilization: 0.80 search-space: - - { tp: 4, kv-offloading: none, conc-list: [1, 4, 8, 16, 32, 42] } - - { tp: 4, kv-offloading: dram, kv-offload-backend: lmcache, conc-list: [1, 4, 8, 16, 32, 42] } + - { tp: 4, kv-offloading: none, conc-list: [1, 4, 8] } + - { tp: 4, kv-offloading: dram, kv-offload-backend: lmcache, conc-list: [16, 32] } kimik2.5-fp4-mi355x-atom: diff --git a/perf-changelog.yaml b/perf-changelog.yaml index b7b6a54da7..0277085f49 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5006,8 +5006,8 @@ - config-keys: - kimik2.7-fp4-mi355x-vllm-agentic description: - - "Add Kimi-K2.7-Code-MXFP4 agentic-coding config on MI355X (cluster:gbt350docker->mi355x-amds) via vLLM v0.24.0, TP4" - - "Sweep KV-offloading none vs dram/LMCache at conc [1,4,8,16,32,42]; LMCache MP server + LMCacheMPConnector, dram-utilization 0.80" + - "Add Kimi-K2.7-Code-MXFP4 agentic-coding config on MI355X (runner: cluster:mi355x-amds) via vLLM v0.24.0, TP4" + - "Sweep KV-offloading none (conc [1,4,8]) vs dram/LMCache (conc [16,32]); LMCache MP server + LMCacheMPConnector, dram-utilization 0.80" - "Recipe benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh clones LMCache to container-local /opt/lmcache-src (pinned) so CI checkout never trips over root-owned build artifacts" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2126 From 6eb6e334292170ae07dffabcc1c6db795c2ec8a9 Mon Sep 17 00:00:00 2001 From: Hyukjoon Lee Date: Thu, 9 Jul 2026 16:52:48 +0900 Subject: [PATCH 08/19] agentx: trim redundant comments in kimik2.7 recipe --- .../agentic/kimik2.7_fp4_mi355x.sh | 30 +++++-------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh index 10184a18ba..7f084cd69f 100755 --- a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh +++ b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh @@ -3,8 +3,6 @@ set -euo pipefail set -x # Agentic trace replay benchmark for Kimi-K2.7 FP4 on MI355X using vLLM. -# -# Variant of kimik2.5_fp4_mi355x.sh that supports TWO KV configs: # KV_OFFLOADING=none -> GPU KV only # KV_OFFLOADING=dram KV_OFFLOAD_BACKEND=lmcache -> LMCache MP server + connector # @@ -25,9 +23,6 @@ if [ -n "${ROCR_VISIBLE_DEVICES:-}" ]; then export HIP_VISIBLE_DEVICES="$ROCR_VISIBLE_DEVICES" fi -# `hf download` creates the target dir if missing and is itself idempotent. -# When MODEL_PATH is unset (stand-alone runs), fall back to the HF_HUB_CACHE -# Either way, MODEL_PATH is what the server is launched with. if [[ -n "${MODEL_PATH:-}" ]]; then if [[ ! -d "$MODEL_PATH" || -z "$(ls -A "$MODEL_PATH" 2>/dev/null)" ]]; then hf download "$MODEL" --local-dir "$MODEL_PATH" @@ -120,8 +115,6 @@ wait_for_lmcache_ready() { exit 1 } -# Resolve the effective offload backend. When KV_OFFLOADING=none there is no -# backend; when dram, KV_OFFLOAD_BACKEND selects native vs lmcache. if [[ "$KV_OFFLOADING" == "none" ]]; then OFFLOAD_MODE="none" else @@ -130,21 +123,16 @@ fi case "$OFFLOAD_MODE" in none) - # GPU-only KV, no DRAM offload. Leave prefix caching at vLLM's - # default (ON) so this is an honest no-offload baseline that still - # reuses shared prefixes on-GPU — apples-to-apples vs the lmcache - # cell, which extends that same reuse into DRAM. (Matches the - # kimik2.5 / dsv4 agentic recipes.) + # GPU-only KV baseline: keep on-GPU prefix caching ON (no DRAM offload) + # so it's apples-to-apples vs the lmcache cell. PREFIX_CACHE_ARGS=(--enable-prefix-caching) ;; lmcache) unset VLLM_USE_SIMPLE_KV_OFFLOAD - # Build LMCache against ROCm if the connector isn't already importable - # (prebuilt kimi-lmcache images already ship it). Clone to a - # container-local dir (NOT the bind-mounted /workspace) so the CI - # checkout's `clean: true` never trips over root-owned build artifacts - # on the next job. Pin a ref for reproducibility. + # Build LMCache against ROCm if the connector isn't importable. Clone to + # a container-local dir (NOT bind-mounted /workspace) so the next job's + # checkout `clean: true` won't trip over root-owned build artifacts. if ! python3 -c "import lmcache.integration.vllm.lmcache_mp_connector" >/dev/null 2>&1; then LMCACHE_SRC_DIR="${LMCACHE_SRC_DIR:-/opt/lmcache-src}" LMCACHE_GIT_REF="${LMCACHE_GIT_REF:-aaf7c0d3}" @@ -161,11 +149,9 @@ case "$OFFLOAD_MODE" in LMCACHE_PORT="${LMCACHE_PORT:-5555}" LMCACHE_HTTP_PORT="${LMCACHE_HTTP_PORT:-8080}" LMCACHE_CONNECT_HOST="${LMCACHE_CONNECT_HOST:-tcp://$LMCACHE_HOST}" - # Let the external MP server own the whole CPU KV pool. The requested - # budget is TOTAL_CPU_DRAM_GB, but LMCache's L1 is SHM-backed: if L1 > - # /dev/shm free it silently disables SHM and falls back to the slow - # pickle path (crashes at load — see kimik27 CI shm-overflow note). - # Cap L1 to 90% of current /dev/shm free space so SHM stays enabled. + # LMCache L1 is SHM-backed: if L1 > /dev/shm free it silently disables + # SHM and falls back to the pickle path (crashes at load). Cap L1 to 90% + # of /dev/shm free so SHM stays enabled. SHM_FREE_GB=$(df -BG --output=avail /dev/shm 2>/dev/null | tail -1 | tr -dc '0-9') SHM_CAP_GB=$(( SHM_FREE_GB * 90 / 100 )) LMCACHE_L1_SIZE_GB="${LMCACHE_L1_SIZE_GB:-$TOTAL_CPU_DRAM_GB}" From cf49417109d52be3d655fe52685576ca5700f7c7 Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 14 Jul 2026 01:02:31 -0500 Subject: [PATCH 09/19] fix(config): structure LMCache backend metadata --- configs/amd-master.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index e4e6d93d1f..a272411653 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -561,7 +561,7 @@ kimik2.7-fp4-mi355x-vllm-agentic: - dram-utilization: 0.80 search-space: - { tp: 4, kv-offloading: none, conc-list: [1, 4, 8] } - - { tp: 4, kv-offloading: dram, kv-offload-backend: lmcache, conc-list: [16, 32] } + - { tp: 4, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32] } kimik2.5-fp4-mi355x-atom: From e23ee3e234cf14204442738d4ed2610b6a550406 Mon Sep 17 00:00:00 2001 From: hyukjlee Date: Tue, 14 Jul 2026 15:14:46 +0900 Subject: [PATCH 10/19] [AMD][AgentX] Move Kimi-K2.7 agentic sweep to TP8 conc[16,32,48] 900s smoke At TP4 the conc16/32 cells were GPU-KV-capacity bound: the ~121 GiB KV pool held only ~12 resident ~90k-token contexts, so throughput plateaued (~160 tok/s) and requests preempted/thrashed from conc16 up (0 preemptions at c8, 24 at c16, 35 at c32). LMCache was healthy (82% external prefix-hit) so offload quality was not the limiter -- raw resident-KV room was. Move the agentic-coding sweep to TP8 (doubles the KV pool and per-token decode compute) at conc [16,32,48] for both KV-offloading none and dram/LMCache, as a 900s trace-replay smoke. Adds an optional per-scenario `duration` override to the agentic-coding config schema (defaults to 3600s when unset) so smoke sweeps can run shorter without changing the global default. Co-Authored-By: Claude Opus 4.8 (1M context) --- configs/amd-master.yaml | 9 +++++-- utils/matrix_logic/generate_sweep_configs.py | 4 +-- utils/matrix_logic/test_validation.py | 27 ++++++++++++++++++-- utils/matrix_logic/validation.py | 5 ++++ 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index a272411653..211846ddf5 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -558,10 +558,15 @@ kimik2.7-fp4-mi355x-vllm-agentic: multinode: false scenarios: agentic-coding: + # TP8 900s smoke to break the TP4 GPU-KV-capacity wall at higher concurrency. + # At TP4 the ~121 GiB KV pool held only ~12 resident ~90k-token contexts, so + # throughput plateaued (~160 tok/s) and preemption thrashed from conc16 up. + # TP8 doubles GPUs -> ~2x KV pool + faster per-token decode. - dram-utilization: 0.80 + duration: 900 search-space: - - { tp: 4, kv-offloading: none, conc-list: [1, 4, 8] } - - { tp: 4, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32] } + - { tp: 8, kv-offloading: none, conc-list: [16, 32, 48] } + - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32, 48] } kimik2.5-fp4-mi355x-atom: diff --git a/utils/matrix_logic/generate_sweep_configs.py b/utils/matrix_logic/generate_sweep_configs.py index 7df1a75b64..d62d951bf4 100644 --- a/utils/matrix_logic/generate_sweep_configs.py +++ b/utils/matrix_logic/generate_sweep_configs.py @@ -700,7 +700,7 @@ def generate_full_sweep(args, all_config_data, runner_data): for agentic_config in agentic_configs: bmk_space = agentic_config[Fields.SEARCH_SPACE.value] - duration = DEFAULT_AGENTIC_DURATION_SECONDS + duration = agentic_config.get(Fields.DURATION.value) or DEFAULT_AGENTIC_DURATION_SECONDS for bmk in bmk_space: if is_multinode: @@ -1003,7 +1003,7 @@ def generate_test_config_sweep(args, all_config_data, runner_data=None): # ---- Agentic-coding scenarios ---- agentic_configs = val[Fields.SCENARIOS.value].get(Fields.AGENTIC_CODING.value, []) if (scenario_filter is None or 'agentic-coding' in scenario_filter) else [] for agentic_config in agentic_configs: - duration = DEFAULT_AGENTIC_DURATION_SECONDS + duration = agentic_config.get(Fields.DURATION.value) or DEFAULT_AGENTIC_DURATION_SECONDS bmk_space = agentic_config[Fields.SEARCH_SPACE.value] for bmk in bmk_space: diff --git a/utils/matrix_logic/test_validation.py b/utils/matrix_logic/test_validation.py index 3d25d03eef..ddab717d42 100644 --- a/utils/matrix_logic/test_validation.py +++ b/utils/matrix_logic/test_validation.py @@ -575,10 +575,33 @@ def test_available_cpu_dram_is_not_a_master_config_field(self): }], }) - def test_duration_is_not_a_master_config_field(self): + def test_duration_is_an_optional_master_config_field(self): + # Per-scenario duration override (falls back to the default 3600s in the + # sweep generator when unset). Used for shorter agentic smoke sweeps. + cfg = AgenticCodingConfig(**{ + "duration": 1800, + "search-space": [{ + "tp": 8, + "kv-offloading": "none", + "conc-list": [16], + }], + }) + assert cfg.duration == 1800 + + def test_duration_defaults_to_none_when_unset(self): + cfg = AgenticCodingConfig(**{ + "search-space": [{ + "tp": 8, + "kv-offloading": "none", + "conc-list": [16], + }], + }) + assert cfg.duration is None + + def test_duration_must_be_positive(self): with pytest.raises(Exception, match="duration"): AgenticCodingConfig(**{ - "duration": 1800, + "duration": 0, "search-space": [{ "tp": 8, "kv-offloading": "none", diff --git a/utils/matrix_logic/validation.py b/utils/matrix_logic/validation.py index 9f19572f08..8f4ca8cdcb 100644 --- a/utils/matrix_logic/validation.py +++ b/utils/matrix_logic/validation.py @@ -638,6 +638,11 @@ class AgenticCodingConfig(BaseModel): dram_utilization: Optional[float] = Field( default=None, alias=Fields.DRAM_UTILIZATION.value, gt=0, le=1 ) + # Per-scenario trace-replay duration override (seconds). Falls back to + # DEFAULT_AGENTIC_DURATION_SECONDS in the sweep generator when unset. + duration: Optional[int] = Field( + default=None, alias=Fields.DURATION.value, gt=0 + ) @model_validator(mode='after') def validate_dram_offload_capacity(self): From 9fa02ce8b8d34c7059d2f141fe2856cd2ee02adb Mon Sep 17 00:00:00 2001 From: hyukjlee Date: Tue, 14 Jul 2026 16:30:30 +0900 Subject: [PATCH 11/19] [AMD][AgentX] Add Mooncake KV-offload backend to kimik2.7 agentic sweep Add a third KV tier to the TP8 agentic comparison alongside none and LMCache: dram/Mooncake via the embedded MooncakeStoreConnector store (built from source for ROCm, tcp protocol), modeled on the MI355X DSv4 vLLM recipe. Wire it as an additive `mooncake)` case so the existing none/lmcache paths are unchanged. configs/amd-master.yaml now carries all three backends at conc [16,32,48]. configs/smoke-kimik2.7-mooncake.yaml is a temporary overlay to dispatch only the Mooncake cells, so the in-flight none/lmcache sweep is not rerun. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../agentic/kimik2.7_fp4_mi355x.sh | 83 ++++++++++++++++++- configs/amd-master.yaml | 1 + configs/smoke-kimik2.7-mooncake.yaml | 18 ++++ 3 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 configs/smoke-kimik2.7-mooncake.yaml diff --git a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh index 7f084cd69f..854f38d4d2 100755 --- a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh +++ b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh @@ -5,6 +5,7 @@ set -x # Agentic trace replay benchmark for Kimi-K2.7 FP4 on MI355X using vLLM. # KV_OFFLOADING=none -> GPU KV only # KV_OFFLOADING=dram KV_OFFLOAD_BACKEND=lmcache -> LMCache MP server + connector +# KV_OFFLOADING=dram KV_OFFLOAD_BACKEND=mooncake -> Mooncake embedded store + connector # # Required env vars: # MODEL, TP, CONC, KV_OFFLOADING, TOTAL_CPU_DRAM_GB, RESULT_DIR, DURATION, EP_SIZE @@ -60,21 +61,27 @@ export VLLM_ALLREDUCE_USE_SYMM_MEM="${VLLM_ALLREDUCE_USE_SYMM_MEM:-0}" # ---- Server config ---------------------------------------------------------- SERVER_LOG="$RESULT_DIR/server.log" LMCACHE_LOG="$RESULT_DIR/lmcache_server.log" +MOONCAKE_MASTER_LOG="$RESULT_DIR/mooncake_master.log" mkdir -p "$RESULT_DIR" OFFLOAD_ARGS=() PREFIX_CACHE_ARGS=() -# ---- LMCache config --------------------------------------------------------- +# ---- Offload service cleanup ------------------------------------------------ LMCACHE_PID="" +MOONCAKE_MASTER_PID="" -cleanup_lmcache_server() { +cleanup_offload_services() { if [[ -n "$LMCACHE_PID" ]] && kill -0 "$LMCACHE_PID" 2>/dev/null; then kill "$LMCACHE_PID" 2>/dev/null || true wait "$LMCACHE_PID" 2>/dev/null || true fi + if [[ -n "$MOONCAKE_MASTER_PID" ]] && kill -0 "$MOONCAKE_MASTER_PID" 2>/dev/null; then + kill "$MOONCAKE_MASTER_PID" 2>/dev/null || true + wait "$MOONCAKE_MASTER_PID" 2>/dev/null || true + fi } -trap cleanup_lmcache_server EXIT +trap cleanup_offload_services EXIT wait_for_lmcache_ready() { { set +x; } 2>/dev/null @@ -192,8 +199,76 @@ case "$OFFLOAD_MODE" in "{\"kv_connector\":\"LMCacheMPConnector\",\"kv_connector_module_path\":\"lmcache.integration.vllm.lmcache_mp_connector\",\"kv_role\":\"kv_both\",\"kv_connector_extra_config\":{\"lmcache.mp.host\":\"$LMCACHE_CONNECT_HOST\",\"lmcache.mp.port\":$LMCACHE_PORT}}" ) ;; + mooncake) + unset VLLM_USE_SIMPLE_KV_OFFLOAD + + # Mooncake embedded mode contributes one global segment per GPU rank to + # a shared distributed store, so pre-divide the aggregate host-memory + # budget across TP ranks. Mirrors the MI355X DSv4 vLLM recipe. + MOONCAKE_PER_RANK_GB=$((TOTAL_CPU_DRAM_GB / TP)) + + # No prebuilt ROCm wheel: build the Mooncake transfer engine from source + # if the store module isn't importable. Clone to a container-local dir + # (NOT bind-mounted /workspace) so the next job's checkout `clean: true` + # won't trip over root-owned build artifacts. + if ! python3 -c "from mooncake.store import MooncakeDistributedStore" >/dev/null 2>&1; then + MOONCAKE_SRC_DIR="${MOONCAKE_SRC_DIR:-/opt/mooncake-src}" + MOONCAKE_GIT_REF="${MOONCAKE_GIT_REF:-main}" + rm -rf "$MOONCAKE_SRC_DIR" + git clone https://github.com/kvcache-ai/Mooncake.git "$MOONCAKE_SRC_DIR" + ( cd "$MOONCAKE_SRC_DIR" + git checkout "$MOONCAKE_GIT_REF" + bash dependencies.sh + mkdir -p build && cd build + cmake .. + make -j + make install ) + python3 -c "from mooncake.store import MooncakeDistributedStore" >/dev/null + fi + + MOONCAKE_MASTER_PORT=$((PORT + 12000)) + MOONCAKE_CONFIG_PATH="$RESULT_DIR/mooncake_config.json" + cat > "$MOONCAKE_CONFIG_PATH" < "$MOONCAKE_MASTER_LOG" 2>&1 & + MOONCAKE_MASTER_PID=$! + echo "Mooncake master PID: $MOONCAKE_MASTER_PID" + sleep 10 + if ! kill -0 "$MOONCAKE_MASTER_PID" 2>/dev/null; then + echo "Mooncake master died during startup. Log follows:" >&2 + cat "$MOONCAKE_MASTER_LOG" >&2 || true + exit 1 + fi + + PREFIX_CACHE_ARGS=(--enable-prefix-caching) + OFFLOAD_ARGS=( + --kv-transfer-config + '{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_both","kv_connector_extra_config":{"load_async":true}}' + ) + ;; *) - echo "Error: unsupported KV_OFFLOAD_BACKEND '$OFFLOAD_MODE' (expected: lmcache)" >&2 + echo "Error: unsupported KV_OFFLOAD_BACKEND '$OFFLOAD_MODE' (expected: lmcache, mooncake)" >&2 exit 1 ;; esac diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index 211846ddf5..6c09dfadb6 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -567,6 +567,7 @@ kimik2.7-fp4-mi355x-vllm-agentic: search-space: - { tp: 8, kv-offloading: none, conc-list: [16, 32, 48] } - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32, 48] } + - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: mooncake, version: "source-main" }, conc-list: [16, 32, 48] } kimik2.5-fp4-mi355x-atom: diff --git a/configs/smoke-kimik2.7-mooncake.yaml b/configs/smoke-kimik2.7-mooncake.yaml new file mode 100644 index 0000000000..2b91c74ea6 --- /dev/null +++ b/configs/smoke-kimik2.7-mooncake.yaml @@ -0,0 +1,18 @@ +# Temporary overlay to dispatch ONLY the Mooncake KV-offload cells for the +# kimik2.7 agentic TP8 smoke, so the in-flight none/lmcache sweep is not +# rerun. Same config key + settings as configs/amd-master.yaml, mooncake only. +# Remove once the 3-way none/lmcache/mooncake comparison is complete. +kimik2.7-fp4-mi355x-vllm-agentic: + image: vllm/vllm-openai-rocm:v0.24.0 + model: amd/Kimi-K2.7-Code-MXFP4 + model-prefix: kimik2.7 + runner: cluster:mi355x-amds + precision: fp4 + framework: vllm + multinode: false + scenarios: + agentic-coding: + - dram-utilization: 0.80 + duration: 900 + search-space: + - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: mooncake, version: "source-main" }, conc-list: [16, 32, 48] } From bb205f810ab2c40d8330487d0d1df35f62bc69f9 Mon Sep 17 00:00:00 2001 From: hyukjlee Date: Tue, 14 Jul 2026 22:40:27 +0900 Subject: [PATCH 12/19] [AMD][AgentX] kimik2.7 TP8 3600s: none c[4,8], lmcache+mooncake c[16,32,48]; fix Mooncake worker import Reshape the TP8 agentic sweep for the real 3600s comparison run: - none (GPU-only) swept only at low conc [4,8] (it collapses under load) - LMCache and Mooncake carry the high-conc [16,32,48] range - duration 3600s (the prior 900s smoke was warmup-dominated for the ~90k-token agentic inputs, so per-request metrics were unreliable) Fix Mooncake so the vLLM worker subprocesses can import it: the previous bare `make install` only laid down C++ libs, so the launcher imported `mooncake` but the workers hit "Please install mooncake ..." at KV-cache init. Build the wheel via Mooncake's scripts/build_wheel.sh (auditwheel bundles every .so) and pip install it into site-packages, and build with -DWITH_STORE=ON so store.so (MooncakeStoreConnector) is present. Drop the temporary configs/smoke-kimik2.7-mooncake.yaml overlay; all three backends now run from one canonical config. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../single_node/agentic/kimik2.7_fp4_mi355x.sh | 17 +++++++++++++++-- configs/amd-master.yaml | 13 +++++++------ configs/smoke-kimik2.7-mooncake.yaml | 18 ------------------ 3 files changed, 22 insertions(+), 26 deletions(-) delete mode 100644 configs/smoke-kimik2.7-mooncake.yaml diff --git a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh index 854f38d4d2..e2c6a019a5 100755 --- a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh +++ b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh @@ -211,18 +211,31 @@ case "$OFFLOAD_MODE" in # if the store module isn't importable. Clone to a container-local dir # (NOT bind-mounted /workspace) so the next job's checkout `clean: true` # won't trip over root-owned build artifacts. + # + # A bare `make install` only lays down the C++ libs, so the launcher can + # import `mooncake` but the vLLM worker SUBPROCESSES cannot (fresh + # site-packages) -> "Please install mooncake ..." at KV-cache init. Build + # the wheel via Mooncake's own scripts/build_wheel.sh (auditwheel bundles + # every .so into a self-contained package) and pip install it so the + # `mooncake` package lands in site-packages and is importable everywhere. if ! python3 -c "from mooncake.store import MooncakeDistributedStore" >/dev/null 2>&1; then MOONCAKE_SRC_DIR="${MOONCAKE_SRC_DIR:-/opt/mooncake-src}" MOONCAKE_GIT_REF="${MOONCAKE_GIT_REF:-main}" + MOONCAKE_PYVER="$(python3 -c 'import sys;print(f"{sys.version_info.major}.{sys.version_info.minor}")')" + pip install --quiet build auditwheel patchelf rm -rf "$MOONCAKE_SRC_DIR" git clone https://github.com/kvcache-ai/Mooncake.git "$MOONCAKE_SRC_DIR" ( cd "$MOONCAKE_SRC_DIR" git checkout "$MOONCAKE_GIT_REF" bash dependencies.sh mkdir -p build && cd build - cmake .. + cmake .. -DWITH_STORE=ON make -j - make install ) + make install + cd .. + # Produces a self-contained wheel under mooncake-wheel/dist/. + bash scripts/build_wheel.sh "$MOONCAKE_PYVER" + pip install --force-reinstall mooncake-wheel/dist/*.whl ) python3 -c "from mooncake.store import MooncakeDistributedStore" >/dev/null fi diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index 6c09dfadb6..f998b475ba 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -558,14 +558,15 @@ kimik2.7-fp4-mi355x-vllm-agentic: multinode: false scenarios: agentic-coding: - # TP8 900s smoke to break the TP4 GPU-KV-capacity wall at higher concurrency. - # At TP4 the ~121 GiB KV pool held only ~12 resident ~90k-token contexts, so - # throughput plateaued (~160 tok/s) and preemption thrashed from conc16 up. - # TP8 doubles GPUs -> ~2x KV pool + faster per-token decode. + # TP8, 3600s. Compares three KV tiers on the agentic trace. At TP8 the + # GPU-only (none) path collapses under load (KV-capacity thrash), so it is + # only swept at low conc [4,8] where it is viable; the dram offload backends + # (LMCache, Mooncake) carry the high-conc [16,32,48] range where they hold + # throughput by keeping the GPU KV pool from thrashing. - dram-utilization: 0.80 - duration: 900 + duration: 3600 search-space: - - { tp: 8, kv-offloading: none, conc-list: [16, 32, 48] } + - { tp: 8, kv-offloading: none, conc-list: [4, 8] } - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32, 48] } - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: mooncake, version: "source-main" }, conc-list: [16, 32, 48] } diff --git a/configs/smoke-kimik2.7-mooncake.yaml b/configs/smoke-kimik2.7-mooncake.yaml deleted file mode 100644 index 2b91c74ea6..0000000000 --- a/configs/smoke-kimik2.7-mooncake.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Temporary overlay to dispatch ONLY the Mooncake KV-offload cells for the -# kimik2.7 agentic TP8 smoke, so the in-flight none/lmcache sweep is not -# rerun. Same config key + settings as configs/amd-master.yaml, mooncake only. -# Remove once the 3-way none/lmcache/mooncake comparison is complete. -kimik2.7-fp4-mi355x-vllm-agentic: - image: vllm/vllm-openai-rocm:v0.24.0 - model: amd/Kimi-K2.7-Code-MXFP4 - model-prefix: kimik2.7 - runner: cluster:mi355x-amds - precision: fp4 - framework: vllm - multinode: false - scenarios: - agentic-coding: - - dram-utilization: 0.80 - duration: 900 - search-space: - - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: mooncake, version: "source-main" }, conc-list: [16, 32, 48] } From a8287d599a8f4045a27da159f95620b7036cb6bd Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 14 Jul 2026 10:02:22 -0500 Subject: [PATCH 13/19] fix(agentic): install Mooncake master binary --- benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh index e2c6a019a5..d9cdfec603 100755 --- a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh +++ b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh @@ -235,8 +235,16 @@ case "$OFFLOAD_MODE" in cd .. # Produces a self-contained wheel under mooncake-wheel/dist/. bash scripts/build_wheel.sh "$MOONCAKE_PYVER" - pip install --force-reinstall mooncake-wheel/dist/*.whl ) + pip install --force-reinstall mooncake-wheel/dist/*.whl + + # CMake installs the Python package into the user site, which + # shadows the wheel installed by pip. Ensure the CLI wrapper can + # find the native master binary in the package it imports. + MOONCAKE_PACKAGE_DIR=$(python3 -c 'import pathlib, mooncake; print(pathlib.Path(mooncake.__file__).parent)') + install -m 0755 build/mooncake-store/src/mooncake_master \ + "$MOONCAKE_PACKAGE_DIR/mooncake_master" ) python3 -c "from mooncake.store import MooncakeDistributedStore" >/dev/null + test -x "$(python3 -c 'import pathlib, mooncake; print(pathlib.Path(mooncake.__file__).parent / "mooncake_master")')" fi MOONCAKE_MASTER_PORT=$((PORT + 12000)) From 7ba22b7cd25ef8b814d3d82a8af0980a15ab60cf Mon Sep 17 00:00:00 2001 From: hyukjlee Date: Wed, 15 Jul 2026 17:50:01 +0900 Subject: [PATCH 14/19] [AMD][AgentX] kimik2.7: explicit AITER-MLA=0 + EP1-vs-EP8 900s tune sweep - Set VLLM_ROCM_USE_AITER_MLA=0 explicitly (64 KV heads incompatible with the ROCm AITER-MLA kernel; was only working via implicit fallback). - Add kimik2.7-fp4-mi355x-vllm-agentic-tune config key: TP8+LMCache, EP1 vs EP8 at conc[16,32], 900s. Probes whether expert parallelism improves perf (current record sweep runs EP=1 on a large MoE). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../agentic/kimik2.7_fp4_mi355x.sh | 6 ++++++ configs/amd-master.yaml | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh index d9cdfec603..4f10ba6ef3 100755 --- a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh +++ b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh @@ -53,6 +53,12 @@ if [[ "$version" == "" || ${version:-0} -lt 177 ]]; then fi export VLLM_ROCM_USE_AITER=1 +# amd/Kimi-K2.7-Code-MXFP4 has 64 KV heads; the ROCm AITER-MLA kernel only +# supports 16 or 128 heads, so it MUST be disabled for this model. Previously +# left unset (inherited master=1) and only worked via vLLM's implicit backend +# fallback -- make it explicit so a fallback/backend-selection change (or the +# --block-size=1 AITER-MLA forcing path) can't turn this into a hard crash. +export VLLM_ROCM_USE_AITER_MLA=0 export VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4 # Avoid intermittent symm_mem all-reduce rendezvous hang at engine init on # MI35x nodes (see KIMIK27_CONC64_LMCACHE_RUNBOOK error #4). diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index f998b475ba..c3b6c8ef90 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -571,6 +571,27 @@ kimik2.7-fp4-mi355x-vllm-agentic: - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: mooncake, version: "source-main" }, conc-list: [16, 32, 48] } +# Perf-tuning experiment key (same recipe as the record sweep above, via +# model-prefix kimik2.7). Wave 1: does expert parallelism help? Compares EP1 +# (current) vs EP8 at TP8+LMCache. Dispatched at 900s via e2e-tests duration +# override to verify the perf delta before committing a full 3600s run. +kimik2.7-fp4-mi355x-vllm-agentic-tune: + image: vllm/vllm-openai-rocm:v0.24.0 + model: amd/Kimi-K2.7-Code-MXFP4 + model-prefix: kimik2.7 + runner: cluster:mi355x-amds + precision: fp4 + framework: vllm + multinode: false + scenarios: + agentic-coding: + - dram-utilization: 0.80 + duration: 900 + search-space: + - { tp: 8, ep: 1, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32] } + - { tp: 8, ep: 8, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32] } + + kimik2.5-fp4-mi355x-atom: image: rocm/atom:rocm7.2.4_ubuntu24.04_py3.12_pytorch_release_2.10.0_atom0.1.4_202607091539 model: amd/Kimi-K2.5-MXFP4 From a35a71f8dfe25c28e2d66334a748cfd8018f813b Mon Sep 17 00:00:00 2001 From: hyukjlee Date: Wed, 15 Jul 2026 17:57:10 +0900 Subject: [PATCH 15/19] [AMD][AgentX] kimik2.7: add DEP (DP-attention + EP) path + 900s tune sweep Wire DP_ATTENTION into the vLLM recipe, mirroring dsv4_fp4_b300_vllm.sh: - DP_ATTENTION=true -> TP1 x DP=$TP with --enable-expert-parallel (experts EP-sharded across DP ranks), fronted by vllm-router on $PORT (consistent_hash + X-session affinity from aiperf's X-Correlation-ID). DP engine binds $PORT+1. - DP_ATTENTION=false -> unchanged pure-TP path on $PORT. - Add DP_ATTENTION to check_env_vars; clean up ROUTER_PID on exit. Retarget the -tune config key from the (non-working) EP1-vs-EP8 probe to a scaling experiment: pure-TP8 vs DEP, each with LMCache/Mooncake, conc[16,32,48], 900s. Aims for a throughput curve that grows with concurrency instead of the GPU-KV-capacity collapse the pure-TP path hits at conc>=16. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../agentic/kimik2.7_fp4_mi355x.sh | 56 +++++++++++++++++-- configs/amd-master.yaml | 13 +++-- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh index 4f10ba6ef3..0dd990d927 100755 --- a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh +++ b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh @@ -13,7 +13,7 @@ set -x source "$(dirname "$0")/../../benchmark_lib.sh" -check_env_vars MODEL TP CONC KV_OFFLOADING TOTAL_CPU_DRAM_GB RESULT_DIR DURATION EP_SIZE +check_env_vars MODEL TP CONC KV_OFFLOADING TOTAL_CPU_DRAM_GB RESULT_DIR DURATION EP_SIZE DP_ATTENTION if [[ -n "${SLURM_JOB_ID:-}" ]]; then echo "JOB $SLURM_JOB_ID running on ${SLURMD_NODENAME:-unknown}" @@ -76,8 +76,13 @@ PREFIX_CACHE_ARGS=() # ---- Offload service cleanup ------------------------------------------------ LMCACHE_PID="" MOONCAKE_MASTER_PID="" +ROUTER_PID="" cleanup_offload_services() { + if [[ -n "$ROUTER_PID" ]] && kill -0 "$ROUTER_PID" 2>/dev/null; then + kill "$ROUTER_PID" 2>/dev/null || true + wait "$ROUTER_PID" 2>/dev/null || true + fi if [[ -n "$LMCACHE_PID" ]] && kill -0 "$LMCACHE_PID" 2>/dev/null; then kill "$LMCACHE_PID" 2>/dev/null || true wait "$LMCACHE_PID" 2>/dev/null || true @@ -305,6 +310,28 @@ if [ "$EP_SIZE" -gt 1 ]; then EP_ARGS=(--enable-expert-parallel) fi +# Parallelism layout: +# DP_ATTENTION=false -> pure TP: attention TP-sharded across all $TP GPUs in a +# single engine (low TPOT, capacity-capped at high CONC). +# DP_ATTENTION=true -> DEP: per-DP-rank attention (TP1 x DP=$TP) with experts +# EP-sharded across the DP ranks (requires EP_SIZE>1). Grows KV capacity + +# decode width with concurrency. Mirrors dsv4_fp4_b300_vllm.sh. +PARALLEL_ARGS=(--tensor-parallel-size="$TP") +USE_VLLM_ROUTER=false +VLLM_BACKEND_PORT="$PORT" +if [ "$DP_ATTENTION" = "true" ]; then + PARALLEL_ARGS=(--tensor-parallel-size=1 --data-parallel-size="$TP") + USE_VLLM_ROUTER=true + VLLM_BACKEND_PORT=$((PORT + 1)) + VLLM_ROUTER_METRICS_PORT=$((PORT + 10000)) + # vllm-router expands the one HTTP backend into one logical worker per DP + # rank and sends X-data-parallel-rank per request; consistent_hash pins each + # conversation to a rank so its prefix cache stays warm. aiperf's stable + # X-Correlation-ID is aliased to the router's X-Session-ID for that affinity. + export AIPERF_HTTP_X_SESSION_ID_FROM_CORRELATION_ID=1 + pip install --quiet "vllm-router==0.1.14" +fi + echo "Starting vllm server..." export PYTHONNOUSERSITE=1 @@ -312,8 +339,8 @@ export PYTHONNOUSERSITE=1 VLLM_CMD=( vllm serve "$MODEL_PATH" --served-model-name "$MODEL" --host 0.0.0.0 - --port "$PORT" - --tensor-parallel-size="$TP" + --port "$VLLM_BACKEND_PORT" + "${PARALLEL_ARGS[@]}" "${EP_ARGS[@]}" --gpu-memory-utilization 0.90 --block-size=1 @@ -329,7 +356,28 @@ printf '\n' | tee -a "$RESULT_DIR/vllm_command.txt" SERVER_PID=$! echo "Server PID: $SERVER_PID" -wait_for_server_ready --port "$PORT" --server-log "$SERVER_LOG" --server-pid "$SERVER_PID" +wait_for_server_ready --port "$VLLM_BACKEND_PORT" --server-log "$SERVER_LOG" --server-pid "$SERVER_PID" + +# In DEP mode, front the DP engine with vllm-router on $PORT so the agentic +# client (which targets $PORT) load-balances across DP ranks with prefix +# affinity. Pure-TP serves the client directly on $PORT. +if [ "$USE_VLLM_ROUTER" = "true" ]; then + ROUTER_LOG="$RESULT_DIR/router.log" + echo "Starting vLLM router on port $PORT for $TP DP ranks..." + vllm-router \ + --worker-urls "http://localhost:$VLLM_BACKEND_PORT" \ + --policy consistent_hash \ + --intra-node-data-parallel-size "$TP" \ + --host 0.0.0.0 \ + --port "$PORT" \ + --prometheus-host 127.0.0.1 \ + --prometheus-port "$VLLM_ROUTER_METRICS_PORT" \ + --request-timeout-secs 14400 \ + --disable-retries > "$ROUTER_LOG" 2>&1 & + ROUTER_PID=$! + echo "Router PID: $ROUTER_PID" + wait_for_server_ready --port "$PORT" --server-log "$ROUTER_LOG" --server-pid "$ROUTER_PID" +fi # ---- Run benchmark ---------------------------------------------------------- build_replay_cmd "$RESULT_DIR" diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index c3b6c8ef90..f39afc9052 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -572,9 +572,11 @@ kimik2.7-fp4-mi355x-vllm-agentic: # Perf-tuning experiment key (same recipe as the record sweep above, via -# model-prefix kimik2.7). Wave 1: does expert parallelism help? Compares EP1 -# (current) vs EP8 at TP8+LMCache. Dispatched at 900s via e2e-tests duration -# override to verify the perf delta before committing a full 3600s run. +# model-prefix kimik2.7). Goal: get a throughput curve that scales with +# concurrency instead of collapsing. Compares pure-TP8 (current, capacity-capped) +# vs DEP (data-parallel attention TP1xDP8 + expert parallelism), each with an +# LMCache/Mooncake KV tier. Dispatched at 900s via e2e-tests duration override to +# verify the perf delta before committing a full 3600s run. kimik2.7-fp4-mi355x-vllm-agentic-tune: image: vllm/vllm-openai-rocm:v0.24.0 model: amd/Kimi-K2.7-Code-MXFP4 @@ -588,8 +590,9 @@ kimik2.7-fp4-mi355x-vllm-agentic-tune: - dram-utilization: 0.80 duration: 900 search-space: - - { tp: 8, ep: 1, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32] } - - { tp: 8, ep: 8, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32] } + - { tp: 8, dp-attn: false, ep: 1, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32, 48] } + - { tp: 8, dp-attn: true, ep: 8, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32, 48] } + - { tp: 8, dp-attn: true, ep: 8, kv-offloading: dram, kv-offload-backend: { name: mooncake, version: "source-main" }, conc-list: [16, 32, 48] } kimik2.5-fp4-mi355x-atom: From a63228b41f757b99ed6849585682f827638b0b91 Mon Sep 17 00:00:00 2001 From: hyukjlee Date: Wed, 15 Jul 2026 18:10:17 +0900 Subject: [PATCH 16/19] [AMD][AgentX] kimik2.7: drop --block-size=1 (incompatible with TRITON_MLA) With VLLM_ROCM_USE_AITER_MLA=0 the only ROCm MLA backend is TRITON_MLA, which rejects block_size=1 ("No valid attention backend found ... TRITON_MLA: block_size not supported"). --block-size=1 only ever existed to force the now-disabled AITER-MLA path. Drop it and let vLLM pick a TRITON_MLA-valid default, matching AMD's reference serve command (AITER_MLA=0, no --block-size). Fixes bringup failure for every cell (pure-TP and DEP alike). Co-Authored-By: Claude Opus 4.8 (1M context) --- benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh index 0dd990d927..cdcc3742ab 100755 --- a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh +++ b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh @@ -54,10 +54,11 @@ fi export VLLM_ROCM_USE_AITER=1 # amd/Kimi-K2.7-Code-MXFP4 has 64 KV heads; the ROCm AITER-MLA kernel only -# supports 16 or 128 heads, so it MUST be disabled for this model. Previously -# left unset (inherited master=1) and only worked via vLLM's implicit backend -# fallback -- make it explicit so a fallback/backend-selection change (or the -# --block-size=1 AITER-MLA forcing path) can't turn this into a hard crash. +# supports 16 or 128 heads, so it MUST be disabled for this model. With AITER-MLA +# off, ROCm serves MLA via TRITON_MLA, which does NOT support block_size=1 -- so +# this recipe passes no --block-size and lets vLLM pick a TRITON_MLA-valid +# default (matches AMD's reference serve command for this model). The old +# --block-size=1 only existed to force the (now-disabled) AITER-MLA path. export VLLM_ROCM_USE_AITER_MLA=0 export VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4 # Avoid intermittent symm_mem all-reduce rendezvous hang at engine init on @@ -343,7 +344,6 @@ VLLM_CMD=( "${PARALLEL_ARGS[@]}" "${EP_ARGS[@]}" --gpu-memory-utilization 0.90 - --block-size=1 --trust-remote-code --max-num-seqs "$CONC" --mm-encoder-tp-mode data From 1092b8c48d439472996dbfcdf93c2b3a4877865a Mon Sep 17 00:00:00 2001 From: hyukjlee Date: Wed, 15 Jul 2026 18:38:51 +0900 Subject: [PATCH 17/19] [AMD][AgentX] kimik2.7: split Mooncake into its own tune key (fail-fast isolation) The DEP Mooncake c16 cell fails fast at bringup; GH matrix fail-fast then cancels the still-running LMCache/pure-TP cells before they finish. Split the LMCache scaling experiment (-tune) from Mooncake (-tune-mc) so a Mooncake bringup failure can't poison the scaling run, and so Mooncake runs alone and uploads its own server_logs for diagnosis. Co-Authored-By: Claude Opus 4.8 (1M context) --- configs/amd-master.yaml | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index f39afc9052..d06abe997b 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -574,9 +574,10 @@ kimik2.7-fp4-mi355x-vllm-agentic: # Perf-tuning experiment key (same recipe as the record sweep above, via # model-prefix kimik2.7). Goal: get a throughput curve that scales with # concurrency instead of collapsing. Compares pure-TP8 (current, capacity-capped) -# vs DEP (data-parallel attention TP1xDP8 + expert parallelism), each with an -# LMCache/Mooncake KV tier. Dispatched at 900s via e2e-tests duration override to -# verify the perf delta before committing a full 3600s run. +# vs DEP (data-parallel attention TP1xDP8 + expert parallelism), both with LMCache. +# Dispatched at 900s via e2e-tests duration override to verify the perf delta +# before committing a full 3600s run. Mooncake is split into a separate key +# (-tune-mc) so a fast Mooncake bringup failure can't fail-fast-cancel these cells. kimik2.7-fp4-mi355x-vllm-agentic-tune: image: vllm/vllm-openai-rocm:v0.24.0 model: amd/Kimi-K2.7-Code-MXFP4 @@ -592,7 +593,22 @@ kimik2.7-fp4-mi355x-vllm-agentic-tune: search-space: - { tp: 8, dp-attn: false, ep: 1, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32, 48] } - { tp: 8, dp-attn: true, ep: 8, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32, 48] } - - { tp: 8, dp-attn: true, ep: 8, kv-offloading: dram, kv-offload-backend: { name: mooncake, version: "source-main" }, conc-list: [16, 32, 48] } + +# Mooncake-under-DEP, isolated so its failure can't cancel the LMCache scaling run. +kimik2.7-fp4-mi355x-vllm-agentic-tune-mc: + image: vllm/vllm-openai-rocm:v0.24.0 + model: amd/Kimi-K2.7-Code-MXFP4 + model-prefix: kimik2.7 + runner: cluster:mi355x-amds + precision: fp4 + framework: vllm + multinode: false + scenarios: + agentic-coding: + - dram-utilization: 0.80 + duration: 900 + search-space: + - { tp: 8, dp-attn: true, ep: 8, kv-offloading: dram, kv-offload-backend: { name: mooncake, version: "source-main" }, conc-list: [16, 32, 48] } kimik2.5-fp4-mi355x-atom: From fa6023de225a347c5fad35d8d2c21828d5073c53 Mon Sep 17 00:00:00 2001 From: hyukjlee Date: Thu, 16 Jul 2026 23:11:02 +0900 Subject: [PATCH 18/19] =?UTF-8?q?[AMD][AgentX]=20kimik2.7:=20best-config?= =?UTF-8?q?=20sweep=20=E2=80=94=20AITER-MLA=20+=20none[4,8]/lmcache[16]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adopt the best-performing config from the sweep analysis: - Attention: keep AITER-MLA ON (VLLM_ROCM_USE_AITER_MLA=1) + --block-size=1. AITER-MLA is ~3x faster than TRITON_MLA on the agentic trace; deliberately chosen for throughput despite AMD's 16/128-head guidance (revisit if accuracy validation shows the 64-head path is wrong). - Record sweep narrowed to the best cell per regime: none [4,8] (GPU-only viable at low conc, peaks ~26.7 tok/s/GPU at c8), LMCache [16] (crossover where DRAM offload overtakes none). Dropped Mooncake and lmcache c32/48 (no headroom over this envelope) and the experimental -tune/-tune-mc keys. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../agentic/kimik2.7_fp4_mi355x.sh | 15 +++--- configs/amd-master.yaml | 54 +++---------------- 2 files changed, 15 insertions(+), 54 deletions(-) diff --git a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh index cdcc3742ab..6d24884d44 100755 --- a/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh +++ b/benchmarks/single_node/agentic/kimik2.7_fp4_mi355x.sh @@ -53,13 +53,13 @@ if [[ "$version" == "" || ${version:-0} -lt 177 ]]; then fi export VLLM_ROCM_USE_AITER=1 -# amd/Kimi-K2.7-Code-MXFP4 has 64 KV heads; the ROCm AITER-MLA kernel only -# supports 16 or 128 heads, so it MUST be disabled for this model. With AITER-MLA -# off, ROCm serves MLA via TRITON_MLA, which does NOT support block_size=1 -- so -# this recipe passes no --block-size and lets vLLM pick a TRITON_MLA-valid -# default (matches AMD's reference serve command for this model). The old -# --block-size=1 only existed to force the (now-disabled) AITER-MLA path. -export VLLM_ROCM_USE_AITER_MLA=0 +# This model has 64 KV heads. AMD flags AITER-MLA as officially supporting only +# 16/128 heads, but empirically it runs this model and (forced via --block-size=1 +# below) is the ONLY ROCm MLA backend that accepts block_size=1 and is ~3x faster +# than TRITON_MLA on the agentic trace (best-perf config, run 29337493492). +# Deliberately keeping AITER-MLA ON for throughput; revisit if accuracy validation +# shows the 64-head path is numerically wrong (then AITER_MLA=0 + drop block-size). +export VLLM_ROCM_USE_AITER_MLA=1 export VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4 # Avoid intermittent symm_mem all-reduce rendezvous hang at engine init on # MI35x nodes (see KIMIK27_CONC64_LMCACHE_RUNBOOK error #4). @@ -344,6 +344,7 @@ VLLM_CMD=( "${PARALLEL_ARGS[@]}" "${EP_ARGS[@]}" --gpu-memory-utilization 0.90 + --block-size=1 --trust-remote-code --max-num-seqs "$CONC" --mm-encoder-tp-mode data diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index d06abe997b..d46cee0fea 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -558,57 +558,17 @@ kimik2.7-fp4-mi355x-vllm-agentic: multinode: false scenarios: agentic-coding: - # TP8, 3600s. Compares three KV tiers on the agentic trace. At TP8 the - # GPU-only (none) path collapses under load (KV-capacity thrash), so it is - # only swept at low conc [4,8] where it is viable; the dram offload backends - # (LMCache, Mooncake) carry the high-conc [16,32,48] range where they hold - # throughput by keeping the GPU KV pool from thrashing. + # TP8, 3600s. Best-config sweep on the agentic trace, one KV tier per regime: + # GPU-only (none) is only viable at low conc [4,8] (peaks ~26.7 tok/s/GPU at + # c8, then collapses at the KV-capacity wall); LMCache DRAM offload carries the + # high-conc side and holds throughput where none thrashes, so it is swept at + # c16 (the crossover where it overtakes none). Mooncake and c32/48 dropped: + # they added no throughput headroom over this best-config envelope. - dram-utilization: 0.80 duration: 3600 search-space: - { tp: 8, kv-offloading: none, conc-list: [4, 8] } - - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32, 48] } - - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: mooncake, version: "source-main" }, conc-list: [16, 32, 48] } - - -# Perf-tuning experiment key (same recipe as the record sweep above, via -# model-prefix kimik2.7). Goal: get a throughput curve that scales with -# concurrency instead of collapsing. Compares pure-TP8 (current, capacity-capped) -# vs DEP (data-parallel attention TP1xDP8 + expert parallelism), both with LMCache. -# Dispatched at 900s via e2e-tests duration override to verify the perf delta -# before committing a full 3600s run. Mooncake is split into a separate key -# (-tune-mc) so a fast Mooncake bringup failure can't fail-fast-cancel these cells. -kimik2.7-fp4-mi355x-vllm-agentic-tune: - image: vllm/vllm-openai-rocm:v0.24.0 - model: amd/Kimi-K2.7-Code-MXFP4 - model-prefix: kimik2.7 - runner: cluster:mi355x-amds - precision: fp4 - framework: vllm - multinode: false - scenarios: - agentic-coding: - - dram-utilization: 0.80 - duration: 900 - search-space: - - { tp: 8, dp-attn: false, ep: 1, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32, 48] } - - { tp: 8, dp-attn: true, ep: 8, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16, 32, 48] } - -# Mooncake-under-DEP, isolated so its failure can't cancel the LMCache scaling run. -kimik2.7-fp4-mi355x-vllm-agentic-tune-mc: - image: vllm/vllm-openai-rocm:v0.24.0 - model: amd/Kimi-K2.7-Code-MXFP4 - model-prefix: kimik2.7 - runner: cluster:mi355x-amds - precision: fp4 - framework: vllm - multinode: false - scenarios: - agentic-coding: - - dram-utilization: 0.80 - duration: 900 - search-space: - - { tp: 8, dp-attn: true, ep: 8, kv-offloading: dram, kv-offload-backend: { name: mooncake, version: "source-main" }, conc-list: [16, 32, 48] } + - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16] } kimik2.5-fp4-mi355x-atom: From 987a153a95db6cd40082535f87619994fd47b951 Mon Sep 17 00:00:00 2001 From: hyukjlee Date: Tue, 21 Jul 2026 08:53:53 -0700 Subject: [PATCH 19/19] [AMD][AgentX] kimik2.7: ship TP4 GPU-only none[1,2,4,8] (drop TP8/offload arms) Settle PR #2126 on the strongest per-GPU config from the 3600s TP4/TP8 sweeps: TP4 GPU-only (none) + prefix caching, swept conc [1,2,4,8]. - TP4 is ~2x more per-GPU efficient than TP8 on this KV-bound agentic trace (none peaks ~49.6 tok/s/GPU at c8 vs 26.8 at TP8), and GPU-only avoids the CPU/DRAM-offload interactivity penalty (LMCache cells sat ~13-15 tok/s/user vs ~48 for none c4). - conc capped at 8: c8 is the last stable point before the GPU-KV-capacity wall (GPU-KV ~74%); none collapses past c8 and the offload tiers only lose per-GPU throughput here. Drop the TP8 arms + dram/LMCache + dram/Mooncake. - No recipe change: TP4 none was already validated green (run 29003473063). Co-Authored-By: Claude Opus 4.8 (1M context) --- configs/amd-master.yaml | 17 +++++++++-------- perf-changelog.yaml | 8 ++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index d46cee0fea..c1bd7e5504 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -558,17 +558,18 @@ kimik2.7-fp4-mi355x-vllm-agentic: multinode: false scenarios: agentic-coding: - # TP8, 3600s. Best-config sweep on the agentic trace, one KV tier per regime: - # GPU-only (none) is only viable at low conc [4,8] (peaks ~26.7 tok/s/GPU at - # c8, then collapses at the KV-capacity wall); LMCache DRAM offload carries the - # high-conc side and holds throughput where none thrashes, so it is swept at - # c16 (the crossover where it overtakes none). Mooncake and c32/48 dropped: - # they added no throughput headroom over this best-config envelope. + # TP4, GPU-only (none) + prefix caching, 3600s. TP4 is ~2x more per-GPU + # efficient than TP8 on this KV-bound trace (none peaks ~49.6 tok/s/GPU at c8 + # vs 26.8 at TP8), and GPU-only avoids the CPU/DRAM-offload interactivity + # penalty (lmcache cells sit at 13-15 tok/s/user; none c4 is ~48). Swept + # [1,2,4,8]: c8 is the last stable point before the GPU-KV-capacity wall + # (GPU-KV ~74%), c1/c2/c4 trace the low-latency frontier. none collapses past + # c8 (c16 dropped), and the DRAM-offload tiers only lose per-GPU throughput + # here, so TP8 and the lmcache/mooncake arms are dropped. - dram-utilization: 0.80 duration: 3600 search-space: - - { tp: 8, kv-offloading: none, conc-list: [4, 8] } - - { tp: 8, kv-offloading: dram, kv-offload-backend: { name: lmcache, version: "aaf7c0d3" }, conc-list: [16] } + - { tp: 4, kv-offloading: none, conc-list: [1, 2, 4, 8] } kimik2.5-fp4-mi355x-atom: diff --git a/perf-changelog.yaml b/perf-changelog.yaml index 0277085f49..c18261b75c 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -5019,3 +5019,11 @@ - "Add a Mooncake KV-offload backend to the recipe (embedded MooncakeStoreConnector store). Built from source for ROCm via Mooncake's build_wheel.sh and pip-installed so the mooncake package lands in site-packages and is importable from the vLLM worker subprocesses (a bare make install left workers unable to import it)" - "Adds optional per-scenario 'duration' override to the agentic-coding config schema (defaults to 3600s when unset)" pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2126 + +- config-keys: + - kimik2.7-fp4-mi355x-vllm-agentic + description: + - "Settle on TP4 GPU-only (none) + prefix caching as the shipped config, swept conc [1,2,4,8] (3600s trace replay); drop the TP8 arms and the dram/LMCache + dram/Mooncake offload tiers" + - "TP4 is ~2x more per-GPU efficient than TP8 on this KV-bound agentic trace (none peaks ~49.6 tok/s/GPU at c8 vs 26.8 at TP8, from the 3600s TP4/TP8 sweeps), and GPU-only avoids the CPU/DRAM-offload interactivity penalty (LMCache cells sat at ~13-15 tok/s/user vs ~48 for none c4)" + - "conc capped at 8: c8 is the last stable point before the GPU-KV-capacity wall (GPU-KV ~74%); none collapses past c8 and the DRAM-offload tiers only lose per-GPU throughput at this scale, so they add no headroom" + pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2126