MiniMax-M3.1 on AMD Instinct GPUs: Day-0 support and optimization

Oct 22, 2026

TL;DR

  • MiniMax-M3.1, MiniMax’s natively multimodal MoE model for coding and agent workloads (1M-token context, NVFP4 experts, a DSpark speculative-decoding draft), serves on AMD Instinct™ MI350 GPUs with both vLLM and ATOM on day 0.
  • An MXFP4 checkpoint produced with AMD Quark, and an equivalent load-time conversion of the NVFP4 checkpoint, run the routed experts on AITER’s MXFP4 fused-MoE kernels; accuracy on both matches within the evaluation error on GSM8K, AIME and MMMU-Pro.
  • vLLM: mono decode, one fused kernel launch per MoE layer for the whole decode step, cuts the per-token decode latency 3.2x at one request, 2.1x at four and 1.5x at sixteen compared with the same server with mono decode off, and gives 2.2-2.4x the interactivity on real coding-agent traces at 1-8 concurrent users.
  • vLLM: DSpark speculative decoding composes with mono decode and adds about a third more interactivity at 1-4 users and 13% at 8; on its own it is the fallback where mono decode cannot run.
  • ATOM: per-channel FP8 attention and a fused shared expert are applied at start-up, and the DSpark draft pass is CUDA-graph captured, accepting about half of its 7 drafts on real text.
  • Serving commands for both engines and both checkpoints, for latency-bound (few users) and throughput-bound (many users) deployments, and for agentic workloads, are given in each engine’s section.

Introduction

We are excited to announce Day-0 support for MiniMax-M3.1 on AMD Instinct™ MI350 Series GPUs across the AMD inference software stack: the ROCm™ build of vLLM and ATOM, the AMD inference engine, both running on ROCm with AITER kernels, with an MXFP4 checkpoint produced by AMD Quark. MiniMax-M3.1 is MiniMax’s latest natively multimodal Mixture-of-Experts model for coding and agent workloads, with a 1M-token context, built-in reasoning with selectable effort, native tool calling and a DSpark speculative-decoding draft.

This post covers what that enablement involved and what we optimized afterwards: how the checkpoint’s NVFP4 experts map onto the MI350 GPUs native MXFP4 and MXFP8 datapaths, the fused “mono decode” kernels and DSpark speculative decoding on vLLM, per-channel FP8 attention, a fused shared expert and CUDA-graph-captured DSpark on ATOM, the accuracy of each configuration, and serving recipes for both engines and both checkpoints.

MiniMax-M3.1 at a glance

MiniMax-M3.1 is the successor of MiniMax-M3: a vision-language Mixture-of-Experts model with a 1M-token context, built-in reasoning with selectable effort, and native tool calling. For inference, four properties matter:

  • Sparse attention on every layer. A lightweight indexer scores 128-token KV blocks and attention runs over the top-k blocks only, so decode attention cost does not grow with context.
  • MoE with a shared expert. 128 routed experts with 4 active per token, plus a shared expert every token passes through, from layer 3 onward; the first three layers are dense.
  • Mixed-precision checkpoint. The routed experts are quantization-aware trained NVFP4; attention projections, the indexer, the dense layers and the shared expert are MXFP8; routers and the LM head are high precision.
  • Speculative decoding by DSpark. A separate 5-layer draft reads the target’s residual stream and proposes up to 7 tokens per step.

Enabling the MXFP4 chckpoint with the AMD Quark

AMD Quark provides broad quantization support across dense and MoE models, text, and multimodal architectures, and deployment formats including MXFP4, INT4, FP8, and others. We used Quark to enable the MXFP4 checkpoint for MiniMax-M3.1.

Starting from the baseline NVFP4 checkpoint, Quark selectively re-quantizes the MoE routed expert layers in the main model to MXFP4, while keeping the remaining layers in their original precision. Quark’s file-to-file workflow processes the model checkpoint shard by shard, enabling scalable conversion from the pre-quantized NVFP4 checkpoint to MXFP4 without loading the full model into memory. Quark’s MXFP4 rounding method further helps minimize quantization error, enabling high-fidelity conversion to the lower-precision format.

