Issues / #3148

#3148 serve: MTP on stage 0 exhausts the first GPU at 768K context (mtp prefill: unspecified launch failure); per-GPU reserve seems ineffective

open · @zhq445078388 · 0 comments · View on GitHub

BenchmarksServer & APIMulti-GPUAMD / HIPModels & quantsWindows

Description

## Summary

On Windows with 2× AMD Radeon AI PRO R9700 and Strata 0.1.45, serving
Qwen3.8-Flash-Next-GSQ with `--max-context 786432` and MTP enabled starts
successfully, but the first chat request fails with:

[strata] the engine reported an error: mtp prefill: unspecified launch failure
[strata] done: 0 tokens in 26 s (0.0 tok/s) (error, cancel=False)

The machine's display goes black at the same time.

The same 786432 context with **MTP disabled** starts and answers normally.
Measurements suggest the engine subtracts the MTP weights from the total expert
cache, but does **not** reserve the MTP prefill scratch / per-GPU headroom on
stage 0. `--vram-reserve-mib` also did not change the expert cache allocation in
this configuration (500 vs 2048 produced identical cache/slots and an unchanged
30.96 GiB on GPU 0).

## Environment

- OS: Windows (AMD gfx1201, WDDM)
- Engine: Strata 0.1.45
- GPU: 2× AMD Radeon AI PRO R9700, 31.86 GiB each
- RAM: 63.4 GiB
- ROCm runtime: `pip-10.0.3686.0-20261018`
- Model: Qwen3.8-Flash-Next-GSQ, IQ3_XXS pack
- Interface: `strata serve`, OpenAI `/v1/chat/completions`
- MTP: `--mtp ...\strata-mtp\rt`, `STRATA_MTP_STAGE0=1`
- Multi-GPU: `--layer-split auto`, `--mmap-experts`, `--expert-cache auto`

## Exact args (serve config)

--pack ...\strata-pack\IQ3_XXS
--native ...\Qwen3.8-Flash-Next-GSQ-RCO-IQ3_XXS-00001-of-00002.gguf
--ple-gguf ...\Qwen3.8-Flash-Next-GSQ-RCO-IQ3_XXS-00002-of-00002.gguf
--expert-profile ...\strata-pack\IQ3_XXS\expert-profile.bin
--expert-cache auto
--prefill auto
--spec 4
--spec-min-p 0.5
--mtp ...\strata-mtp\rt
--max-context 786432
--rope-scaling yarn
--rope-scale 2
--yarn-orig-ctx 262144
--kv int8
--ple-io mmap
--vram-reserve-mib 500
--vram-reserve-later-mib 500
--layer-split auto
--mmap-experts

Environment:

STRATA_MTP_STAGE0=1
STRATA_HIPBLASLT_TUNING=hip\gfx1201-hipblaslt-100500.txt
STRATA_RESIDENT_PIN=0

## Reproduction

1. Start `strata serve` with the args above (`--max-context 786432`, MTP on).
2. Wait for:

[strata] filling the GPU's expert cache (12971 experts, 18.79 GiB of VRAM) ...
ready: http://127.0.0.1:8080/v1 (context 786432 tokens)

3. Send one small request (about 54 prompt tokens), for example:

{
  "model": "qwen3.8-flash-next-gsq",
  "messages": [{"role": "user", "content": "只回复 OK"}],
  "max_tokens": 16,
  "stream": false
}

4. The engine reports `mtp prefill: unspecified launch failure`, returns
   `0 tokens`, and the display goes black.

At the time of the failure:

GPU 0: 30.96 GiB used / 31.86 GiB  (~0.90 GiB free)
GPU 1: 27.72 GiB used / 31.86 GiB  (~4.14 GiB free)

## Same context with MTP disabled

With `--max-context 786432` and **no `--mtp`**, the same request succeeds:

GPU 0: 30.64 GiB / 31.86 GiB
GPU 1: 30.30 GiB / 31.86 GiB
expert_slots = 24576 / 24576
expert_cache = 40924 MiB
vram_free = 1221 MiB

Startup cache differs by about the MTP size:

MTP on,  768K: 12971 experts, 18.79 GiB
MTP off, 768K: 13824 experts, 20.01 GiB

So the MTP **weights** do appear to be subtracted from the total expert cache.
The problem is that the first GPU still ends up with only ~0.9 GiB free, and
`mtp prefill` apparently needs more temporary space than that.

## Evidence that per-GPU reserve is not doing what it says

At 524288 context with MTP on, I compared two runs that differed only in the
first-card reserve:

--vram-reserve-mib 500  --vram-reserve-later-mib 500
--vram-reserve-mib 2048 --vram-reserve-later-mib 500

Both runs produced exactly:

expert_cache          = 38313 MiB
expert_cache_primary  = 16325 MiB
expert_slots          = 23163
GPU 0 usage           = 30.96 GiB
GPU 1 usage           = 27.90 GiB

The first-card reserve change had no effect on the expert cache or GPU 0. This
was with an explicit `--layer-split 22`, so it was not just an auto-split
difference.

I also tried explicit layer splits to move layers away from the MTP stage:

layer-split auto: GPU 0 30.96 / GPU 1 27.72, cache 40735 MiB, slots 24474
layer-split 23:   GPU 0 30.96 / GPU 1 28.80, cache 39228 MiB, slots 23660
layer-split 22:   GPU 0 30.96 / GPU 1 27.90, cache 38313 MiB, slots 23163

GPU 0 stayed at 30.96 GiB in all three cases. `expert-cache auto` seems to
refill the space freed by moving layers with more expert cache, so moving layers
does not create MTP headroom on stage 0.

## Expected

One of:

- `expert-cache auto` should reserve the MTP prefill scratch / temporary buffers
  on stage 0 when `STRATA_MTP_STAGE0=1`.
- `--vram-reserve-mib` should actually reduce GPU 0's cache allocation when it
  is set higher.
- If the requested context cannot fit with MTP, fail at startup with a clear
  message instead of starting, then crashing the GPU on the first `mtp prefill`
  and taking the display down.

## Actual

The service starts successfully and reports ready, then the first request causes
`mtp prefill: unspecified launch failure`; the display goes black.

## Workaround used

- 768K context: disable MTP. This is stable.
- 524288 context: MTP on is stable.
- Do not use 768K + MTP on this machine.

## Question

Is this a known limitation of `STRATA_MTP_STAGE0=1` + `--expert-cache auto`, or
is the first-card reserve supposed to account for MTP prefill buffers as well?
If there is a recommended flag combination for dual-GPU + MTP (for example
`--trim-stage-weights` or a specific `--vram-reserve-later-mib`), I can test it
and report the results.

Thanks.

Related on this site

Quick links to related pages.