Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f296829
[AMD] [WIP] [AGENTX] KIMI-K3 Perf Tuning
AjithSirra Aug 13, 2026
d28c525
[AMD] [WIP] [AGENTX] KIMI-K3 Perf Tuning
AjithSirra Aug 13, 2026
38faee4
[AMD] [WIP] [AGENTX] KIMI-K3 Perf Tuning
AjithSirra Aug 13, 2026
c0119e6
[AMD] [AGENTX] KIMI-K3 Perf Tuning
AjithSirra Aug 14, 2026
ad8f584
Merge branch 'main' into amd/kimi-k3-agentic-perf-tuning
ajith-sirra-amd Aug 14, 2026
eb81b48
[AMD] [AGENTX] KIMI-K3 Perf Tuning
AjithSirra Aug 14, 2026
ed6c730
[AMD] [AGENTX] KIMI-K3 Perf Tuning
AjithSirra Aug 14, 2026
b7d1f4f
Merge branch 'main' into amd/kimi-k3-agentic-perf-tuning
ajith-sirra-amd Aug 14, 2026
8366815
[AMD] [WIP] [AGENTX] KIMI-K3 Perf with fixes applied.
AjithSirra Aug 14, 2026
9bc673b
[AMD] [WIP] [AGENTX] KIMI-K3 Perf with fixes applied.
AjithSirra Aug 14, 2026
c1215ff
Merge branch 'amd/kimi-k3-agentic-perf-tuning' of https://github.com/…
AjithSirra Aug 14, 2026
f080865
[AMD] [WIP] [AGENTX] KIMI-K3 Perf with fixes applied.
AjithSirra Aug 14, 2026
4901088
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied & Perf Boost
AjithSirra Aug 14, 2026
84bc103
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied & Perf Boost
AjithSirra Aug 14, 2026
aab67c0
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 14, 2026
57fd591
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 14, 2026
081d1b8
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 14, 2026
8a52651
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 14, 2026
e985b3e
Merge branch 'main' into amd/kimi-k3-agentic-perf-tuning
ajith-sirra-amd Aug 14, 2026
9a96547
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 15, 2026
9dacd22
Merge branch 'main' into amd/kimi-k3-agentic-perf-tuning
ajith-sirra-amd Aug 15, 2026
d820ae1
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 15, 2026
25d1e54
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 15, 2026
bbe304c
Merge branch 'amd/kimi-k3-agentic-perf-tuning' of https://github.com/…
AjithSirra Aug 15, 2026
8988497
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 15, 2026
7ef3ff8
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 16, 2026
1b1dd63
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 16, 2026
a72c8b9
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 17, 2026
127db36
Merge branch 'main' into amd/kimi-k3-agentic-perf-tuning
ajith-sirra-amd Aug 17, 2026
cbfe9d7
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 17, 2026
99cc45e
Merge branch 'amd/kimi-k3-agentic-perf-tuning' of https://github.com/…
AjithSirra Aug 17, 2026
4c50610
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 17, 2026
bf0bf1b
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 17, 2026
71313ac
[AMD] [WIP] [AGENTX] KIMI-K3 with fixes applied, Perf Boost & stability.
AjithSirra Aug 17, 2026
e631afb
Merge branch 'main' into amd/kimi-k3-agentic-perf-tuning
ajith-sirra-amd Aug 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions benchmarks/single_node/agentic/apply_aiter_pybind11_fix.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/usr/bin/env bash
# Fix AITER JIT modules building against a different pybind11 than the prebuilt
# .so files shipped in the image.
#
# Symptom (kills the server during warmup, before it binds):
# TypeError: fmha_fwd_bf16_opus_fwd(): incompatible function arguments
# RuntimeError: Engine core initialization failed
#
# Cause: aiter/jit/utils/cpp_extension.py adds the standalone pybind11 include
# via -I, which outranks the -isystem path holding torch's bundled pybind11.
# The prebuilt modules (module_aiter_core.so) use torch's pybind11
# (PYBIND11_INTERNALS_VERSION 11); the standalone package is version 12.
# pybind11 keeps a SEPARATE type registry per internals id, so the JIT module
# cannot see aiter_tensor_t registered by the core module.
#
# Effect: lets ROCM_AITER_FA be used for MLA prefill instead of falling back to
# FLASH_ATTN. Measured on 8x MI355X / Kimi-K3 MXFP4 TP8:
# ~24k ctx 12,953 -> 13,524 tok/s (+4.4%)
# ~93k ctx 11,174 -> 13,423 tok/s (+20.1%)
#
# Idempotent: safe to run repeatedly. No-op if already patched or not needed.
set -euo pipefail

