File size: 6,123 Bytes
07cb9b1
 
 
 
6d82264
07cb9b1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6d82264
07cb9b1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6d82264
07cb9b1
078b54a
07cb9b1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# MiniMax-M2.7-MXFP416 vLLM Deployment Guide (RDNA 4 / RX 9700)

## Hardware Requirements

- **GPU:** 8× AMD RX 9700 (RDNA 4 / gfx12xx)
- **Memory:** 128GB+ system RAM for 8-GPU setup
- **OS:** Linux with ROCm 6.x
- **Docker:** RDNA4-compatible vLLM image

## Docker Image

The only validated runtime for this model is [`tcclaviger/vllm22:latest`](https://hub.docker.com/r/tcclaviger/vllm22):

```bash
docker pull tcclaviger/vllm22:latest
```

This image includes:
- Custom Triton attention kernels tuned for RDNA4 (significantly faster than ROCm attention at long context)
- Fixed FP8 KV-cache quantization path (~2× throughput improvement)
- Pre-tuned GEMM configs for RX 9700
- MXFP4-16 kernels compiled for gfx12xx

## System Setup

### GPU Devices

Make sure all GPUs are visible:

```bash
rocm-smi --showid
# Should show: 0, 1, 2, 3, 4, 5, 6, 7
```

### Power Limit (Recommended)

RDNA4 performs best with tuned power limits. Default is ~300W but 210W provides better sustained throughput on multi-GPU setups:

```bash
# Set per-GPU power limit
for i in 0 1 2 3 4 5 6 7; do
    rocm-smi --setpowerlimit $i 210
done
```

> **Note:** At full power (300W) sustained speeds are lower due to thermal throttling. At 210W, sustained generation throughput is consistently higher under multi-user workloads.

## Launching the Server

### Single Container (8 GPUs)

```bash
docker run --name minimax-mxfp416 \
  --rm --tty --ipc=host --shm-size=128g \
  --device /dev/kfd:/dev/kfd \
  --device /dev/dri/renderD128:/dev/dri/renderD128 \
  --device /dev/dri/renderD129:/dev/dri/renderD129 \
  --device /dev/dri/renderD130:/dev/dri/renderD130 \
  --device /dev/dri/renderD132:/dev/dri/renderD132 \
  --device /dev/dri/renderD137:/dev/dri/renderD137 \
  --device /dev/dri/renderD138:/dev/dri/renderD138 \
  --device /dev/dri/renderD139:/dev/dri/renderD139 \
  --device /dev/dri/renderD140:/dev/dri/renderD140 \
  -e HIP_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
  -e ROCR_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
  -e TRUST_REMOTE_CODE=1 \
  -e PYTORCH_TUNABLEOP_ENABLED=1 \
  -e PYTORCH_TUNABLEOP_TUNING=0 \
  -e PYTORCH_TUNABLEOP_RECORD_UNTUNED=0 \
  -e PYTORCH_ALLOC_CONF=expandable_segments:True \
  -e PYTORCH_HIP_ALLOC_CONF=expandable_segments:True \
  -e GPU_MAX_HW_QUEUES=1 \
  -v /path/to/models:/app/models:ro \
  -p 8000:8000 \
  tcclaviger/vllm22:latest \
  bash -c "cp /app/models/vllm22_minimax_m2.py /app/vllm/vllm/model_executor/models/minimax_m2.py && \
    pip install -q sentencepiece && \
    exec vllm serve \
      /app/models/MiniMax-M2.7-MXFP416 \
      --served-model-name minimax-m2.7-mxfp416 \
      --host 0.0.0.0 --port 8000 \
      --trust-remote-code \
      --tensor-parallel-size 8 \
      --enable-expert-parallel \
      --disable-cascade-attn \
      --reasoning-parser minimax_m2 \
      --enable-auto-tool-choice \
      --tool-call-parser minimax_m2 \
      --enable-prefix-caching \
      --gpu-memory-utilization 0.93 \
      --max-model-len 180000 \
      --max-num-seqs 48 \
      --max-num-batched-tokens 2048 \
      --kv-cache-dtype fp8_e4m3 \
      --attention-backend TRITON_ATTN \
      --override-generation-config '{\"max_tokens\": 16384}'"
```

### Key vLLM Flags Explained

| Flag | Value | Purpose |
|------|-------|---------|
| `--tensor-parallel-size` | 8 | Split model across 8 GPUs |
| `--enable-expert-parallel` | | Enable expert-parallel distribution |
| `--disable-cascade-attn` | | Disable cascade attention for MoE layers |
| `--attention-backend` | TRITON_ATTN | Use Triton kernels (10× faster than ROCm on RDNA4) |
| `--kv-cache-dtype` | fp8_e4m3 | FP8 KV cache (~50% memory savings) |
| `--enable-prefix-caching` | | Cache common prefixes (93%+ hit rate observed) |
| `--max-model-len` | 180000 | 180k context |
| `--max-num-seqs` | 48 | Max concurrent sequences |
| `--max-num-batched-tokens` | 2048 | Max tokens per batch |
| `--gpu-memory-utilization` | 0.93 | Use 93% of GPU memory |

> **Important:** The `--disable-cascade-attn` flag is required for MoE models. Without it, the model will produce incorrect outputs.

### Running with Patches

If you have custom model patches:

```bash
-v /path/to/patches:/patches:ro \
```

The Docker entry point copies `vllm22_minimax_m2.py` to the vLLM model directory before launching. This adds MXFP4-16 support for MiniMax-M2.7.

## Performance Notes

### Observed Performance (8× RX 9700, 210W power limit)

- **Generation throughput:** 30–35 tokens/s
- **Prefill throughput:** 2000+ tokens/s (with prefix caching)
- **Prefix cache hit rate:** ~93%
- **KV cache usage:** 25–33% typical at 180k context
- **Max concurrent users:** 4–5 at full 180k context

### KV Cache Capacity

With 8× RX 9700 and FP8 KV cache:
- **KV cache memory:** 11.35 GiB
- **KV cache tokens:** ~768K tokens
- **Max context per request:** 180,000 tokens
- **Max concurrent at 180k:** ~4 requests

### Model Loading

- **Weight loading time:** ~42 seconds
- **Memory per GPU (TP8):** ~17.5 GiB
- **Torch compile warmup:** ~37 seconds

## Testing the Deployment

```python
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="EMPTY",
)

completion = client.chat.completions.create(
    model="minimax-m2.7-mxfp416",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Explain what MXFP4 quantization is in one sentence."}
    ],
    temperature=1.0,
    max_tokens=256,
)

print(completion.choices[0].message.content)
```

## Troubleshooting

### "expandable_segments not supported"

This warning is benign on ROCm. The model runs correctly despite the warning.

### Low throughput at long context

Ensure `TRITON_ATTN` backend is active. Default ROCm attention is 10× slower on RDNA4 at long context.

### Thermal throttling

If sustained throughput degrades over time, reduce power limit to 210W per GPU:
```bash
rocm-smi --setpowerlimit 0 210
```

### Model fails to load

Ensure `--trust-remote-code` is set and the model path is correct. The custom model file (`vllm22_minimax_m2.py`) must be copied before vLLM loads the model.