Quark also supports flexible mixed-precision configurations, creating room for further performance optimization as new kernels and inference capabilities become available on AMD GPUs.

Day 0 support for AMD Instinct GPUs

MiniMax-M3.1 is supported on AMD Instinct MI350 Series GPUs in both inference engines from day 0: vLLM and ATOM. Both run the routed experts on AITER’s MXFP4 fused MoE with fp8 KV and index caches, AITER’s INT4 quick-reduce for the all-reduces, and tensor parallelism over 4 GPUs per model replica, so two replicas fit on an 8-GPU node. vLLM serves both checkpoints below (the MiniMax-M3.1-Flash release with its experts converted at load, and the Quark MXFP4 export); ATOM serves the Quark MXFP4 export. Where the two engines differ is in how they treat the MXFP8 attention linears and the shared expert at start-up, described in each engine’s section.

Supported checkpoints:

Checkpoint

Routed experts

Everything else

MiniMax-M3.1-Flash (the release, NVFP4 experts)

NVFP4 in the file, converted to OCP MXFP4 at load (--quantization-config.moe mxfp4)

MXFP8, served as-is

MiniMax-M3.1-Flash-Quark-MXFP4 (AMD export)

OCP MXFP4 in the file

MXFP8, served as-is

Both checkpoints carry the DSpark draft in their dspark/ subdirectory, which the speculative config below points at. The serving stack below accepts either checkpoint: the Quark MXFP4 export as-is, or the original NVFP4 checkpoint with the same NVFP4-to-MXFP4 conversion of the routed experts applied at load time.

Serving with vLLM

What we Optimized

The decode path. A decode step on the day-0 path was dominated by kernel-launch overhead rather than arithmetic: about 1,200 small kernels per step. Before fusing anything, each per-layer module was moved to the fastest available kernel: fp8 KV and index caches, AITER’s sparse paged attention with the shuffled KV layout, the fused QK-norm/RoPE kernel, a stacked router GEMM, and the AITER MXFP4 fused MoE with the shared expert optionally folded into the expert table. Each of these is accuracy-neutral.

Mono decode: one kernel launch per layer. The decode step then went from about 1,200 launches to one per MoE layer. Each sparse MoE layer runs as a single FlyDSL kernel that fuses the QKV projection, QK normalization and RoPE, the KV and index-cache insert, the indexer scoring and top-k block selection, the sparse attention itself, the output projection, the tensor-parallel all-reduces (done in-kernel over peer memory), the RMSNorm and router, and the MXFP4 MoE with the shared expert. The kernels are adapted from ROCm ATOM’s MiniMax-M3 mono decode; the vLLM host side dispatches a step to them whenever it is a pure decode of at most 16 tokens under a full-decode CUDA graph, and leaves everything else (prefill, wider steps) on the standard path. Throughout this post “mono decode off” means that standard path: the same server and kernels with the per-layer modules run one after another instead of as the fused kernel. Inside the kernels the attention projections run in per-channel fp8 (re-quantized once at startup from the checkpoint’s MXFP8); the shared expert runs in MXFP8. Every accuracy number below for a mono configuration was measured with this in effect.

Speculative decoding with DSpark. The shipped DSpark draft runs on ROCm with its attention on the Triton backend. The draft commits about 3 tokens per step at K=3 on real text (two accepted draft tokens plus the target’s own) and about 4.5 at its full 7-token block. It composes with mono decode: the verify step’s K+1 rows per request go through the mono kernels as long as the total stays within the 16-row step, which covers up to 4 concurrent requests at K=3.

