Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
123 changes: 123 additions & 0 deletions benchmarks/single_node/fixed_seq_len/dsv4_fp8_mi300x.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/usr/bin/env bash
set -eo pipefail

# DeepSeek-V4-Pro FP8 single-node on MI300X (gfx942) via vLLM.
#
# EXTRAPOLATED bring-up recipe. The sglang path was abandoned: on gfx942
# (no native FP4) the dsv4 sglang backend's nvfp4 MoE / TileLang-MLA kernels
# have no gfx942 equivalents (they exist only for gfx950/MI355X). vLLM instead
# runs the checkpoint in FP8 via --quantization deepseek_v4_fp8, which
# dequantizes the FP4 MoE experts to FP8 — the same path the H200 dsv4 vLLM
# recipe uses (H200 is also a no-FP4 SKU). Derived from:
# * same model + framework + AMD family: dsv4_fp4_mi355x_vllm.sh (ROCm vLLM
# dsv4 structure: AITER MoE, deepseek_v4 tokenizer/parser, mp executor,
# FULL_AND_PIECEWISE compile)
# * same model, FP8 path: dsv4_fp8_h200.sh (--quantization deepseek_v4_fp8)
# * same SKU, different model: minimaxm3_fp8_mi300x.sh (gfx942 vLLM/AITER)
#
# The FP4->FP8 dequant roughly doubles the MoE footprint (~1.05 TB total),
# which fits 8x192 GB only at TP8, so the sweep is TP8-only.
#
# MoE backend is left at auto (NOT --moe-backend aiter). --quantization
# deepseek_v4_fp8 only handles the dense/attention weights; the MoE experts
# stay mxfp4 and go through vLLM's mxfp4 MoE selector. On gfx942, forcing
# aiter selects AITER_MXFP4_MXFP4 (W4A4, native mxfp4) which the gfx942 kernel
# rejects ("Mxfp4 MoE backend 'AITER_MXFP4_MXFP4' does not support ... QuantKey
# (u8 ... col=32)"). With auto, vLLM's select_deepseek_v4_mxfp4_moe_backend
# takes its ROCm+DeepseekV4 branch and prefers AITER_MXFP4_BF16 (W4A16 CK,
# dequantizes weights — no native FP4), falling back to TRITON_UNFUSED. MI355X
# keeps --moe-backend aiter because gfx950 supports the W4A4 kernel.

source "$(dirname "$0")/../../benchmark_lib.sh"

check_env_vars \
MODEL \
TP \
DP_ATTENTION \
CONC \
ISL \
OSL \
MAX_MODEL_LEN \
RANDOM_RANGE_RATIO \
RESULT_FILENAME

if [[ -n "$SLURM_JOB_ID" ]]; then
echo "JOB $SLURM_JOB_ID running on $SLURMD_NODENAME"
fi

