diff --git a/benchmarks/single_node/fixed_seq_len/dsv4_fp8_mi300x.sh b/benchmarks/single_node/fixed_seq_len/dsv4_fp8_mi300x.sh new file mode 100755 index 000000000..b921b6054 --- /dev/null +++ b/benchmarks/single_node/fixed_seq_len/dsv4_fp8_mi300x.sh @@ -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 diff --git a/benchmarks/single_node/fixed_seq_len/dsv4_fp8_mi300x_mtp.sh b/benchmarks/single_node/fixed_seq_len/dsv4_fp8_mi300x_mtp.sh new file mode 100755 index 000000000..0f71361f6 --- /dev/null +++ b/benchmarks/single_node/fixed_seq_len/dsv4_fp8_mi300x_mtp.sh @@ -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 diff --git a/configs/amd-master.yaml b/configs/amd-master.yaml index 4b1ea4aed..0d6577d59 100644 --- a/configs/amd-master.yaml +++ b/configs/amd-master.yaml @@ -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 diff --git a/perf-changelog.yaml b/perf-changelog.yaml index e05c2ca1c..55228a17c 100644 --- a/perf-changelog.yaml +++ b/perf-changelog.yaml @@ -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: @@ -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