Agentic serving configuration. Agent workloads (long shared prefixes, multi-turn tool calls, 100k+ token contexts) use the same engine with a GPU-resident prefix cache, large prefill chunks, admission at twice the expected concurrency, a dense CUDA-graph capture list, AITER unified attention, INT4 quick-reduce for the all-reduces, streaming every 20 tokens and the reasoning parser on; this matches the InferenceX AgentX server configuration.

Additional enablement and tuning. Load-time re-quantization through vLLM’s standard online-quantization option; tuned MXFP8 tiles for the small-batch dense and shared-expert GEMMs; tuned AITER fused-MoE rows for the Quark export’s expert shape; the vision encoder on AITER flash attention with data-parallel encoding; AITER’s INT4 quick-reduce for the decode-sized all-reduces. Native NVFP4 support (serving the NVFP4 experts and an NVFP4 KV cache without conversion) was added last and is available as an option; the recipes here use the MXFP4 expert path, which is the tuned one. The same vLLM build also serves MiniMax-M3.1 on AMD Instinct MI300 Series (gfx942) GPUs on the standard path; mono decode and the native MXFP8 GEMMs are MI350 Series (gfx950) features.

Performance, mono decode on vs off (same GPUs, same checkpoint, same server settings)

Decode latency and throughput on random prompts (8k-in / 1k-out unless noted):

 

1 request

4 requests

16 requests

32-128 requests

per-token decode latency (1k-in / 64-out), mono on vs off

3.2x lower

2.1x lower

1.5x lower

equal

output throughput, mono on vs off

+178%

+82%

+31%

equal (within noise)

Figure 1
Figure 1: Decode-latency speed-up of mono decode over the same server with mono decode off, as the ratio of median time per output token. Rows are input tokens / output tokens at C concurrent requests, random prompts of exact length. The gain is largest at one request and shrinks as the step fills toward the 16-token limit.

Above 16 decode tokens per step the mono kernels do not apply and the dispatcher leaves the step on the original path, so the two converge at high concurrency. With mono decode off, folding the shared expert into the expert table is worth +19% at 32 and +15% at 64 concurrent requests; INT4 quick-reduce adds +12% at 32 and +19% at 64 on that path and cuts time to first token by 10-29% on every path.

On the InferenceX agentic-coding traces (real coding-agent sessions with 100k+ token contexts, one hour per point), interactivity (tokens per second per user) and throughput per GPU, relative to mono decode off at the same number of agents:

Concurrent agents

Mono decode

Mono decode + DSpark K=3

DSpark K=7 without mono (fallback)

1-4

2.4x interactivity, +40-75% throughput per GPU

a further +30-33% interactivity (K=3) on top of mono, +18-32% throughput per GPU

+90% interactivity, +38% throughput per GPU at 4

8

2.2x interactivity, +44% throughput per GPU

a further +13% interactivity (K=2) on top of mono, +11% throughput per GPU

+85% interactivity, +51% throughput per GPU

16

1.9x interactivity, +44% throughput per GPU

no gain (K=2 is 9% below mono alone)

+70% interactivity, +50% throughput per GPU

32

interactivity at parity (every step exceeds the 16-row limit), +14% throughput per GPU

not applicable

not viable (eager steps)

DSpark at K=7 without mono reaches 80-90% of mono’s interactivity at 8-16 agents at equal throughput, so it is the recipe for deployments that cannot run the mono kernels rather than a step up from them. The Quark MXFP4 export measures the same curve as the converted NVFP4 checkpoint at every point.

How to run

The commands below run inside the ROCm vLLM container on an MI350 Series node, 4 GPUs per replica. The upstream vLLM recipe for MiniMax-M3.1 on the AMD Instinct GPUs is at vLLM recipes: MiniMax-M3.1 on AMD; the container that ships the MiniMax-M3.1 work is vllm/vllm-openai:minimax-m31-flash.

		docker pull vllm/vllm-openai-rocm:minimax-m31-flash
