Qwen3.5 inference for AMD MI50 -- TP, MTP, GGUF
996
GPU inference engine for Qwen3.5 (Dense) hybrid models on AMD Instinct MI50 (gfx906).
Custom HIP kernels, flash attention, P2P tensor parallelism (TP=1..8), MTP speculative decoding. Reads GGUF model files.
# Benchmark
docker run --device=/dev/kfd --device=/dev/dri --group-add video \
--ipc=host -v /path/to/models:/models \
skyne98/tp906-engine tp906-bench -m /models/model.gguf
# Chat
docker run -it --device=/dev/kfd --device=/dev/dri --group-add video \
--ipc=host -v /path/to/models:/models \
skyne98/tp906-engine tp906-chat /models/model.gguf
# OpenAI-compatible server
docker run --device=/dev/kfd --device=/dev/dri --group-add video \
--ipc=host -v /path/to/models:/models -p 8080:8080 \
skyne98/tp906-engine tp906-server /models/model.gguf --host 0.0.0.0
Architecture: Qwen3.5 Dense (and MoE variants).
| Model | TP=1 | TP=2 | TP=4 |
|---|---|---|---|
| Qwen3.5-0.8B | yes | yes | yes |
| Qwen3.5-2B | yes | yes | yes |
| Qwen3.5-4B | yes | yes | yes |
| Qwen3.5-9B | yes | yes | yes |
| Qwen3.5-27B | -- | yes | yes |
TP must evenly divide the model head count (32 for all dense Qwen3.5), so valid values are 1, 2, 4, 8, 16, 32.
| Format | Notes |
|---|---|
| Q8_0 | Native, best quality/speed tradeoff |
| Q4_0 | Converted to Q8_0 in VRAM on load (fast GPU kernel) |
| Q4_1 | Converted to Q8_0 in VRAM on load (fast GPU kernel) |
| Q6_K | Converted to Q8_0 in VRAM on load (fast GPU kernel) |
| Q5_K_M | Converted to Q8_0 in VRAM on load (CPU dequant path) |
| Q4_K_M | Converted to Q8_0 in VRAM on load (CPU dequant path) |
| Q3_K | Converted to Q8_0 in VRAM on load (CPU dequant path) |
| Q2_K | Converted to Q8_0 in VRAM on load (CPU dequant path) |
| F16 | Converted to Q8_0 in VRAM on load |
Note: All quantizations are converted to Q8_0 at load time. Q4_0, Q4_1, and Q6_K use fast GPU requantization kernels; others go through CPU dequant. VRAM usage is always the Q8_0 size regardless of source format.
MTP provides ~10-15% faster decode by speculatively predicting one token ahead.
Pre-extracted weights for all Qwen3.5 sizes: raspbfox/tp906-mtp
# Download for your model size — place next to the GGUF file
cd /path/to/models/
wget https://huggingface.co/raspbfox/tp906-mtp/resolve/main/Qwen3.5-9B/mtp_weights.bin
Available: 0.8B (39 MB) | 2B (116 MB) | 4B (230 MB) | 9B (465 MB) | 27B (811 MB)
Auto-detect: place mtp_weights.bin in the same directory as your GGUF file. tp906 finds it automatically.
Explicit: --mtp /path/to/mtp_weights.bin
Server INI: use the mtp key (see models.ini section below).
# Requires: pip install huggingface_hub numpy
python3 tools/extract_mtp.py --repo Qwen/Qwen3.5-9B -o mtp_weights.bin
Downloads only the needed safetensor shards, extracts the 15 MTP tensors, converts BF16 to F16.
docker run --device=/dev/kfd --device=/dev/dri --group-add video \
--ipc=host -v /path/to/models:/models \
skyne98/tp906-engine tp906-bench -m /models/model.gguf --tp 4
--ipc=host is requiredServe multiple models from one instance. Clients select via the model field in API requests. TP is automatically reconfigured when switching models.
; First entry loads at startup. Comments: ; or #
[Qwen3.5-9B]
path = /models/Qwen3.5-9B-Q8_0.gguf
mtp = /models/Qwen3.5-9B/mtp_weights.bin
tp = 4
max_seq = 32768
[Qwen3.5-4B]
path = /models/Qwen3.5-4B-Q8_0.gguf
tp = 2
[Qwen3.5-0.8B]
path = /models/Qwen3.5-0.8B-Q8_0.gguf
tp = 1
| Key | Required | Description |
|---|---|---|
path | yes | Path to GGUF model file |
mtp | Path to MTP weights (or auto-detect from model dir) | |
tp | Tensor parallelism degree (number of GPUs) | |
max_seq | Maximum sequence length (default: 8192) |
docker run --device=/dev/kfd --device=/dev/dri --group-add video \
--ipc=host -v /path/to/models:/models -p 8080:8080 \
skyne98/tp906-engine tp906-server --models /models/models.ini --host 0.0.0.0
Benchmark tool with llama-bench compatible output format.
| Flag | Default | Description |
|---|---|---|
-m, --model <file> | (required) | GGUF model file |
-p, --n-prompt <n> | 512 | Prompt tokens to benchmark |
-n, --n-gen <n> | 128 | Generation tokens to benchmark |
-d, --n-depth <n> | 0 | KV cache depth before benchmarking |
-r, --repetitions <n> | 5 | Repetitions per test |
--tp <n> | 1 | Tensor parallel across N GPUs |
--max-seq <n> | 131072 | Maximum sequence length |
--mtp <path> | (auto-detect) | MTP weights for speculative decoding |
-o, --output <fmt> | md | Output format: md or csv |
--no-warmup | Skip warmup runs |
Comma-separated values for sweeps: -p 128,256,512 -n 64,128
Interactive chat CLI.
| Flag | Default | Description |
|---|---|---|
<model.gguf> | (required) | GGUF model file (positional) |
--tp <n> | 1 | Tensor parallel across N GPUs |
--max-seq <n> | 8192 | Maximum sequence length |
--max-new-tokens <n> | 32768 | Max tokens to generate per turn |
--system <text> | System prompt | |
--prompt <text> | One-shot prompt (non-interactive mode) | |
--no-thinking | Disable thinking/reasoning blocks | |
--temp <f> | 0.80 | Temperature |
--top-k <n> | 40 | Top-K sampling |
--top-p <f> | 0.95 | Top-P / nucleus sampling |
--min-p <f> | 0.05 | Min-P sampling |
--repeat-penalty <f> | 1.0 | Repetition penalty (1.0 = disabled) |
--seed <n> | (random) | Random seed for reproducibility |
--mtp <path> | (auto-detect) | MTP weights for speculative decoding |
Interactive commands: /help /paste /file <path> /history /reset /quit
OpenAI-compatible HTTP API server.
| Flag | Default | Description |
|---|---|---|
<model.gguf> | GGUF model file (single-model mode) | |
--models <ini> | Model catalog INI file (multi-model mode) | |
--host <addr> | 0.0.0.0 | Bind address |
--port <n> | 8080 | Port |
--tp <n> | 1 | Tensor parallel across N GPUs |
--max-seq <n> | 8192 | Maximum sequence length |
--max-new-tokens <n> | 32768 | Max tokens to generate |
--no-thinking | Disable thinking/reasoning blocks | |
--temp <f> | 0.80 | Default temperature |
--top-k <n> | 40 | Default top-K |
--top-p <f> | 0.95 | Default top-P |
--min-p <f> | 0.05 | Default min-P |
--seed <n> | (random) | Default random seed |
--mtp <path> | (auto-detect) | MTP weights for speculative decoding |
Endpoints:
| Method | Path | Description |
|---|---|---|
| POST | /v1/chat/completions | Chat completion (streaming supported via stream: true) |
| GET | /v1/models | List available models |
| GET | /health | Health check |
--device=/dev/kfd --device=/dev/dri --group-add video--ipc=host for multi-GPU tensor parallelismsudo sysctl -w kernel.numa_balancing=0 # prevent GPU DMA stalls
# Kernel parameter (GRUB): iommu=pt # prevent IOMMU overhead
| Model | Quant | TP | Prefill (pp512) | Decode (tg128) |
|---|---|---|---|---|
| Qwen3.5 0.8B | Q8_0 | 1 | 4,050 t/s | 182 t/s |
| Qwen3.5 4B | Q8_0 | 2 | 1,405 t/s | 89 t/s |
| Qwen3.5 9B | Q8_0 | 4 | 1,223 t/s | 68 t/s |
0.0.1-pre-alpha-1 -- early testing release.
Content type
Image
Digest
sha256:1e85a7d31…
Size
350.2 MB
Last updated
6 months ago
docker pull skyne98/tp906-engine