Dissecting llama.cpp, Part 1: From GGML to GGUF, and Why llama.cpp Is Just the Wrapper
GGML is a lightweight C/C++ tensor library and model serialization format designed specifically for running LLaMA on consumer CPU hardware without GPU dependencies or Python frameworks GGML's graph-first execution model builds the full computation graph before running, enabling single memory allocation and reuse across all tokens—critical for batch-size-1 autoregressive generation where memory bandwidth, not compute, is the bottleneck The GGML file format evolved through three iterations (unvers
Analysis
TL;DR
- GGML is a lightweight C/C++ tensor library and model serialization format designed specifically for running LLaMA on consumer CPU hardware without GPU dependencies or Python frameworks
- GGML's graph-first execution model builds the full computation graph before running, enabling single memory allocation and reuse across all tokens—critical for batch-size-1 autoregressive generation where memory bandwidth, not compute, is the bottleneck
- The GGML file format evolved through three iterations (unversioned GGML → versioned GGMF → GGJT), with GGJT adding memory-mapping support for near-instant loading of multi-gigabyte model files
- PyTorch's eager execution model suffers from per-operation allocation overhead that becomes a severe disadvantage at batch size 1, while GGML's compile-time fixed 4-dimensional tensor struct eliminates dynamic shape allocation entirely
- llama.cpp is fundamentally a thin wrapper around GGML; understanding GGML's tensor structure, computation graph, and quantization schemes is essential to understanding how local LLM inference actually works
Why It Matters
This article provides the foundational engineering context that most practitioners skip when learning to run local LLMs, revealing why quantization and CPU inference are viable at all. For AI engineers working on deployment, edge computing, or cost-constrained inference, understanding the GGML design philosophy—graph execution, memory mapping, aggressive quantization—directly informs decisions about model serving architecture and hardware selection.
Technical Details
- GGML tensor struct: Fixed at compile time with a maximum of 4 dimensions (
GGML_MAX_DIMS), eliminating dynamic shape allocation. Each tensor carries metadata including data type (ggml_type), stride/bytes per dimension (nb[]), computation graph node info (op,src[]), and optional view/slice tracking (view_src,view_offs) for memory-efficient operations like reshaping without copying data. - Graph execution vs. eager execution: GGML constructs a complete computation graph before any operations run, reserving all intermediate tensor memory upfront and reusing the same buffers across every token generation step. This contrasts with PyTorch's eager mode, which allocates and deallocates memory per operation—acceptable for batched training but costly for the matrix-vector multiplies that dominate autoregressive inference.
- GGJT file format layout: Binary serialization with an 8-byte header (4-byte magic number + 4-byte version), followed by 28 bytes of fixed hyperparameters (
n_vocab,n_embd,n_mult,n_head,n_layer,n_rot,ftype), then variable-length vocabulary entries (4-byte token length + token bytes + 4-byte float32 score per token), and finally tensor data blocks with per-tensor descriptors (dimensions, name, dtype, alignment padding, raw data). - Quantization storage math: For Q4_0 quantization, each block represents 32 weights (
QK4_0 = 32) stored in 18 bytes (tysize), comprising a 2-byte delta/scale and 16 bytes of nibbles. The general formula isn_bytes = n_elems × tysize / blksize, with each quantization scheme defining its ownblksize/tysizepair. - Memory mapping (mmap): GGJT-format files are aligned to enable direct memory mapping, allowing the OS to load model weights on demand rather than reading the entire multi-gigabyte file into RAM upfront—this is the primary reason model loading feels near-instantaneous even for large models.
Industry Insight
- The batch-size-1 performance crossover between GGML and PyTorch demonstrates that framework choice for inference should be driven by the actual workload shape, not training benchmarks—practitioners should evaluate inference frameworks using single-token generation patterns rather than bulk matrix operations.
- The three-stage evolution of the GGML file format (unversioned → GGMF → GGJT) illustrates a common pattern in ML infrastructure: early formats prioritize functionality over compatibility, then add versioning, then optimize for the actual deployment access pattern (memory mapping)—teams building model serialization tools should plan for all three stages from the start.
- GGML's design choices—zero dependencies, consumer hardware targeting, aggressive quantization—created an entirely new category of local LLM inference that has since been widely copied; understanding this origin story helps practitioners evaluate emerging alternatives (like MLX, ONNX Runtime, or TensorRT-LLM) on their actual design tradeoffs rather than surface-level feature comparisons.
Disclaimer: The above content is generated by AI and is for reference only.