docker run -it --device /dev/dri --device /dev/kfd \
  --network host --ipc host --group-add video \
  --cap-add=SYS_PTRACE --security-opt seccomp=unconfined \
  --shm-size=64G -v /models:/models \
  vllm/vllm-openai-rocm:minimax-m31-flash
	

Recipe 1: release checkpoint, few concurrent users – mono decode + DSpark. Up to 4 concurrent requests. Remove --language-model-only and add --mm-encoder-tp-mode data --mm-encoder-attn-backend ROCM_AITER_FA --mm-processor-cache-type shm  for image and video inputs.

		VLLM_ROCM_USE_AITER=1 VLLM_ROCM_SHUFFLE_KV_CACHE_LAYOUT=1 VLLM_ROCM_MINIMAX_M3_MONO=1 \
VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4 VLLM_ROCM_QUICK_REDUCE_CAST_BF16_TO_FP16=0 VLLM_ROCM_QUICK_REDUCE_QUANTIZATION_MIN_SIZE_KB=256 \
vllm serve /models/MiniMax-M3.1-Flash \
  --served-model-name minimax-m3.1 --tokenizer-mode hf --load-format safetensors --generation-config vllm \
  --language-model-only --dtype bfloat16 \
  --tensor-parallel-size 4 --distributed-executor-backend mp \
  --moe-backend aiter --quantization-config.moe mxfp4 \
  --attention-backend TRITON_ATTN --block-size 128 \
  --kv-cache-dtype fp8 --attention_config.indexer_kv_dtype fp8 \
  --max-model-len 131072 --max-num-seqs 4 --max-num-batched-tokens 16384 --gpu-memory-utilization 0.85 \
  --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' --enable-chunked-prefill --no-enable-prefix-caching \
  --disable-hybrid-kv-cache-manager \
  --speculative-config '{"method":"dspark","model":"/models/MiniMax-M3.1-Flash/dspark","num_speculative_tokens":3,"attention_backend":"TRITON_ATTN"}' \
  --reasoning-parser minimax_m3 --tool-call-parser minimax_m3 --enable-auto-tool-choice \
  --default-chat-template-kwargs '{"thinking_mode":"enabled"}'
	

Recipe 2: Quark MXFP4 checkpoint. Identical except for the checkpoint path, no --quantization-config, and the optional tuned fused-MoE rows for this checkpoint’s expert shape (they ship in the image; neutral when mono decode serves the decode steps):

		VLLM_ROCM_USE_AITER=1 VLLM_ROCM_SHUFFLE_KV_CACHE_LAYOUT=1 VLLM_ROCM_MINIMAX_M3_MONO=1 \
VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4 VLLM_ROCM_QUICK_REDUCE_CAST_BF16_TO_FP16=0 VLLM_ROCM_QUICK_REDUCE_QUANTIZATION_MIN_SIZE_KB=256 \
vllm serve /models/MiniMax-M3.1-Flash-Quark-MXFP4 \
  --served-model-name minimax-m3.1 --tokenizer-mode hf --load-format safetensors --generation-config vllm \
  --language-model-only --dtype bfloat16 \
  --tensor-parallel-size 4 --distributed-executor-backend mp \
  --moe-backend aiter \
  --attention-backend TRITON_ATTN --block-size 128 \
  --kv-cache-dtype fp8 --attention_config.indexer_kv_dtype fp8 \
  --max-model-len 131072 --max-num-seqs 4 --max-num-batched-tokens 16384 --gpu-memory-utilization 0.85 \
  --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' --enable-chunked-prefill --no-enable-prefix-caching \
  --disable-hybrid-kv-cache-manager \
  --speculative-config '{"method":"dspark","model":"/models/MiniMax-M3.1-Flash-Quark-MXFP4/dspark","num_speculative_tokens":3,"attention_backend":"TRITON_ATTN"}' \
  --reasoning-parser minimax_m3 --tool-call-parser minimax_m3 --enable-auto-tool-choice \
  --default-chat-template-kwargs '{"thinking_mode":"enabled"}'
	

