minimax_music3: performance pack — native rope/SwiGLU lowering + opt-in CFG reuse, chunk hop, batched ensemble takes, q4_k depth - #321
Conversation
|
@iamwavecut Thanks for the PR. One issue I recently found is that some optimizations were rejected by me because, on my setup, they only showed noise-level performance changes, while on different hardware the gains could be significant. So I may miss many useful optimizations. RTX 5090:
I’m not a CI expert, so I’m not sure whether the new cuBLASLt dependency could break Docker images or prebuilts. I need a bit more time to investigate. |
|
Also I think the changes to external/ggml/src/ggml-cuda/mmq.cuh was merged already. |
…-cache eviction on release, pipeline buffer reuse
…priority CUDA stream
…s probe (MM3_DC_VERIFY)
…iew-aliasing corruption) + b1 determinism diagnostics (MM3_DC_B1_*), MMQ fixup-buffer zeroing
…U, overlap auto-off on long requests, delta-cache interval=2 default
…; K=1 byte-equivalence force probe; per-stage AR timings
…e philox top-k sampler (MM3_DEPTH_GPU_SAMPLE) and full GPU frame with device residual-ids and hidden accumulation (MM3_DEPTH_GPU_FRAME); exports the ggml CUDA backend stream
…nd: -24% depth, ~-6% wall; q8_0 stays available)
…ix at batch 2, batched decode KV export/replication, shared flow seed under the lock
… seams audible; kept for hybrid experiments)
…th consistently rederived crops/carry; defaults hop=150 + delta-cache interval=3 (flow -40%, 60s solo 74.1s, K=6 ensemble 46.9s/song)
flow_uncond_interval back to 1 (exact reference trajectory), flow_chunk_hop_frames back to the model config (100), depth decoder back to q8_0. Out of the box this branch changes only the flow lowering (native NEOX rope + fused swapped SwiGLU; spectrally equivalent and faster, MM3_LEGACY_ROPE/MM3_LEGACY_GLU restore the previous path) — everything else is opt-in via request/session options.
f54a96e to
e458211
Compare
|
Fair points. Dropped the cuBLASLt commit entirely — it never beat MMQ in my runs either, not worth a new dependency — and rebased on main, so the mmq.cuh hunk is gone too (you already merged it). 12 commits now. On the 2–4%: your run only exercises the default-on part. The bigger wins are the opt-in knobs (flow_uncond_interval, flow_chunk_hop_frames, ensemble_takes), and they're largest on bandwidth-bound cards like A40/3090 — a 5090 hides most of that. |
|
@iamwavecut Thanks for the update! The opt-in options help a lot. I just picked two that don't require new GGUFs. Songs are valid based on my ears.
Please address these issues:
|
…riority to the backend instance, document the new options - Remove the MM3_DC_* determinism probes, the carry-free flow probe, and the K=1 ensemble force switch; the supported env surface is now MM3_LEGACY_ROPE, MM3_LEGACY_GLU, MM3_DEPTH_GPU_SAMPLE, MM3_DEPTH_GPU_FRAME. - Replace the process-wide GGML_CUDA_STREAM_PRIORITY env with a per-backend ggml_backend_cuda_set_stream_priority() (resolved through the backend proc address table like the other CUDA hooks), so a stream created by another context can no longer inherit the overlap priority. - Document the opt-in performance options, the q4_k depth decoder GGUF, and the supported environment variables in docs/community_models/minimax_music3.md.
|
Done, all three: 1. Debug paths — stripped entirely (the MM3_DC_* probes, the carry-free flow probe, the K=1 ensemble force). Net −220 lines. Supported env vars are now exactly the four you listed: 2. Stream priority — the 3. Docs — Smoke-tested on the official GGUF pack: default, interval+hop, ensemble, overlap, legacy env, q4_k depth — all pass. |
|
@iamwavecut Merged. Thanks! 🎉 |
What
A performance pack for MiniMax Music 3 (improving the existing family per CONTRIBUTING, building on #241/#243/#271 by @JoeMattie). 13 focused commits; out of the box only the flow lowering changes — everything else is opt-in and the defaults reproduce the current upstream trajectory.
Default-on (changes flow internals, spectrally equivalent):
ggml_rope_extNEOX lowering instead of the slice/concat rope chains, both flow batches. Also works around a gallocr view-aliasing hazard we bisected: a freshly allocated batch-1 flow graph corrupts its first ~4 invocations, bitwise-reproducibly (batch 2 is saved by an explicitggml_repeat). Repro/diagnostics ship asMM3_DC_B1_*envs;MM3_LEGACY_ROPE=1restores the old lowering.ggml_swiglu_swappedfor the flow FFN (our layout is[states|gate]— plainggml_swiglusilences the wrong half, mel 25 dB off; the swapped variant is exact).MM3_LEGACY_GLU=1restores.Opt-in (upstream defaults preserved):
flow_uncond_interval=N— reuse the CFG guidance delta between steps. N=2: flow −25-30%, mel-L1 ~0.3 dB vs exact; N=1 (default) = exact trajectory.flow_chunk_hop_frames— the stock chunking (200-frame chunks, hop 100) denoises every second twice. hop=150: flow −35%; crops and the carry window are rederived consistently (hop=100 reproduces the stock geometry byte-for-byte).ensemble_takes=K(1..16) — decode K takes of one prompt in a single batched AR pass. The LM+depth stages are weight-bandwidth-bound, so K takes cost far less than K runs; flow/vocoder run per take, outputs land astake_NNvia--out-dir. Adds an additiveexport_batched_decode_state()to the Qwen decode runtime (no behavior change for existing callers).ensemble_prefix_frames=N— intro-lock: the first N frames decode once as a shared master trajectory, then takes fork (take_01 continues the master exactly). "One intro, K continuations."q4_k(upstream file): −24% depth-stage time, panel-clean; option only, default staysq8_0.Numbers (fresh run on a clean A40 SECURE pod, driver 580.159.04, this branch, CUDA)
60 s track, 30 flow steps, one seed, single run each (fresh clone of this branch, canonical build script):
flow_uncond_interval=2flow_chunk_hop_frames=150ensemble_takes=6, combo options20 s sanity pair: native lowering 33.9 s vs
MM3_LEGACY_ROPE/GLU36.2 s (−6% from the lowering itself).From the longer campaign behind this: the ensemble K-curve on a 60 s track runs 89.3/72.4/67.2/64.4/63.7 s per AR pass for K=1/3/6/10/16 (LM+depth are weight-bandwidth-bound, so extra takes are nearly free until flow dominates). Every recipe step was gated on a spectral panel (chroma/harmonicity/dynamics/onsets staying in the reference band) plus human listening.
Build / run
Baseline run (upstream defaults, only the flow lowering differs):
Full opt-in recipe (what
combo60in the table runs):Ensemble: add
--request-option ensemble_takes=6 --out-dir out/(takes land astake_NN.wav).Validation
minimax_music3_graph_release_policy_test,minimax_music3_lm_head_test,minimax_music3_pipeline_buffers_test: pass.Spectrograms from the fresh run (branch
evidence/mm3-perf-20260827holds these + the raw table):defaults (95.9 s) vs full opt-in recipe (68.3 s), same seed:
legacy lowering vs native lowering (20 s, same seed — diverged takes, same character):
Known limitations
MM3_LEGACY_ROPE/GLUkeep the exact old path if you need it.ensemble_takespeak VRAM grows ~0.7 GB per take at 60 s (K=6 ≈ 12.4 GB total on A40).