Skip to content
Merged
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
34 changes: 34 additions & 0 deletions .github/configs/nvidia-master.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11845,6 +11845,40 @@ minimaxm3-fp8-b200-vllm:
- { tp: 4, conc-start: 1, conc-end: 64 }
- { tp: 8, ep: 8, dp-attn: true, conc-start: 128, conc-end: 256 }

# EAGLE3 speculative-decoding (spec-decoding: mtp) variant of
# minimaxm3-fp8-b200-vllm, pairing MiniMaxAI/MiniMax-M3-MXFP8 with the
# Inferact/MiniMax-M3-EAGLE3 draft head (3 speculative tokens, drafter pinned
# to FLASH_ATTN since the head is MHA and FlashInfer needs GQA/MQA at page
# size 128). Search space mirrors the non-MTP entry trimmed at the
# extreme-concurrency end, identical to the minimaxm3-fp8-b300-vllm-mtp
# precedent: spec decode pays off at low/mid concurrency while acceptance
# dilutes in big batches, and the draft weights + draft KV shave headroom.
minimaxm3-fp8-b200-vllm-mtp:
image: vllm/vllm-openai:minimax-m3
model: MiniMaxAI/MiniMax-M3-MXFP8
model-prefix: minimaxm3
runner: b200-dgxc
precision: fp8
framework: vllm
multinode: false
scenarios:
fixed-seq-len:
- isl: 1024
osl: 1024
search-space:
- { tp: 8, conc-start: 1, conc-end: 64, spec-decoding: mtp }
- { tp: 8, ep: 8, conc-start: 1, conc-end: 256, spec-decoding: mtp }
- { tp: 4, conc-start: 1, conc-end: 64, spec-decoding: mtp }
- { tp: 4, ep: 4, conc-start: 64, conc-end: 256, spec-decoding: mtp }
- { tp: 8, ep: 8, dp-attn: true, conc-start: 256, conc-end: 512, spec-decoding: mtp }
- isl: 8192
osl: 1024
search-space:
- { tp: 8, conc-start: 1, conc-end: 64, spec-decoding: mtp }
- { tp: 8, ep: 8, conc-start: 1, conc-end: 256, spec-decoding: mtp }
- { tp: 4, conc-start: 1, conc-end: 64, spec-decoding: mtp }
- { tp: 8, ep: 8, dp-attn: true, conc-start: 128, conc-end: 256, spec-decoding: mtp }

# EAGLE3 speculative-decoding (spec-decoding: mtp) variant of
# minimaxm3-fp8-b300-vllm, pairing MiniMaxAI/MiniMax-M3-MXFP8 with the
# Inferact/MiniMax-M3-EAGLE3 draft head (3 speculative tokens).
Expand Down
135 changes: 135 additions & 0 deletions benchmarks/single_node/fixed_seq_len/minimaxm3_fp8_b200_mtp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/usr/bin/env bash

# MiniMax-M3 MXFP8 B200 single-node vLLM recipe with EAGLE3 speculative
# decoding — the repo's spec-decoding=mtp variant of minimaxm3_fp8_b200.sh
# (https://recipes.vllm.ai/MiniMaxAI/MiniMax-M3). Adds the
# Inferact/MiniMax-M3-EAGLE3 draft head via --speculative-config with 3
# speculative tokens. Everything else keeps the non-MTP serve shape:
# --block-size 128 is mandatory (MSA sparse_block_size is 128; the default 16
# misaligns sparse indexing), and --language-model-only skips the vision
# encoder for the text-only benchmark. dp-attn=true maps to DP×EP (DEP);
# ep>1 maps to TP+EP (TEP).
#
# The drafter is pinned to FLASH_ATTN: the EAGLE3 head is MHA, and FlashInfer
# only supports page size 128 through its trtllm-gen kernel, which requires
# GQA/MQA — engine init dies in FlashInferMetadataBuilder otherwise (the
# failure hit on the B300 MTP canary). The target keeps its default
# (FlashInfer) backend; FLASH_ATTN takes any multiple-of-16 block size, so
# the mandatory 128 is fine for the draft.

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

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

DRAFT_MODEL="Inferact/MiniMax-M3-EAGLE3"

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

nvidia-smi