More concurrent users. Up to 16: drop the --speculative-config and --disable-hybrid-kv-cache-manager lines and set --max-num-seqs 16; mono decode serves every step and steps wider than 16 tokens fall back automatically. Above 16: set VLLM_ROCM_MINIMAX_M3_MONO=0, --max-num-seqs 128, --gpu-memory-utilization 0.90, and fold the shared expert into the expert table with VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS=1 and --quantization-config.targets '{"*block_sparse_moe.experts*":"mxfp4","*shared_expert*":"mxfp4"}' in place of --quantization-config.moe mxfp4. Where mono decode cannot run at all (another tensor-parallel size, bf16 caches, piecewise graphs), keep VLLM_ROCM_MINIMAX_M3_MONO=0 and use the speculative config with "num_speculative_tokens":7.

Agentic serving. Agent workloads (long shared prefixes, multi-turn tool calls, 100k+ token contexts) take recipe 1 with the InferenceX AgentX server settings: prefix caching on, 32k prefill chunks, 0.90 of GPU memory, admission at twice the expected number of agents, a dense CUDA-graph capture list, AITER unified attention for the target (the draft stays on TRITON_ATTN), streaming every 20 tokens, and the reasoning parser so tool calls come back structured. This is the configuration behind the agentic ratios above.

		VLLM_ROCM_USE_AITER=1 VLLM_ROCM_SHUFFLE_KV_CACHE_LAYOUT=1 VLLM_ROCM_MINIMAX_M3_MONO=1 \
VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4 VLLM_ROCM_QUICK_REDUCE_CAST_BF16_TO_FP16=0 VLLM_ROCM_QUICK_REDUCE_QUANTIZATION_MIN_SIZE_KB=256 \
vllm serve /models/MiniMax-M3.1-Flash \
  --served-model-name minimax-m3.1 --tokenizer-mode hf --load-format safetensors --generation-config vllm \
  --language-model-only --dtype bfloat16 --trust-remote-code \
  --tensor-parallel-size 4 --distributed-executor-backend mp \
  --moe-backend aiter --quantization-config.moe mxfp4 \
  --attention-backend ROCM_AITER_UNIFIED_ATTN --block-size 128 \
  --kv-cache-dtype fp8 --attention_config.indexer_kv_dtype fp8 \
  --max-model-len 1048576 --max-num-seqs 8 --max-num-batched-tokens 32768 --gpu-memory-utilization 0.90 \
  --enable-chunked-prefill --enable-prefix-caching \
  --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY","cudagraph_capture_sizes":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,24,26,28,30,32,34,36,48,64,72,80,88,96,104,112,120,128]}' \
  --disable-hybrid-kv-cache-manager \
  --speculative-config '{"method":"dspark","model":"/models/MiniMax-M3.1-Flash/dspark","num_speculative_tokens":3,"attention_backend":"TRITON_ATTN"}' \
  --reasoning-parser minimax_m3 --tool-call-parser minimax_m3 --enable-auto-tool-choice \
  --default-chat-template-kwargs '{"thinking_mode":"enabled"}' --stream-interval 20
	

--max-num-seqs is twice the number of agents you expect (8 for four). At eight agents, At eight agents keep the draft with "num_speculative_tokens":2 and --max-num-seqs 16; above that, remove the --speculative-config and --disable-hybrid-kv-cache-manager lines and raise --max-num-seqs to twice the agent count; above 16 agents switch to the high-concurrency settings above. The Quark export takes the same command with its path and no --quantization-config.

1M context. --max-model-len 1048576 --max-num-seqs 8 on any of the above; the fp8 KV pool holds the full context, and a needle ladder at 32k / 128k / 512k / 1M retrieves 12/12 with and without mono decode.

Serving with ATOM

