perf(moe): pool heterogeneous GGUF cache rows - #199
Draft
pedro-moser wants to merge 4 commits into
Draft
Conversation
Adds the laguna GGUF architecture: hybrid full/SWA attention with per-layer query-head counts, QK RMSNorm, per-layer-type rope (YaRN partial-dim on full layers, plain rope on SWA), a per-head softplus attention output gate, and sigmoid + score-correction-bias MoE routing with one always-on shared expert. Semantics follow llama.cpp src/models/laguna.cpp. Poolside/Unsloth laguna checkpoints quantize per tensor, so this also generalizes the GGUF plumbing: - six more ggml types (Q3_K, Q4_K, Q5_K, IQ1_S, IQ2_S, IQ2_XXS, IQ3_XXS, IQ4_XS) wired into the dequant tables and mmvq/mmq/dequant dispatch - a "gguf" expert-bank format whose per-layer quant types vary: flat padded [E, stride] host banks plus a new expert_stride_bytes argument threaded through the vendored moe_vec launchers (0 = previous dense behaviour) - moe_vec calls chunked to min(65535, 16384) rows: the kernel indexes experts via blockIdx.z (CUDA grid-z cap 65535) and a 16k-token x top-8 prefill chunk also overflowed transient VRAM - q/k/v kept as separate projections (a layer may quantize attn_v differently from attn_q/k -- observed on the XS Q4_K_M build) - deferred GGUF linears materialized from the file's tensor table at conversion time, before the engine collects the state dict Tested on: RTX 5080 (16 GB), 23 GB RAM, NVIDIA 610.62, CUDA 13, wsl2. Checkpoints: unsloth/Laguna-S-2.1-GGUF (Laguna-S-2.1-UD-IQ1_S.gguf, S, metadata/tensor coverage only) and poolside/Laguna-XS-2.1-GGUF (Laguna-XS-2.1-Q4_K_M.gguf) plus a third-party APEX-I-Mini XS build (Q3_K/Q4_K/Q5_K/Q6_K/IQ2_S) run end to end. Validation on Laguna-XS-2.1-APEX-I-Mini.gguf: ft serve --model <model> --kv-cache-dtype fp8_e4m3 --num-tokens 262144 --kv-reserve-tokens 262144 - NIAH 3/3 at 250,054 tokens (needle at 10%/50%/90% depth, exact passcode), ~433 tok/s prefill - decode 157-162 tok/s at 64k ctx, 21-23 tok/s at ~250k ctx (PCIe-bound) Not done: S-model e2e (host lacked RAM for its ~37 GiB expert banks), hybrid/cpu MoE backend for the gguf format, FTW conversion, TP>1. See tasks/laguna-handover.md. Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Important
This is a draft stacked on #102. Until #102 lands, the GitHub diff against
mainincludes its Laguna GGUF commits. The heterogeneous-cache changes to review are the final two commits (2c6591canda9f8824, 15 files). I will rebase ontomainafter #102 merges.Summary
layer_idwhile preserving a full-layer max-stride prefill overlayhybridfor GGUF, whose experts have no CPU executorCloses #194 after #102 lands.
Motivation
Laguna-S Q4_K_M has 47 MoE layers but two very different expert geometries:
#102's safe uniform layout pads every layer to the 18 MiB maximum. On this checkpoint that means:
Compact host rows reduce expert-bank RAM to 85.359375 GiB. Geometry pools spend the same GPU arena bytes on many more Q4_K rows rather than 18 MiB padding.
Design
OffloadMoeCacheremains the single owner and public facade:uint8GGUF rows. Uniform formats retain their existing shape/dtype/contiguity contract.moe_cache_sizedenomination.bank_views(layer_id=...),ensure_experts, and copies through the selected pool.Backend auto-selection also stays on
offloadwhen a saved bandwidth profile recommendshybridfor GGUF. Explicit backend choices are unchanged; this only prevents an automatic post-load failure in a CPU executor that has no GGUF expert implementation.The row-strided CUDA path copies compact registered-host rows directly into padded destinations. A peak-memory regression verifies it does not allocate a CUDA temporary proportional to the payload.
Controlled A/B
Hardware: RTX 5080 16,303 MiB (SM 12.0), driver 610.57.04, CUDA toolkit 13.3, Ryzen 7 9800X3D, 128 GiB RAM. PCIe expert gather measured at 47-48 GB/s.
Checkpoint:
unsloth/Laguna-S-2.1-GGUF, revision750f92f90cf54159c4d7a610cb7b3e74498e75c6, Laguna-S Q4_K_M GGUF (96,031,829,760-byte local file).Both benchmark arms ran on the same #102 + #103 integration branch and differed only in cache layout. #103 supplied Q8_0 KV for the benchmark but is not a code dependency of this PR.
Identical prompt, sampling, one warm request, and 247 completion tokens. The client used the public streaming API and measured decode as
(completion_tokens - 1) / (last_token_time - first_token_time)so the first token is not counted before the timing window:Warm decode improved 23.13% at the same cache-byte budget. The geometry branch also measured 18.686 tok/s on a cold 127-token request.
Tests
On current
mainmerged with #102, without #103:across cache budgeting, Laguna mixed-weight loading, MoE/offload behavior, the strided CUDA kernels, CLI stats, and scheduler reporting.
for isolated Laguna config/module tests.
Additional verified coverage includes:
FREETOKEN_FUSED_COPYenabled and disabledtests/moe/test_prefill_hit_d2d.pyis 4 passed / 1 failed on both this branch and the rebased #102 baseline: the optionalcudaMemcpyBatchAsyncprobe copies wrong bytes on this driver. Geometry mode intentionally does not use that path.Compatibility, limitations, and risks