# launch_b200-dgxc.sh rewrites MODEL to the pre-downloaded
# /lustre/fsw/gharunners/models/MiniMax-M3-MXFP8 path; only download the target
# when handed a bare HF id (b200-cw / b200-nb runners). The EAGLE3 draft is
# never pre-staged, so fetch it either way: next to the target weights when
# MODEL is a local path (the gharunners tree is writable), into the HF cache
# otherwise.
if [[ "$MODEL" != /* ]]; then
hf download "$MODEL"
hf download "$DRAFT_MODEL"
DRAFT_MODEL_PATH="$DRAFT_MODEL"
else
DRAFT_MODEL_PATH="$(dirname "$MODEL")/${DRAFT_MODEL##*/}"
if [[ ! -d "$DRAFT_MODEL_PATH" || -z "$(ls -A "$DRAFT_MODEL_PATH" 2>/dev/null)" ]]; then
hf download "$DRAFT_MODEL" --local-dir "$DRAFT_MODEL_PATH"
fi
fi

SERVER_LOG=/workspace/server.log

# 444 GB of MXFP8 weights off shared FS; engine startup can exceed the
# default 600s readiness window.
export VLLM_ENGINE_READY_TIMEOUT_S=3600

if [ "${DP_ATTENTION}" = "true" ]; then
PARALLEL_ARGS="--tensor-parallel-size=1 --data-parallel-size=$TP --enable-expert-parallel"
elif [ "$EP_SIZE" -gt 1 ]; then
PARALLEL_ARGS="--tensor-parallel-size=$TP --enable-expert-parallel"
else
PARALLEL_ARGS="--tensor-parallel-size=$TP"
fi

# use 3 speculative tokens for all configs for now
NUM_SPEC_TOKENS=3

# Fixed-seq-len runs don't need graphs past the decode step's token count:
# with spec decoding every running request contributes 1 + NUM_SPEC_TOKENS
# tokens per step, so capture up to the next power of two >=
# CONC * (1 + NUM_SPEC_TOKENS), capped at vLLM's 2048 ceiling.
CAPTURE_SIZE=4
while (( CAPTURE_SIZE < CONC * (1 + NUM_SPEC_TOKENS) )); do CAPTURE_SIZE=$((CAPTURE_SIZE * 2)); done
(( CAPTURE_SIZE > 2048 )) && CAPTURE_SIZE=2048

if [ "${EVAL_ONLY}" = "true" ]; then
setup_eval_context
MAX_MODEL_LEN="$EVAL_MAX_MODEL_LEN"
fi
# Start GPU monitoring (power, temperature, clocks every second)
start_gpu_monitor

set -x
vllm serve $MODEL --port $PORT \
$PARALLEL_ARGS \
--gpu-memory-utilization 0.90 \
--max-model-len $MAX_MODEL_LEN \
--block-size 128 \
--language-model-only \
--max-cudagraph-capture-size $CAPTURE_SIZE \
--max-num-batched-tokens "$((ISL * 2 ))" \
--speculative-config "{\"method\": \"eagle3\", \"model\": \"$DRAFT_MODEL_PATH\", \"num_speculative_tokens\": $NUM_SPEC_TOKENS, \"attention_backend\": \"FLASH_ATTN\"}" \
--stream-interval 20 --no-enable-prefix-caching \
--trust-remote-code > $SERVER_LOG 2>&1 &

SERVER_PID=$!

# Wait for server to be ready
wait_for_server_ready --port "$PORT" --server-log "$SERVER_LOG" --server-pid "$SERVER_PID"

pip install -q datasets pandas

# Spec-decode acceptance rate degrades on raw random tokens; route prompts
# through the chat template as the other MTP recipes do.
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 \
--use-chat-template

# After throughput, run evaluation only if RUN_EVAL is true
if [ "${RUN_EVAL}" = "true" ]; then
run_eval --framework lm-eval --port "$PORT"
append_lm_eval_summary
fi

# Stop GPU monitoring
stop_gpu_monitor
set +x
10 changes: 10 additions & 0 deletions perf-changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3696,3 +3696,13 @@
- "H200 layouts: TP4 / TP8 (latency), TP4+EP4 / TP8+EP8 (TEP), TP8+EP8 dp-attn (DEP) across 1k1k and 8k1k — non-MTP search space trimmed at the extreme-concurrency end. H100 is TP8-only (no room below TP8 at ~56 GB weights/GPU); DEP omitted (KV-cache init fails at high conc, draft only tightens it)"
- "Adds SPEC_SUFFIX to the three H100 launchers (cw, cr, dgxc-slurm) so spec-decoding=mtp routes to the _mtp script — they hardcoded _h100.sh and never gained the _mtp routing the H200 launchers have had since #392"
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/1739

- config-keys:
- minimaxm3-fp8-b200-vllm-mtp
description:
- "Initial submission: MiniMax-M3 MXFP8 B200 vLLM benchmark with EAGLE3 speculative decoding (target: MiniMaxAI/MiniMax-M3-MXFP8, draft: Inferact/MiniMax-M3-EAGLE3, 3 speculative tokens) — spec-decoding=mtp variant of the day-zero B200 recipe"
- "Image: vllm/vllm-openai:minimax-m3 (same m3_release-branch build as the non-MTP entry)"
- "Serve shape follows minimaxm3-fp8-b200-vllm (--block-size 128, --language-model-only); cudagraph capture scaled to CONC * (1 + spec tokens); prompts routed through the chat template for realistic acceptance"
- "Drafter pinned to FLASH_ATTN via speculative-config attention_backend: the EAGLE3 head is MHA and FlashInfer only supports the mandatory page size 128 through its GQA-only trtllm-gen kernel"
- "Layouts: TP8 / TP4 (latency), TP8+EP8 / TP4+EP4 (TEP), TP8+EP8 dp-attn (DEP) across 1k1k and 8k1k — non-MTP search space trimmed at the extreme-concurrency end, mirroring the minimaxm3-fp8-b300-vllm-mtp search space"
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/1741
Loading