ATOM serves both checkpoints, with text and image inputs. On the Quark MXFP4 export the routed experts stay in MXFP4; on the release checkpoint ATOM converts the NVFP4 routed experts to OCP MXFP4 at load. Every other linear is MXFP8 in the file. ATOM parses Quark’s per-block [1, 32] layout as MXFP8 (one scale per 32 values), so these linears load in their native group-32 form. Either checkpoint with the DSpark draft peaks at under a quarter of each GPU’s memory.

What we optimized

PTPC FP8 attention. At start-up ATOM can dequantize each MXFP8 attention and dense-MLP linear and re-quantize it to FP8 with one scale per output channel, with activations scaled per token at run time (--online_quant_config with ptpc_fp8): 126 linears per rank, done in 1-3 seconds; the MoE is excluded and keeps its stored formats. This is the same recipe ATOM uses for MiniMax-M3, and the same precision the vLLM mono kernels use for the attention projections.

A fused shared expert. ATOM’s fastest MoE path treats the shared expert as a 129th expert that every token selects, so each MoE layer runs one 129-expert / top-5 fused kernel for which AITER ships tuned configurations. The shared expert is MXFP8 next to MXFP4 routed experts, so with ATOM_FUSE_MXFP8_SHARED_INTO_MXFP4=1 ATOM stages the shared expert’s MXFP8 tensors while loading, dequantizes them to BF16 and re-quantizes them to MXFP4 into the fused slot, then frees the staging buffer. Without the switch the shared expert runs as its own MXFP8 MLP next to a 128-expert / top-4 MoE. The switch is off by default; both recipes below turn it on, but it takes effect only on the Quark MXFP4 export: on the release checkpoint the shared expert stays a separate MXFP8 MLP.

DSpark speculative decoding with a CUDA-graph-captured draft pass. The DSpark draft is a parallel block drafter: one pass of its 5-layer backbone drafts 7 tokens, a low-rank Markov head samples them left to right, and the target verifies the block in one forward pass. ATOM taps the five target layers the draft reads through forward hooks, keeps the draft’s KV cache in a sibling pool that shares the target’s 128-token pages, runs the block’s non-causal attention as length-1 paged-decode rows over [context | block], and builds the rows’ page tables outside the graph in pre-allocated buffers, so the whole draft pass has fixed shapes and is captured for every batch size up to --max-num-seqs. On GSM8K the draft accepts about 54% of its 7 drafts on either checkpoint, 4.7-4.8 tokens per target forward.

ATOM’s fused MiniMax-M3 mono decode kernels are not used for M3.1 yet: they assume dense attention in the first three layers, and DSpark reads the target layers through forward hooks. Bringing them to M3.1 is the first item in “What’s next”.

How to run

Launch the container (replace the tag with the release that ships the MiniMax-M3.1 changes):

		docker pull rocm/atom-dev:minimax-m31-flash
docker run -it --device /dev/dri --device /dev/kfd \
  --network host --ipc host --group-add video \
  --cap-add=SYS_PTRACE --security-opt seccomp=unconfined \
  --shm-size=16G --ulimit memlock=-1 --ulimit stack=67108864 \
  -v /models:/models \
  rocm/atom-dev:minimax-m31-flash
	

Either checkpoint from the checkpoint table in the vLLM “How to run” works with the commands below; both carry the DSpark draft in dspark/. As in the vLLM recipes, thinking is on by default (--default-chat-template-kwargs). Every command carries its environment inline; the appendix lists what each variable does.

Recipe 1: release checkpoint – PTPC FP8 attention, fused shared expert and DSpark. Up to 128 concurrent requests. The online-quantization config converts the routed experts to MXFP4 and re-quantizes the attention and dense-MLP linears to PTPC FP8; the router gate and the shared expert are left out.

		MODEL=/models/MiniMax-M3.1-Flash
