llama.cpp
MoE Offloading & Memory Optimization
In Mixture of Experts (MoE) models (such as Qwen 3.8 Flash Next, DeepSeek-V2/V3, Mixtral, etc.), expert weights represent the majority of parameters and VRAM. cafe-llama.cpp provides flags to offload MoE weights to pinned host RAM (CUDA_Host) or CPU RAM while keeping attention, KV cache, and routers on the GPU:
| Flag | Long Flag | Description |
|---|---|---|
--pipeline-parallel | --no-pipeline-parallel | Enable the offloading acceleration pipeline, required for -hmoe, -nhmoe, -hmoed. |
-hmoe | --host-moe | Keep all MoE expert weights in pinned host memory (CUDA_Host). Enables zero-copy async DMA over PCIe. |
-nhmoe N | --n-host-moe N | Keep MoE weights of the first N layers in pinned host memory. |
-cmoe | --cpu-moe | Keep all MoE expert weights in CPU system RAM. |
-ncmoe N | --n-cpu-moe N | Keep MoE weights of the first N layers in CPU system RAM. |
-ssd | --ssd-streaming, --no-ssd-streaming | Stream routed expert weights from SSD on-demand via mmap: only the experts a token actually selects page into RAM, the rest stay on disk. |
-nssd N | --ssd-n-streaming N | Stream the MoE experts of the first N layers from SSD (implies --ssd-streaming); analogous to -ncmoe / -nhmoe, but the destination is SSD instead of RAM. |
-hmoed | --host-moe-draft | Keep draft model MoE weights in pinned host memory (for speculative decoding). |
-nhmoed N | --n-host-moe-draft N | Keep draft model MoE weights of the first N layers in pinned host memory (for speculative decoding). |
-cmoed | --cpu-moe-draft | Keep draft model MoE weights in CPU system RAM (for speculative decoding). |
-ncmoed N | --n-cpu-moe-draft N | Keep draft model MoE weights of the first N layers in CPU system RAM (for speculative decoding). |
Turbo KV Cache (low-bit K/V, GPU-only)
Low-bit TurboQuant types for the attention KV cache, selected with -ctk / -ctv (draft: -ctkd / -ctvd). Rows are stored in the rotated (WHT) domain and reconstructed inside the fused flash-attention kernel, so flash-attention (-fa) is required: it is auto-enabled, and loading aborts if flash-attention is explicitly disabled. Turbo KV types are GPU-side only.
| Type | Approx bits/value | Compression vs fp16 | Constraint |
|---|---|---|---|
turbo4 | ~4.1 | ~3.9x | none |
turbo3 | ~3.5 | ~4.6x | head dim (K/V) must be a multiple of 128 |
turbo2 | ~2.5 | ~6.4x | head dim (K/V) must be a multiple of 128 |
Lower-bit K/V lets long-context KV fit in VRAM. Example: -ctk turbo4 -ctv turbo4 -fa on.
Qwen 3.8 Flash Next / Qwen4 Internal N-Gram (PLE) Optimization
Qwen 3.8 Flash Next includes an internal Prompt Lookup Expert (PLE) N-gram hash embedding table (per_layer_token_embd, ~51B parameters). cafe-llama.cpp provides dedicated flags to manage its memory footprint:
| Flag | Long Flag | Description |
|---|---|---|
--ngram-ssd | --offload-ngram-ssd, --no-ngram-ssd | Exclusively offload the internal N-gram embedding table to SSD on-demand via memory mapping (mmap), leaving active model layers in RAM/VRAM. |
--no-ngram | --disable-ngram, --no-load-ngram | Force completely disable the internal N-gram embedding table and PLE layers, skipping all PLE tensors (0 bytes allocated in RAM/VRAM). |
--ngram | --load-ngram | Normal mode: load internal N-gram table and PLE layers into memory (default). |
Qwen 3.8 Flash Next & MTP Speculative Decoding
MTP (Multi-Token Prediction) draft models in GGUF format are available at: 👉 Hugging Face: quimmedes/Qwen3.8-Flash-Next-MTP-GGUF
Available quantizations:
mtp-Qwen3.8-Flash-Next-Q4_K_M.gguf(~2.65 GB) - Recommended for balanced memory and speedmtp-Qwen3.8-Flash-Next-Q6_K.gguf(~3.24 GB)mtp-Qwen3.8-Flash-Next-Q8_0.gguf(~3.94 GB)mtp-Qwen3.8-Flash-Next-BF16.gguf(~7.40 GB) - Full precision
Recommended Server Command for Qwen 3.8 Flash Next:
llama-server -m Qwen3.8-Flash-Next-UD-IQ3_XXS-00001-of-00003.gguf \
-ctk q8_0 -ctv q8_0 -kvu \
-fa on -ngl 99 -nhmoe 36 -c 64000 --pipeline-parallel -np 1 --no-ngram
Disable Ngram if you don't have enough RAM/VRAM
llama-server -m Qwen3.8-Flash-Next-UD-IQ3_XXS-00001-of-00003.gguf \
-ctk q8_0 -ctv q8_0 -kvu \
-fa on -ngl 99 -nhmoe 36 -c 64000 \
--no-ngram --pipeline-parallel -np 1 --no-ngram
MTP with offload
llama-server \
-m Qwen3.8-Flash-Next-UD-IQ3_XXS-00001-of-00003.gguf \
-md mtp.gguf \
--spec-type draft-mtp \
--spec-draft-n-max 2 \
-ngl 99 \
-nhmoe 36 \
-fa on \
-ctk q8_0 -ctv q8_0 -kvu \
-ctkd q4_0 -ctvd q4_0 -ngld 99 \
-c 64000 -b 1024 -ub 128 -np 1 \
--pipeline-parallel --no-ngram
//Faster above 30% context load
llama-server -m Qwen3.8-Flash-Next-UD-IQ3_XXS-00001-of-00003.gguf \
-md mtp.gguf -ctk q8_0 -ctv q8_0 -kvu -fa on -c 64000 \
-np 1 -t 8 -b 1024 -ub 128 --spec-type draft-mtp,ngram-mod \
--spec-draft-n-max 2 --spec-ngram-mod-n-match 24 --spec-ngram-mod-n-min 48 \
--spec-ngram-mod-n-max 64 -ctkd q4_0 -ctvd q4_0 \
--pipeline-parallel -nhmoe 34 -ngl 99 -ngld 99 --no-ngram
Serving Safetensors Checkpoints
-m / --model accepts a Hugging Face safetensors checkpoint directly: either a directory with config.json and its shards, or a single .safetensors file. No GGUF file is produced - the checkpoint metadata is read into memory and the weights are streamed from the shards while the model buffers are filled, so the shards stay untouched and no extra disk space is used.
llama-server -m /path/to/Qwen3.6-35B-A3B-FP8 -c 32768
| Flag | Description |
|---|---|
--safetensors-outtype TYPE | Storage type for the quantized weights of the checkpoint: auto (default) keeps FP8 weights in q8_0 and packed int4 weights in q4_0, so neither expands to 16 bits. f16, bf16, q8_0 and q4_0 force one type for every quantized weight. NVFP4 weights are always kept in nvfp4, the flag does not apply to them. |
--safetensors-native | Keep the FP8 weights of the checkpoint as they are stored, in the f8_e4m3 type: the E4M3 codes plus the fp32 scale of every block of 128 values, 8.25 bits per weight. This is the same as --safetensors-outtype native, and it takes precedence over everything else the outtype asks for. |
Notes:
-mm/--mmprojaccepts the same checkpoint: the vision tower is built in memory as a CLIP model, so images work without a convertedmmproj-*.gguf. The capabilities of the tower are read from the same in memory metadata, the checkpoint is never opened as a GGUF file.- MTP:
--spec-type draft-mtpuses the MTP layer that is part of the checkpoint, and-md <checkpoint>loads only its MTP block as a standalone draft (-mdwith a safetensors path is detected automatically). The block can sit in the main shards or in a shard of its own, like themodel_mtp.safetensorsof Qwen3.5. - Weights stored as-is in the checkpoint (
BF16,F16,F32) are read withmmapand take no extra RAM, exactly like a GGUF file. Everything else is produced by the source while the model buffers are filled: FP8 is dequantized with its 128x128 block scales or its per tensor scale, compressed-tensors int4 weights are unpacked with their per group scales, NVFP4 weights are repacked in thenvfp4blocks with their E4M3 scales, packed experts are collected into a single 3d tensor, norms and linear attention parameters are adjusted, and the vision tower is cast to F16/F32 - the same work the converter does, in memory. For a 35B FP8 checkpoint that is about 35 GB of RAM withq8_0(nothing is written to disk). --safetensors-nativekeeps FP8 weights inf8_e4m3instead of requantizing them toq8_0, so the codes and the block scales of the checkpoint survive bit for bit. The CPU vector kernels decode the codes directly, CUDA dequantizes them in the kernel and Vulkan in the shader. The type has no matrix-matrix kernels: on both GPU backends batches of up to 8 columns use the vector kernels, larger ones the dequantizeto_f16path. CUDA offloads routed experts (MUL_MAT_ID) of MoE checkpoints as well, Vulkan does not, so on Vulkan the experts of a MoE checkpoint stay on the CPU. SYCL, Metal and WebGPU do not implement the type.- The block of
f8_e4m3covers 128 values and holds one fp32 scale, so the row length of every FP8 weight of the checkpoint must be a multiple of 128. The loader stops with an error naming the tensor otherwise. - Exl3 checkpoints (ExLlamaV3) are decoded in memory as well: every quantized linear holds a trellis of 1 to 3 bit coded indices plus one factor per input and per output channel. The loader runs the reference decode (the 16 bit sliding window through the mul1 codebook, then the Hadamard transform of 128 along both axes with the factors) and emits a dense weight. The output type follows the bit width of each tensor - 1 and 2 bit tensors become
q2_k, 3 bit tensorsq3_k- so a 2.0 bpw 27B checkpoint lands near its own file size (about 12 GB resident for a 9.7 GB checkpoint).--safetensors-outtype q8_0,f16,bf16orq4_0overrides that with one higher precision type for every tensor when memory is not the constraint. - The native path is verified against the same checkpoint loaded on the CPU: CUDA reproduces the CPU logits (
Mean KLD -0.000000,100 %identical top tokens), Vulkan stays within its own rounding (0.000108,99.2 %identical top tokens). - A modelopt
MIXED_PRECISIONcheckpoint quantizes the attention layers to FP8 and the FFN and the LM head to NVFP4, layer by layer. The NVFP4 weights keep their original bits and theirweight_scale_2andinput_scaleare loaded as the separate<name>.scaleand<name>.input_scaletensors that the graph multiplies with, exactly like the converter stores them. - The tokenizer is read from
vocab.jsonandmerges.txtwhen the checkpoint ships them, otherwise fromtokenizer.json, so checkpoints that only carry the fast tokenizer load as well. - The SSD streaming flags (
-ssd,-nssd,--ngram-ssd) cannot page those tensors from disk, the loader logs a warning when they are requested. - Supported checkpoints with a hand written mapping:
qwen3_5(Qwen3.5 / Qwen3.8 dense),qwen3_5_moe(Qwen3.5 / Qwen3.6 MoE),gemma4/gemma4_unified(Gemma 4, text model of the unified multimodal checkpoints),NemotronH(Nemotron-H and Nemotron-3 Nano Omni, text model) andagnes(Agnes 3.0), text model and vision tower of the qwen and agnes families. - The nemotron-h mapping reads the hybrid layout of that family: the layer pattern (
Mmamba2,Eexperts,*attention) decides the per layer feed forward length and kv head count, the mamba2 parameters keep the shapes this runtime expects (the group norm split by the ssm groups, A_log negated and exponentiated, D and A_log as columns), and the routed experts are NVFP4 packed per expert, stacked into one tensor with the per expert scales next to it. Its scale factors are the ones the converter writes:context_lengthof the hybrid window, the uniform head width for the rope, and thepixtralpre-tokenizer of the checkpoint. - The gemma 4 mapping covers what that family needs on top of the plain decoder: the sliding window pattern per layer, the separate head dimensions and rope of the full attention layers, the shared kv layers, the per layer output scale, the key used as value where the checkpoint has no
v_proj, and the frequency factors of the proportional rope, which the loader generates like the converter does. Its tokenizer is read as the sentencepiece style pieces of this repo (gemma4tokenizer), the token ids match the ones of the Hugging Face tokenizer. - A checkpoint whose tensor names do not line up with what the architecture expects is refused with the name of the missing tensor, and a checkpoint that mixes several compressed-tensors groups (e.g. FP8 attention with NVFP4 FFN, as the unsloth NVFP4 releases do) is handled per tensor: the group of every tensor is resolved by name, and the global scales of the NVFP4 groups are applied as the reciprocal ggml expects.
- Any other checkpoint of a plain decoder is read by a generic mapping: the tensor names, the hyperparameters and the tokenizer come from
config.jsonand the tokenizer files. The families known to it are llama, mistral and mixtral (llama), qwen2 and qwen2-moe, qwen3 and qwen3-moe, gemma, gemma2 and gemma3-text, olmo2, phi3 and starcoder2. It applies what those layouts need on top of the plain skeleton: the(1 + w)normalization of the gemma family, the q/k rotary permutation of the llama family, the attention biases of qwen2 and the routed experts of the MoE variants. This is pure data derived from the configuration, no per architecture code, and it is verified against the converter: loading such a checkpoint and the GGUF produced from it gives the same perplexity and logits. - A checkpoint that needs more than that - fused or reshaped projections, a tokenizer that is not byte pair encoding (SentencePiece, WordPiece, tiktoken), or a non decoder layout - is refused with the reason instead of being loaded wrongly. Convert those to GGUF first.
- Packed int4 checkpoints (compressed-tensors
pack-quantized, 4 bit weights, one scale per group of 128 columns) are loaded without expanding them to 8 or 16 bits. The routed experts of a packed checkpoint are not supported yet. - NVFP4 weights are repacked from the modelopt nibble order into the ggml
nvfp4blocks, which need a row length that is a multiple of 64. Packed NVFP4 experts are not supported yet. - Agnes 3.0 runs a second FFN in parallel with the main one. It is loaded as separate tensors (
ffn_gate_par,ffn_up_par,ffn_down_par) with the length in the new*.feed_forward_parallel_lengthkey, and the graph adds its output to the main FFN - so every weight can be mapped from the checkpoint instead of being rewritten. - Without
-nrthe fork copies the weights of CPU layers into repacked host buffers; add-nrto keep them memory mapped when serving a checkpoint that does not fit in RAM, and-ngl Nto place part of the layers in VRAM.
Building from Source
1. NVIDIA CUDA (Windows / Linux)
# CMake configure with CUDA backend
cmake -B build -DGGML_CUDA=ON
# Build Release
cmake --build build --config Release -j 2
2. Vulkan (Cross-Platform AMD / Intel / NVIDIA)
# Requires Vulkan SDK installed
cmake -B build -DGGML_VULKAN=ON
cmake --build build --config Release -j 2
3. AMD ROCm / HIP (Linux / Windows)
cmake -B build -DGGML_HIP=ON -DAMDGPU_TARGETS="gfx1100;gfx1030"
cmake --build build --config Release -j 2
4. Apple Metal (macOS)
cmake -B build -DGGML_METAL=ON
cmake --build build --config Release -j 2
5. CPU Only (AVX2 / AVX-512)
cmake -B build -DGGML_CUDA=OFF -DGGML_VULKAN=OFF
cmake --build build --config Release -j 2
-j N: The number of CPU threads the processor will use to compile, a safe number is the amount of physical cores of the processor.
Quick start
A few options to get llama.cpp installed on your machine:
- Visit https://llama.app and follow the instructions
- Run with Docker - see our Docker documentation
- Download pre-built binaries from the releases page
- Build from source by cloning this repository - check out our build guide
Once installed:
# Download and run a model directly from Hugging Face
llama cli -hf ggml-org/Qwen3.5-0.8B-GGUF
# Launch OpenAI-compatible API server
llama serve -hf ggml-org/Qwen3.5-0.8B-GGUF
Description
The main goal of llama.cpp is to enable LLM (and VLM) inference with minimal setup and state-of-the-art performance on a wide range of hardware - locally and in the cloud.
- Plain C/C++ implementation without any dependencies
- Apple silicon is a first-class citizen - optimized via ARM NEON, Accelerate and Metal frameworks
- AVX, AVX2, AVX512 and AMX support for x86 architectures
- RVV, ZVFH, ZFH, ZICBOP and ZIHINTPAUSE support for RISC-V architectures
- 1.5-bit, 2-bit, 3-bit, 4-bit, 5-bit, 6-bit, and 8-bit integer quantization for faster inference and reduced memory use
- Custom CUDA kernels for running LLMs on NVIDIA GPUs (support for AMD GPUs via HIP and Moore Threads GPUs via MUSA)
- Vulkan and SYCL backend support
- CPU+GPU hybrid inference to partially accelerate models larger than the total VRAM capacity
The llama.cpp project is build on top of the ggml library.
Supported backends
| Backend | Target devices |
|---|---|
| BLAS | All |
| BLIS | All |
| CANN | Ascend NPU |
| CUDA | Nvidia GPU |
| HIP | AMD GPU |
| Hexagon | Snapdragon |
| IBM zDNN | IBM Z & LinuxONE |
| MUSA | Moore Threads GPU |
| Metal | Apple Silicon |
| OpenCL | Adreno GPU |
| OpenVINO [In Progress] | Intel CPUs, GPUs, and NPUs |
| RPC | All |
| SYCL | Intel GPU |
| VirtGPU | VirtGPU APIR |
| Vulkan | GPU |
| WebGPU | All |
| ZenDNN | AMD CPU |
Documentation
Tools
Development
- How to build
- Running on Docker
- Build on Android
- Multi-GPU usage
- Performance troubleshooting
- GGML tips & tricks
- XCFramework
- Completions
- Models
- Release process
Contributing
- Contributors can open PRs
- Collaborators will be invited based on contributions
- Maintainers can push to branches in the
llama.cpprepo and merge PRs into themasterbranch - Any help with managing issues, PRs and projects is very appreciated!
- Read the CONTRIBUTING.md for more information
Acknowledgements
- yhirose/cpp-httplib - Single-header HTTP server, used by
llama-server- MIT license - nothings/stb - Single-header image format decoder, used by multimodal subsystem - Public domain
- nlohmann/json - Single-header JSON library, used by various tools/examples - MIT License
- mackron/miniaudio - Single-header audio format decoder, used by multimodal subsystem - Public domain
- sheredom/subprocess.h - Single-header process launching solution for C and C++ - Public domain
Summary
MoE-offloading llama.cpp fork (49 stars, MIT, quimmedes): flags to keep MoE expert weights in pinned host RAM (-hmoe, zero-copy PCIe DMA), CPU RAM (-cmoe), or SSD-streamed via mmap (-ssd — only token-selected experts page in), with first-N-layers variants and -hmoed drafter offload; attention/KV/routers stay on GPU. Targets Qwen3.8-Flash-Next, DeepSeek.
Learnings
- Strata’s tiered-offload idea as llama.cpp flags on any MoE GGUF instead of a bespoke engine — the community answer for running 125B-class MoE on 3090+32GB-class rigs. In Inference engines’s forks list; pairs with the Qwen3.8-Flash-Next section of Qwen model family.
Gotchas
- (none yet)
Hands-on
(candidate for llamacpp-tools build script; the 125B-on-doombox experiment fork)