PY=${PYTHON:-python3}

TARGET=$($PY - <<'EOF'
import os
try:
import aiter.jit.utils.cpp_extension as m
print(os.path.abspath(m.__file__))
except Exception:
print("")
EOF
)

if [ -z "$TARGET" ] || [ ! -f "$TARGET" ]; then
echo "[aiter-fix] aiter cpp_extension not found; nothing to do."
exit 0
fi

# Is there actually an internals-version mismatch to fix?
NEED=$($PY - <<'EOF'
import os, re
try:
import torch, pybind11
except Exception:
print("no"); raise SystemExit
def ver(p):
f = os.path.join(p, "pybind11", "detail", "internals.h")
if not os.path.isfile(f):
return None
m = re.search(r"define\s+PYBIND11_INTERNALS_VERSION\s+(\d+)", open(f).read())
return int(m.group(1)) if m else None
t = ver(os.path.join(os.path.dirname(torch.__file__), "include"))
s = ver(pybind11.get_include())
print("yes" if (t is not None and s is not None and t != s) else "no")
EOF
)

if [ "$NEED" != "yes" ]; then
echo "[aiter-fix] pybind11 internals versions already agree; no patch needed."
exit 0
fi

if grep -q "_use_torch_pybind11" "$TARGET"; then
echo "[aiter-fix] already patched: $TARGET"
else
cp -n "$TARGET" "$TARGET.orig" || true
$PY - "$TARGET" <<'EOF'
import sys, io
path = sys.argv[1]
src = io.open(path, encoding="utf-8").read()
old = " extra_include_paths.append(pybind11.get_include())\n"
new = (
" # PATCHED: prefer torch's bundled pybind11 so JIT modules land in the\n"
" # same pybind11 type registry as the prebuilt .so files. Mismatched\n"
" # PYBIND11_INTERNALS_VERSION otherwise yields:\n"
" # TypeError: ...(): incompatible function arguments\n"
" _use_torch_pybind11 = False\n"
" if not torch_exclude:\n"
" _use_torch_pybind11 = os.path.isdir(\n"
" os.path.join(TORCH_INCLUDE_ROOT, \"pybind11\")\n"
" )\n"
" if not _use_torch_pybind11:\n"
" extra_include_paths.append(pybind11.get_include())\n"
)
if old not in src:
sys.stderr.write("[aiter-fix] ERROR: anchor line not found; aborting.\n")
sys.exit(1)
if src.count(old) != 1:
sys.stderr.write("[aiter-fix] ERROR: anchor line not unique; aborting.\n")
sys.exit(1)
io.open(path, "w", encoding="utf-8").write(src.replace(old, new))
print("[aiter-fix] patched", path)
EOF
fi