AITER_LOG_LEVEL=WARNING ATOM_FORCE_ATTN_TRITON=1 AITER_QUICK_REDUCE_QUANTIZATION=INT4 \
ATOM_FUSE_MXFP8_SHARED_INTO_MXFP4=1 HIP_VISIBLE_DEVICES=0,1,2,3 \
python -m atom.entrypoints.openai_server \
  --model $MODEL --served-model-name minimax-m3.1 --trust-remote-code \
  --default-chat-template-kwargs '{"thinking_mode":"enabled"}' \
  --tensor-parallel-size 4 --server-port 8000 \
  --kv_cache_dtype fp8 --index-cache-dtype fp8 --block-size 128 \
  --max-model-len 131072 --max-num-seqs 128 --max-num-batched-tokens 32768 --gpu-memory-utilization 0.9 \
  --online_quant_config '{"global_quant_config": "ptpc_fp8", "layer_quant_config": {"*.experts": "mxfp4"}, "exclude_layer": ["lm_head", "model.embed_tokens", "vision_tower", "multi_modal_projector", "patch_merge_mlp", "*block_sparse_moe.gate", "*shared_experts*"]}' \
  --no-enable_prefix_caching \
  --method dspark --draft-model $MODEL/dspark --num-speculative-tokens 7
	

Recipe 2: Quark MXFP4 checkpoint. Identical except for the checkpoint path and the online-quantization config: the experts are already MXFP4, so the whole MoE block is left out and only the attention and dense-MLP linears are re-quantized:

		MODEL=/models/MiniMax-M3.1-Flash-Quark-MXFP4
AITER_LOG_LEVEL=WARNING ATOM_FORCE_ATTN_TRITON=1 AITER_QUICK_REDUCE_QUANTIZATION=INT4 \
ATOM_FUSE_MXFP8_SHARED_INTO_MXFP4=1 HIP_VISIBLE_DEVICES=0,1,2,3 \
python -m atom.entrypoints.openai_server \
  --model $MODEL --served-model-name minimax-m3.1 --trust-remote-code \
  --default-chat-template-kwargs '{"thinking_mode":"enabled"}' \
  --tensor-parallel-size 4 --server-port 8000 \
  --kv_cache_dtype fp8 --index-cache-dtype fp8 --block-size 128 \
  --max-model-len 131072 --max-num-seqs 128 --max-num-batched-tokens 32768 --gpu-memory-utilization 0.9 \
  --online_quant_config '{"global_quant_config": "ptpc_fp8", "exclude_layer": ["lm_head", "model.embed_tokens", "vision_tower", "multi_modal_projector", "patch_merge_mlp", "*block_sparse_moe"]}' \
  --no-enable_prefix_caching \
  --method dspark --draft-model $MODEL/dspark --num-speculative-tokens 7
	

Notes:

  • --block-size 128 is required, because the draft pool shares the target’s pages.
  • Set --max-model-len explicitly; the model’s default is 1M tokens.
  • Without speculative decoding, drop the last three flags.
  • When running two instances on one node, give the second HIP_VISIBLE_DEVICES=4,5,6,7, a different --server-port and engine --port (default 8006).

Quick check:

		curl http://localhost:8000/v1/chat/completions -H "Content-Type: application/json" -d '{
  "model": "'"$MODEL"'",
  "messages": [{"role": "user", "content": "What is 17*23? Answer briefly."}],
  "max_tokens": 2000, "temperature": 0}'
	

The reasoning is returned in reasoning_content, and the answer 391 in content.

Accuracy

Evaluated with lm-eval against the running server, per engine and checkpoint. GSM8K on the full 1,319-question test set (5-shot chat with the few-shot turns as prior chat turns, flexible / strict match); AIME 2025 and AIME 2026 as mean@16 (16 seeded passes, temperature 1.0, top_p 0.95); MMMU-Pro standard and vision splits (vision tower on). The vLLM rows were served with recipe 1 and recipe 2 above (mono decode + DSpark draft, maximum reasoning effort); the ATOM rows with the ATOM commands above (the accuracy-first row is PTPC attention with the shared expert kept as a separate MXFP8 MLP, with DSpark).

Engine

Checkpoint

GSM8K flexible / strict