if [[ "$MODEL" != /* ]]; then hf download "$MODEL"; fi

if [ -n "$ROCR_VISIBLE_DEVICES" ]; then
export HIP_VISIBLE_DEVICES="$ROCR_VISIBLE_DEVICES"
fi

export VLLM_ROCM_USE_AITER=1
export VLLM_ROCM_USE_AITER_MOE=1

# Cap eval concurrency for gfx942's tight KV. FP8 weights (~131GB/GPU) leave
# only ~71k tokens of KV on the 192GB MI300X ("Maximum concurrency ... 7.52x"
# for a 9472-token request). The eval defaults to CONC (128) concurrent
# requests, which OOM-kills the server mid-gsm8k. Cap to the KV budget; this
# only affects run_eval (throughput jobs use CONC directly). MI325X (256GB)
# has the headroom and keeps the default.
export EVAL_CONCURRENT_REQUESTS=8

SERVER_LOG=/workspace/server.log

if [ "${EVAL_ONLY}" = "true" ]; then
setup_eval_context
MAX_MODEL_LEN="$EVAL_MAX_MODEL_LEN"
fi

start_gpu_monitor

PARALLEL_ARGS=(--tensor-parallel-size "$TP" --data-parallel-size 1)
if [ "${DP_ATTENTION}" = "true" ]; then
PARALLEL_ARGS=(--tensor-parallel-size 1 --data-parallel-size "$TP")
fi

EP_ARGS=()
if [ "${EP_SIZE:-1}" -gt 1 ]; then
EP_ARGS=(--enable-expert-parallel)
fi

set -x
vllm serve $MODEL --port $PORT \
"${PARALLEL_ARGS[@]}" \
"${EP_ARGS[@]}" \
--quantization deepseek_v4_fp8 \
--async-scheduling \
--no-enable-prefix-caching \
--distributed-executor-backend mp \
--gpu-memory-utilization 0.9 \
--max-model-len "$MAX_MODEL_LEN" \
--kv-cache-dtype fp8 \
--trust-remote-code \
--tokenizer-mode deepseek_v4 \
--reasoning-parser deepseek_v4 \
--compilation-config '{"mode":3,"cudagraph_mode":"FULL_AND_PIECEWISE"}' > $SERVER_LOG 2>&1 &

SERVER_PID=$!

wait_for_server_ready --port "$PORT" --server-log "$SERVER_LOG" --server-pid "$SERVER_PID"

run_benchmark_serving \
--model "$MODEL" \
--port "$PORT" \
--backend vllm \
--input-len "$ISL" \
--output-len "$OSL" \
--random-range-ratio "$RANDOM_RANGE_RATIO" \
--num-prompts "$((CONC * 10))" \
--max-concurrency "$CONC" \
--result-filename "$RESULT_FILENAME" \
--result-dir /workspace/ \
--trust-remote-code

if [ "${RUN_EVAL}" = "true" ]; then
run_eval --framework lm-eval --port "$PORT"
append_lm_eval_summary
fi

stop_gpu_monitor
set +x
133 changes: 133 additions & 0 deletions benchmarks/single_node/fixed_seq_len/dsv4_fp8_mi300x_mtp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/usr/bin/env bash
set -eo pipefail

# DeepSeek-V4-Pro FP8 single-node on MI300X (gfx942) via vLLM, MTP variant.
#
# MTP sibling of dsv4_fp8_mi300x.sh: adds --speculative-config
# '{"method":"mtp","num_speculative_tokens":2}' (DeepSeek-V4 built-in MTP)
# and --dsv4 chat-template encoding for run_benchmark_serving (EAGLE/MTP is
# trained on chat-formatted inputs).
#
# EXTRAPOLATED bring-up recipe. The sglang path was abandoned: on gfx942
# (no native FP4) the dsv4 sglang backend's nvfp4 MoE / TileLang-MLA kernels
# have no gfx942 equivalents (they exist only for gfx950/MI355X). vLLM instead
# runs the checkpoint in FP8 via --quantization deepseek_v4_fp8, which
# dequantizes the FP4 MoE experts to FP8 — the same path the H200 dsv4 vLLM
# recipe uses (H200 is also a no-FP4 SKU). Derived from:
# * same model + framework + AMD family: dsv4_fp4_mi355x_vllm.sh (ROCm vLLM
# dsv4 structure: AITER MoE, deepseek_v4 tokenizer/parser, mp executor,
# FULL_AND_PIECEWISE compile)
# * same model, FP8 path: dsv4_fp8_h200.sh (--quantization deepseek_v4_fp8)
# * same SKU, different model: minimaxm3_fp8_mi300x.sh (gfx942 vLLM/AITER)
#
# The FP4->FP8 dequant roughly doubles the MoE footprint (~1.05 TB total),
# which fits 8x192 GB only at TP8, so the sweep is TP8-only.
#
# MoE backend is left at auto (NOT --moe-backend aiter). --quantization
# deepseek_v4_fp8 only handles the dense/attention weights; the MoE experts
# stay mxfp4 and go through vLLM's mxfp4 MoE selector. On gfx942, forcing
# aiter selects AITER_MXFP4_MXFP4 (W4A4, native mxfp4) which the gfx942 kernel
# rejects ("Mxfp4 MoE backend 'AITER_MXFP4_MXFP4' does not support ... QuantKey
# (u8 ... col=32)"). With auto, vLLM's select_deepseek_v4_mxfp4_moe_backend
# takes its ROCm+DeepseekV4 branch and prefers AITER_MXFP4_BF16 (W4A16 CK,
# dequantizes weights — no native FP4), falling back to TRITON_UNFUSED. MI355X
# keeps --moe-backend aiter because gfx950 supports the W4A4 kernel.

source "$(dirname "$0")/../../benchmark_lib.sh"

check_env_vars \
MODEL \
TP \
DP_ATTENTION \
CONC \
ISL \
OSL \
MAX_MODEL_LEN \
RANDOM_RANGE_RATIO \
RESULT_FILENAME

if [[ -n "$SLURM_JOB_ID" ]]; then
echo "JOB $SLURM_JOB_ID running on $SLURMD_NODENAME"
fi

if [[ "$MODEL" != /* ]]; then hf download "$MODEL"; fi

if [ -n "$ROCR_VISIBLE_DEVICES" ]; then
export HIP_VISIBLE_DEVICES="$ROCR_VISIBLE_DEVICES"
fi

export VLLM_ROCM_USE_AITER=1
export VLLM_ROCM_USE_AITER_MOE=1

# Cap eval concurrency for gfx942's tight KV. FP8 weights (~131GB/GPU) leave
# only ~71k tokens of KV on the 192GB MI300X ("Maximum concurrency ... 7.52x"
# for a 9472-token request). The eval defaults to CONC (128) concurrent
# requests, which OOM-kills the server mid-gsm8k. Cap to the KV budget; this
# only affects run_eval (throughput jobs use CONC directly). MI325X (256GB)
# has the headroom and keeps the default.
export EVAL_CONCURRENT_REQUESTS=8

SERVER_LOG=/workspace/server.log

if [ "${EVAL_ONLY}" = "true" ]; then
setup_eval_context
MAX_MODEL_LEN="$EVAL_MAX_MODEL_LEN"
fi

start_gpu_monitor

PARALLEL_ARGS=(--tensor-parallel-size "$TP" --data-parallel-size 1)
if [ "${DP_ATTENTION}" = "true" ]; then
PARALLEL_ARGS=(--tensor-parallel-size 1 --data-parallel-size "$TP")
fi

EP_ARGS=()
if [ "${EP_SIZE:-1}" -gt 1 ]; then
EP_ARGS=(--enable-expert-parallel)
fi

# Use 2 speculative tokens (matches dsv4_fp4_mi355x_vllm_mtp.sh).
NUM_SPEC_TOKENS=2

set -x
vllm serve $MODEL --port $PORT \
"${PARALLEL_ARGS[@]}" \
"${EP_ARGS[@]}" \
--quantization deepseek_v4_fp8 \
--async-scheduling \
--no-enable-prefix-caching \
--distributed-executor-backend mp \
--gpu-memory-utilization 0.9 \
--max-model-len "$MAX_MODEL_LEN" \
--kv-cache-dtype fp8 \
--trust-remote-code \
--tokenizer-mode deepseek_v4 \
--reasoning-parser deepseek_v4 \
--speculative-config "{\"method\": \"mtp\", \"num_speculative_tokens\": $NUM_SPEC_TOKENS}" \
--compilation-config '{"mode":3,"cudagraph_mode":"FULL_AND_PIECEWISE"}' > $SERVER_LOG 2>&1 &

SERVER_PID=$!

wait_for_server_ready --port "$PORT" --server-log "$SERVER_LOG" --server-pid "$SERVER_PID"

run_benchmark_serving \
--model "$MODEL" \
--port "$PORT" \
--backend vllm \
--input-len "$ISL" \
--output-len "$OSL" \
--random-range-ratio "$RANDOM_RANGE_RATIO" \
--num-prompts "$((CONC * 10))" \
--max-concurrency "$CONC" \
--result-filename "$RESULT_FILENAME" \
--result-dir /workspace/ \
--trust-remote-code \
--dsv4

if [ "${RUN_EVAL}" = "true" ]; then
run_eval --framework lm-eval --port "$PORT"
append_lm_eval_summary
fi

stop_gpu_monitor
set +x
55 changes: 55 additions & 0 deletions configs/amd-master.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,61 @@ dsr1-fp8-mi325x-sglang:
search-space:
- { tp: 8, conc-start: 4, conc-end: 64 }

# DeepSeek-V4-Pro FP8 single-node on MI300X (gfx942) via vLLM.
# EXTRAPOLATED bring-up. sglang was abandoned: on gfx942 (no native FP4) the
# dsv4 sglang backend's nvfp4 MoE / TileLang-MLA kernels have no gfx942 build
# (gfx950/MI355X only). vLLM runs the checkpoint in FP8 via --quantization
# deepseek_v4_fp8 (dequant FP4 MoE -> FP8), the same path the H200 dsv4 vLLM
# recipe uses. Config mirrors the same-model dsv4-fp4-mi355x-vllm (TP8, conc
# 4-512); the FP4->FP8 dequant (~1.05TB) fits 8x192GB only at TP8. Launch
# script dsv4_fp8_mi300x.sh carries the deepseek_v4 + gfx942 AITER flags.
dsv4-fp8-mi300x-vllm:
image: vllm/vllm-openai-rocm:nightly-09663abde0f50944a8d5ea30120666024b503faa
model: deepseek-ai/DeepSeek-V4-Pro
model-prefix: dsv4
runner: mi300x
precision: fp8
framework: vllm
multinode: false
scenarios:
fixed-seq-len:
- isl: 1024
osl: 1024
search-space:
- { tp: 8, conc-start: 4, conc-end: 512 }
- isl: 8192
osl: 1024
search-space:
# 8k1k KV fits only ~20x concurrency (9472-token requests), so conc512 is
# ~25x oversubscribed -> request timeouts. conc256 is proven green; cap here.
- { tp: 8, conc-start: 4, conc-end: 256 }

# MTP variant of dsv4-fp8-mi300x-vllm. Mirrors the base recipe and adds
# DeepSeek-V4 built-in MTP via --speculative-config (num_speculative_tokens=2),
# routing to dsv4_fp8_mi300x_mtp.sh; benchmark uses --dsv4 chat-template
# encoding (required for meaningful MTP acceptance).
dsv4-fp8-mi300x-vllm-mtp:
image: vllm/vllm-openai-rocm:nightly-09663abde0f50944a8d5ea30120666024b503faa
model: deepseek-ai/DeepSeek-V4-Pro
model-prefix: dsv4
runner: mi300x
precision: fp8
framework: vllm
multinode: false
scenarios:
fixed-seq-len:
- isl: 1024
osl: 1024
search-space:
- { tp: 8, conc-start: 4, conc-end: 512, spec-decoding: mtp }
- isl: 8192
osl: 1024
search-space:
# 8k1k MTP KV is tighter than normal (draft model): conc256 failed here
# (19.2% req failures) and conc512 was 55.8%; conc128 passed cleanly.
# Cap 8k1k MTP at 128 (normal holds 256, 1k1k holds 512).
- { tp: 8, conc-start: 4, conc-end: 128, spec-decoding: mtp }

dsr1-fp8-mi355x-sglang:
image: lmsysorg/sglang:v0.5.12-rocm700-mi35x
model: deepseek-ai/DeepSeek-R1-0528
Expand Down
35 changes: 35 additions & 0 deletions perf-changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4751,6 +4751,22 @@
- "6 topologies across 1k/1k and 8k/1k: 1P1D TP4 STP + wide-EP (DEP4 prefill / DEP16 decode) from 1P1D up to 8P1D, recipes under benchmarks/multi_node/srt-slurm-recipes/sglang/qwen3.5/gb300-fp8/"
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2137

- config-keys:
- dsv4-fp8-h200-vllm
- dsv4-fp8-h200-vllm-mtp
description:
- "Bump vLLM image from v0.21.0 to v0.25.0 for DeepSeek-V4-Pro FP8 on H200, matching the B200/B300 dsv4 vLLM bump (#2169)"
- "Refresh stale H200 dsv4 submissions (last run 2026-05-21)"
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2191

- config-keys:
- dsv4-fp8-h200-sglang
- dsv4-fp8-h200-sglang-mtp
description:
- "Bump the pinned lmsysorg/sglang:deepseek-v4-hopper digest from the 2026-05-02 push (7f19c6dc) to the current 2026-05-13 push (1bf5d508)"
- "Refresh stale H200 dsv4 SGLang submissions (last run 2026-05-04)"
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2191

- config-keys:
- dsv4-fp4-mi355x-sglang
description:
Expand All @@ -4765,3 +4781,22 @@
- "Bump image to lmsysorg/sglang-rocm:v0.5.14-rocm720-mi35x-20260708"
- "Clean the export envs"
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2198

- config-keys:
- dsv4-fp8-mi300x-vllm
description:
- "Add DeepSeek-V4-Pro FP8 single-node MI300X vLLM benchmark (new SKU, previously no dsv4 data on gfx942)"
- "vLLM, not sglang: on gfx942 (no native FP4) the dsv4 sglang backend's nvfp4 MoE and TileLang-MLA kernels have no gfx942 build (gfx950/MI355X only). vLLM runs the checkpoint in FP8 via --quantization deepseek_v4_fp8 (dequant FP4 MoE -> FP8), the same path the no-FP4 H200 dsv4 vLLM recipe uses"
- "Recipe mirrors the same-model dsv4-fp4-mi355x-vllm (ROCm vLLM dsv4: deepseek_v4 tokenizer/reasoning-parser, mp executor, FULL_AND_PIECEWISE compile) plus gfx942 AITER infra from minimaxm3-fp8-mi300x-vllm; TP8 conc 4-512 (the FP4->FP8 dequant ~1.05TB fits 8x192GB only at TP8)"
- "MoE backend left at auto (unlike MI355X's --moe-backend aiter): deepseek_v4_fp8 only dequantizes dense/attention, the MoE experts stay mxfp4; forcing aiter on gfx942 selects AITER_MXFP4_MXFP4 (W4A4 native-mxfp4) which the gfx942 kernel rejects, while auto's ROCm+DeepseekV4 path prefers AITER_MXFP4_BF16 (W4A16, dequant) with TRITON_UNFUSED fallback"
- "EVAL_CONCURRENT_REQUESTS=8: FP8 weights (~131GB/GPU) leave only ~71k tokens of KV on 8x192GB (max 7.52x concurrency for a 9472-token request); the eval default of CONC (128) concurrent requests OOM-kills the server mid-gsm8k, so eval concurrency is capped to the KV budget (throughput unaffected; MI325X's 256GB keeps the default)"
- "Image vllm/vllm-openai-rocm:nightly-09663abde0f50944a8d5ea30120666024b503faa (the DSv4-validated ROCm vLLM build)"
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2194

- config-keys:
- dsv4-fp8-mi300x-vllm-mtp
description:
- "Add DeepSeek-V4-Pro FP8 MI300X vLLM MTP (speculative-decoding) variant, mirroring dsv4-fp8-mi300x-vllm plus --speculative-config {\"method\":\"mtp\",\"num_speculative_tokens\":2} (DeepSeek-V4 built-in MTP)"
- "run_benchmark_serving uses --dsv4 chat-template encoding, required for meaningful MTP acceptance rate (EAGLE/MTP is trained on chat-formatted inputs)"
- "Same gfx942 auto-MoE (AITER_MXFP4_BF16) + EVAL_CONCURRENT_REQUESTS=8 KV cap as the base recipe; routes to dsv4_fp8_mi300x_mtp.sh via the launcher's spec-decoding=mtp suffix"
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2194