# Drop JIT artifacts built against the wrong pybind11 so they rebuild.
# Ask aiter for its jit dir: it honours AITER_JIT_DIR and falls back to ~/.aiter
# when dist-packages is not writable, so deriving it from $TARGET is wrong.
JITDIR=$($PY -c 'from aiter.jit.core import get_user_jit_dir; print(get_user_jit_dir())' 2>/dev/null || true)
if [ -z "$JITDIR" ] || [ ! -d "$JITDIR" ]; then
JITDIR=$(dirname "$(dirname "$TARGET")")
fi
echo "[aiter-fix] jit dir: $JITDIR"
# Sweep every module, not just the one we happened to hit first: any module
# JIT-built before the patch carries the wrong internals id.
shopt -s nullglob
for so in "$JITDIR"/*.so; do
if grep -qa "__pybind11_internals_v12" "$so" 2>/dev/null; then
rm -f "$so"
rm -rf "$JITDIR/build/$(basename "${so%.so}")"
echo "[aiter-fix] removed stale v12 module: $(basename "$so")"
fi
done
shopt -u nullglob

echo "[aiter-fix] done."
65 changes: 65 additions & 0 deletions benchmarks/single_node/agentic/apply_triton_mla_cudagraph_fix.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env bash
# Let DSpark spec-decode keep FULL cudagraphs on ROCm.
#
# vllm/v1/attention/backends/mla/triton_mla.py declares
# TritonMLAMetadataBuilder._cudagraph_support = UNIFORM_SINGLE_TOKEN_DECODE
# which caps min_cg_support below UNIFORM_BATCH, so config/compilation.py:1443
# downgrades FULL_AND_PIECEWISE -> PIECEWISE whenever spec-decode is enabled:
# "CUDAGraphMode.FULL_AND_PIECEWISE is not supported with spec-decode for
# attention backend TritonMLABackend"
# v1/worker/gpu/spec_decode/dflash/speculator.py:110-127 then gives the DSpark
# drafter CUDAGraphMode.NONE -- fully eager, with NO warning logged. Every draft
# layer and the Markov head dispatch kernel-by-kernel from Python each step.
#
# TRITON_MLA cannot simply be swapped out: it is the only ROCm MLA backend with
# supports_non_causal_multi_token_decode = True, which the DSpark draft needs.
# ROCM_AITER_MLA fails with "non-causal attention not supported".
#
# The builder already sets supports_non_causal_multi_token_decode = True and
# calls _init_reorder_batch_threshold(1, supports_spec_as_decode=True) "so
# full-cudagraph capture admits it", so UNIFORM_BATCH is the consistent value.
#
# MEASURED on 8x MI355X, Kimi-K3 MXFP4 TP8, DSpark, single stream, 600-tok gens:
# before: 14.05 tok/s, ITL 71.16 ms (PIECEWISE, drafter eager)
# after : 77.65 tok/s, ITL 12.88 ms (FULL cudagraphs) = 5.52x
# output verified correct in both ("17*23" -> 391, finish_reason stop)
#
# Idempotent. No-op if already patched or if the anchor is absent.
set -euo pipefail
PY=${PYTHON:-python3}

TARGET=$($PY - <<'EOF'
import os
try:
import vllm.v1.attention.backends.mla.triton_mla as m
print(os.path.abspath(m.__file__))
except Exception:
print("")
EOF
)
if [ -z "$TARGET" ] || [ ! -f "$TARGET" ]; then
echo "[triton-mla-fix] triton_mla.py not found; nothing to do."
exit 0
fi
if grep -q "AttentionCGSupport.UNIFORM_BATCH" "$TARGET"; then
echo "[triton-mla-fix] already patched: $TARGET"
exit 0
fi
cp -n "$TARGET" "$TARGET.orig" || true
$PY - "$TARGET" <<'EOF'
import sys, io
path = sys.argv[1]
src = io.open(path, encoding="utf-8").read()
old = """ _cudagraph_support: ClassVar[AttentionCGSupport] = (
AttentionCGSupport.UNIFORM_SINGLE_TOKEN_DECODE
)"""
new = """ # PATCHED: UNIFORM_SINGLE_TOKEN_DECODE forced a PIECEWISE downgrade under
# spec-decode, which silently made the DSpark drafter fully eager.
_cudagraph_support: ClassVar[AttentionCGSupport] = AttentionCGSupport.UNIFORM_BATCH"""
if src.count(old) != 1:
sys.stderr.write("[triton-mla-fix] anchor missing or not unique; aborting.\n")
sys.exit(1)
io.open(path, "w", encoding="utf-8").write(src.replace(old, new))
print("[triton-mla-fix] patched", path)
EOF
echo "[triton-mla-fix] done."
52 changes: 51 additions & 1 deletion benchmarks/single_node/agentic/kimik3_fp4_mi355x_mtp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,31 @@ amd-smi || true
resolve_trace_source
install_agentic_deps

# ---- AITER pybind11 fix ------------------------------------------------------
# The image's prebuilt aiter .so files are compiled against torch's bundled
# pybind11 (PYBIND11_INTERNALS_VERSION 11), but aiter's JIT builder injects the
# standalone pybind11 3.1.0 (version 12) as a -I flag, which outranks the
# -isystem path holding torch's copy. pybind11 keeps a SEPARATE type registry
# per internals id, so a JIT-built module cannot see aiter_tensor_t registered
# by the prebuilt core, and the first call dies during model warmup with:
# TypeError: fmha_fwd_bf16_opus_fwd(): incompatible function arguments
# The script below is idempotent, verifies the mismatch actually exists before
# touching anything, and self-disables once the image ships a fixed aiter.
bash "$(dirname "$0")/apply_aiter_pybind11_fix.sh" || true

# ---- DSpark FULL-cudagraph fix ----------------------------------------------
# TritonMLA declares _cudagraph_support=UNIFORM_SINGLE_TOKEN_DECODE, which forces
# FULL_AND_PIECEWISE -> PIECEWISE under spec-decode and then silently gives the
# DSpark drafter CUDAGraphMode.NONE (fully eager). Measured on 8x MI355X, single
# stream 600-token generations: 14.05 -> 77.65 tok/s, ITL 71.16 -> 12.88 ms (5.52x),
# output verified correct. Idempotent; no-op if already patched.
bash "$(dirname "$0")/apply_triton_mla_cudagraph_fix.sh" || true

# ---- Reference env block ----------------------------------------------------
# Keep ALL of these. Commenting them out does not avoid the AITER FMHA crash:
# that crash is gated on VLLM_ROCM_USE_AITER alone (AiterFlashAttnPrefillBackend
# .is_available() consults only rocm_aiter_ops.is_enabled()), so disabling the
# others just loses the MoE kernels while keeping the failure.
export VLLM_ROCM_AITER_MLA_ASM_PADDING=asm
export VLLM_ROCM_USE_AITER=1
export SAFETENSORS_FAST_GPU=1
Expand Down Expand Up @@ -147,7 +171,7 @@ esac
fi

# ---- LLM server ------------------------------------------------------------
bash "$(dirname "$0")/apply_k3_container_patches.sh"


# ---- Parallelism ------------------------------------------------------------
EP_ARGS=()
Expand All @@ -171,6 +195,31 @@ else
)
fi

# ---- MLA prefill backend -----------------------------------------------------
# On ROCm the prefill priority is [ROCM_AITER_FA, FLASH_ATTN]. ROCM_AITER_FA
# JIT-builds module_fmha_fwd_bf16_opus at runtime; that module registers its own
# aiter_tensor_t, distinct from the one in the prebuilt module_aiter_core, so the
# first call dies with:
# TypeError: fmha_fwd_bf16_opus_fwd(): incompatible function arguments
# during compile_or_warm_up_model -> _dummy_run, before the server binds.
# Pinning FLASH_ATTN keeps every AITER MoE kernel (and its throughput) while
# skipping only the broken FMHA prefill path.
# UPDATE: the AITER packaging issue is now fixed at source by
# apply_aiter_pybind11_fix.sh (run above), so ROCM_AITER_FA is usable again and
# is the default. Measured on 8x MI355X / Kimi-K3 MXFP4 TP8, cold prefill:
# ~24k ctx FLASH_ATTN 12,953 -> AITER 13,524 tok/s (+4.4%)
# ~93k ctx FLASH_ATTN 11,174 -> AITER 13,423 tok/s (+20.1%)
# This workload averages ~99k input tokens, so the ~93k figure is the relevant
# one. Set MLA_PREFILL_BACKEND=FLASH_ATTN to fall back if AITER regresses.
MLA_PREFILL_BACKEND="${MLA_PREFILL_BACKEND:-ROCM_AITER_FA}"
MLA_PREFILL_ARGS=()
if [ -n "$MLA_PREFILL_BACKEND" ]; then
MLA_PREFILL_ARGS=(
--attention-config
"{\"mla_prefill_backend\":\"$MLA_PREFILL_BACKEND\"}"
)
fi
Comment on lines +229 to +236

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Minor dead-code nit: on line 214, MLA_PREFILL_BACKEND="${MLA_PREFILL_BACKEND:-ROCM_AITER_FA}" already guarantees the variable is non-empty (bash's :- fires on both unset and empty), so the if [ -n "$MLA_PREFILL_BACKEND" ] on line 216 is always true and the implicit empty-MLA_PREFILL_ARGS else-branch is unreachable. Consider dropping the guard and building MLA_PREFILL_ARGS unconditionally, matching how COMPILATION_CONFIG_ARGS/SPEC_ARGS are built elsewhere in this file.

Extended reasoning...

What the bug is: Line 214 sets MLA_PREFILL_BACKEND="${MLA_PREFILL_BACKEND:-ROCM_AITER_FA}". Bash's ${var:-default} form (with the colon) substitutes default whenever var is either unset or set to the empty string — this is distinct from ${var-default} (no colon), which only substitutes on unset. Because of the colon, after line 214 executes, $MLA_PREFILL_BACKEND is guaranteed to be non-empty: it is either the caller's non-empty override or the literal ROCM_AITER_FA fallback.

The code path: Line 216 then guards the array construction with if [ -n "$MLA_PREFILL_BACKEND" ]; then MLA_PREFILL_ARGS=(--attention-config ...); fi. Since the variable can never be empty at this point, the condition is always true, and the implicit else (which would leave MLA_PREFILL_ARGS=() empty) is dead code that can never execute — not even via MLA_PREFILL_BACKEND="" as an explicit env override, since that empty string is itself replaced by the default on line 214 before the check ever runs.

Why nothing catches this today: There's no test or lint that exercises unreachable branches in this shell script, and the guard reads as plausible defensive code at a glance (mirroring the real, reachable guards used for EP_ARGS at line ~199 and OFFLOAD_ARGS's case statement), so it's easy to miss that this particular guard's precondition was already foreclosed on the prior line.

Impact: None functionally — behavior is identical whether or not the if is present, since the branch it guards against can never be taken. This is purely a readability/maintainability nit.

Proof by walkthrough:

  1. Caller leaves MLA_PREFILL_BACKEND unset → line 214: :- fires → MLA_PREFILL_BACKEND=ROCM_AITER_FA.
  2. Caller sets MLA_PREFILL_BACKEND="" → line 214: :- fires (colon form applies to empty too) → MLA_PREFILL_BACKEND=ROCM_AITER_FA.
  3. Caller sets MLA_PREFILL_BACKEND=FLASH_ATTN → line 214: :- does not fire → MLA_PREFILL_BACKEND=FLASH_ATTN.
  4. In all three cases, line 216's [ -n "$MLA_PREFILL_BACKEND" ] evaluates to true, so MLA_PREFILL_ARGS is always built with the --attention-config flag — the else-path (empty array) is unreachable in every case.

Suggested fix: Drop the if/fi and build MLA_PREFILL_ARGS unconditionally, e.g.:

MLA_PREFILL_BACKEND="${MLA_PREFILL_BACKEND:-ROCM_AITER_FA}"
MLA_PREFILL_ARGS=(
    --attention-config
    "{\"mla_prefill_backend\":\"$MLA_PREFILL_BACKEND\"}"
)

This matches the pattern already used for COMPILATION_CONFIG_ARGS and SPEC_ARGS earlier in the same file, both of which are built unconditionally without a reachable empty-array path.


# ---- HIP graph ------------------------------------------------------------
MAX_NUM_SEQS=20
MAX_CUDAGRAPH_CAPTURE_SIZE=60
Expand Down Expand Up @@ -202,6 +251,7 @@ VLLM_CMD=(
--max-model-len 1048576
--enable-prefix-caching
--kv-cache-dtype "fp8"
"${MLA_PREFILL_ARGS[@]}"
"${COMPILATION_CONFIG_ARGS[@]}"
"${SPEC_ARGS[@]}"
"${OFFLOAD_ARGS[@]}"
Expand Down
4 changes: 2 additions & 2 deletions configs/amd-master.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ dsr1-fp8-mi355x-sglang-disagg-mtp:
- "DECODE_MTP_SIZE=2"

kimik3-fp4-mi355x-vllm-agentic-mtp:
image: vllm/vllm-openai-rocm:nightly-cb8104839c141609d99f1254459ef3a4f1bd4263
image: vllm/vllm-openai-rocm:nightly-3ee2df30337a301164c46ae444b76ee67e71c106
model: moonshotai/Kimi-K3
model-prefix: kimik3
runner: cluster:mi355x-amds
Expand All @@ -648,7 +648,7 @@ kimik3-fp4-mi355x-vllm-agentic-mtp:
agentic-coding:
- dram-utilization: 0.50
search-space:
- { tp: 8, kv-offloading: none, conc-list: [1, 4, 8] , spec-decoding: mtp}
# - { tp: 8, kv-offloading: none, conc-list: [1, 4, 8] , spec-decoding: mtp}
- { tp: 8, ep: 1, kv-offloading: dram, kv-offload-backend: { name: vllm-simple }, conc-list: [10], spec-decoding: mtp }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 AGENTS.md:21 requires a perf-changelog.yaml entry for every change that can affect benchmark performance or any recipe addition/modification, but this PR is missing one despite bumping the kimik3-fp4-mi355x-vllm-agentic-mtp image, disabling the tp:8/conc-list [1,4,8] search-space arm in configs/amd-master.yaml, and flipping the default MLA_PREFILL_BACKEND from FLASH_ATTN to ROCM_AITER_FA in kimik3_fp4_mi355x_mtp.sh. Please append an entry documenting these changes and the measured throughput deltas (+4.4%/+20.1% prefill, 5.52x DSpark) before merging.

Extended reasoning...

AGENTS.md:21 states a non-negotiable invariant: "Every change that can affect benchmark performance and every recipe addition or modification requires a new perf-changelog.yaml entry. The file is append-only and byte-sensitive. Preserve all existing bytes and separator whitespace, and append only at the tail." This is an explicit repository-mandated check, not a stylistic suggestion, and it applies squarely here.

This PR makes several performance-affecting modifications to the kimik3-fp4-mi355x-vllm-agentic-mtp recipe: it bumps the pinned image from nightly-cb8104839c141609d99f1254459ef3a4f1bd4263 to nightly-3ee2df30337a301164c46ae444b76ee67e71c106 in configs/amd-master.yaml, comments out the tp:8/kv-offloading:none/conc-list [1,4,8] search-space arm (removing it from the sweep entirely), and in kimik3_fp4_mi355x_mtp.sh flips the default MLA_PREFILL_BACKEND from FLASH_ATTN to ROCM_AITER_FA plus wires in two new patch scripts (apply_aiter_pybind11_fix.sh and apply_triton_mla_cudagraph_fix.sh) that the PR itself claims produce measured throughput deltas of +4.4%/+20.1% on prefill and a 5.52x speedup for DSpark spec-decode. Each of these is independently sufficient to trigger the AGENTS.md rule — the image bump and search-space edit are recipe modifications to configs/amd-master.yaml, and the backend flip plus patch scripts directly change benchmark performance/behavior.

Despite this, perf-changelog.yaml is not in the PRs changed-files list at all — only apply_aiter_pybind11_fix.sh, apply_triton_mla_cudagraph_fix.sh, kimik3_fp4_mi355x_mtp.sh, and configs/amd-master.yaml were touched. I confirmed the file exists at the repo root (368KB, append-only) and its existing entries follow a config-keys / description / pr-link format per PR (see the tail entries for PRs #2550, #2554, #2562, #2570) — none reference this PR or the kimik3-fp4-mi355x-vllm-agentic-mtp recipe.

Nothing in the existing code prevents this omission — there is no CI check enforced here that fails a PR for a missing changelog entry visible in this diff, so the requirement relies entirely on author/reviewer discipline per AGENTS.md. Concretely, a reviewer or downstream consumer relying on perf-changelog.yaml as the source of truth for why a recipes performance profile changed (e.g. someone investigating a throughput regression/improvement report for kimik3-fp4-mi355x-vllm-agentic-mtp after this merges) would find no record explaining the image bump, the removed search-space arm, or the backend default flip and its claimed gains.

Step-by-step proof:

  1. Search perf-changelog.yaml for any config-keys entry containing kimik3-fp4-mi355x-vllm-agentic-mtp — none exists in the current file (confirmed via the tail of the file, and the PR does not add one since the file is absent from the diff).
  2. Diff configs/amd-master.yaml: the kimik3-fp4-mi355x-vllm-agentic-mtp image tag changes and the tp:8, conc-list:[1,4,8] line is commented out — both are recipe modifications per AGENTS.md:21.
  3. Diff kimik3_fp4_mi355x_mtp.sh: MLA_PREFILL_BACKEND="${MLA_PREFILL_BACKEND:-ROCM_AITER_FA}" replaces the prior FLASH_ATTN default, and the PR description quantifies this as a measurable performance change.
  4. Per AGENTS.md:21, each of steps 2–3 alone "requires a new perf-changelog.yaml entry" — the PR should append one covering the image bump, the removed search-space arm, and the backend default change with a pointer to this PR, before merge.

Fix: append a new entry at the tail of perf-changelog.yaml (preserving all existing bytes/whitespace per the byte-sensitive requirement) with config-keys: [kimik3-fp4-mi355x-vllm-agentic-mtp], a description summarizing the AITER pybind11 fix, the TritonMLA cudagraph fix, the MLA_PREFILL_BACKEND default flip, the removed search-space arm, and the measured throughput deltas, plus a pr-link to this PR.


dsr1-fp4-mi355x-sglang-disagg:
Expand Down