AIME 2026 mean@16

AIME 2025 mean@16

MMMU-Pro standard / vision

vLLM

release (converted experts)

0.960 / 0.904

0.948

0.900-0.929 (two seed sets)

0.806 / 0.699

vLLM

Quark MXFP4

0.952 / 0.887

0.933

0.917

0.805 / 0.698

ATOM

release (converted experts)

0.958 / 0.917

0.927

0.906

0.802 / 0.690

ATOM

Quark MXFP4

0.955 / 0.914

0.919

0.915

0.791 / 0.682

What’s next

  • Wider mono steps. The 16-token step limit is why mono + DSpark stops at 4 concurrent requests and mono alone converges with mono-off at 32; wider steps are the next kernel item and the unlock for speculative decoding at 8-16 users.
  • ATOM: mono decode for M3.1. Bring ATOM’s fused per-layer decode kernels, which serve MiniMax-M3’s small decode steps, to M3.1, including its DSpark verify steps; vLLM and SGLang with the ATOM plugin.

Acknowledgements

We thank the MiniMax model team, Inferact, and the AMD vLLM, ATOM, ROCm, AITER and Quark contributors for the model, serving integration, kernel and quantization work that underpins this enablement effort.

Footnotes

Test configuration and disclaimer

vLLM results were measured on 4 GPUs of an 8x AMD Instinct MI350X node with ROCm 7.2, PyTorch 2.13, Triton 3.8, AITER 0.1.25 and FlyDSL 0.3.4, running a ROCm vLLM build with the MiniMax-M3.1 work described here, in October 2026. ATOM results were measured on 4 GPUs of an 8x AMD Instinct MI355X node in a ROCm ATOM development container with the MiniMax-M3.1 changes, in October 2026. Checkpoints: the MiniMax-M3.1 release and AMD’s Quark MXFP4 export of it. Serving-mode ratios come from vLLM’s serving benchmark with random prompts; agentic ratios from the InferenceX agentic-coding harness (AIPerf replay of recorded coding-agent traces) with one hour per point; accuracy from lm-eval. Results on other hardware, software versions, settings or workloads will differ; these figures are for illustration and are not a performance guarantee.

Footnotes

Appendix: environment variables

Variable

Set to

Description

VLLM_ROCM_USE_AITER

1

AITER kernels for MoE, attention, indexer and all-reduce

VLLM_ROCM_SHUFFLE_KV_CACHE_LAYOUT

1

AITER shuffled KV layout for the sparse paged attention; required by mono decode

VLLM_ROCM_MINIMAX_M3_MONO

1 / 0

mono decode on; 0 for the high-concurrency and no-mono recipes. Steps the kernels cannot serve fall back and log the reason

VLLM_ROCM_QUICK_REDUCE_QUANTIZATION, ..._CAST_BF16_TO_FP16, ..._QUANTIZATION_MIN_SIZE_KB

INT4, 0, 256

AITER INT4 quick-reduce for the decode-sized all-reduces

VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS

1 (high-concurrency recipe only)

fold the shared expert into the expert table; needs the shared expert in --quantization-config.targets

AITER_CONFIG_FMOE

path (recipe 2, optional)

tuned AITER fused-MoE rows for the Quark export’s expert shape

ATOM:

Variable

Set to

Description

ATOM_FORCE_ATTN_TRITON

1

Triton attention kernels for the target

AITER_QUICK_REDUCE_QUANTIZATION

INT4

AITER INT4 quick-reduce for the all-reduces

ATOM_FUSE_MXFP8_SHARED_INTO_MXFP4

1 (speed-first) / unset (accuracy-first)

re-quantize the MXFP8 shared expert to MXFP4 and fold it into the fused 129-expert MoE

AITER_LOG_LEVEL

WARNING

quieter AITER start-up log

HIP_VISIBLE_DEVICES

e.g. 0,1,2,3

the four GPUs of a TP4 instance

Related Blogs