Appearance
GPT-Generated Unified Format —— llama.cpp 生态的二进制模型文件格式,一个文件包含完整的模型参数和元数据。
为什么需要专用文件格式
训练好的模型有几十 GB 的参数(张量)和大量配置信息(层数、维度、词表等)。如果用 JSON 存元数据 + 单独文件存权重,加载慢且容易版本不一致。GGUF 把所有东西打包成一个紧凑的二进制文件,支持零拷贝 mmap 加载。
文件结构
┌──────────────────────────────┐
│ Header (24 bytes) │ magic "GGUF" + version + 张量数 + KV 数
├──────────────────────────────┤
│ 元数据 KV 表 │ 模型名、架构参数(层数/维度/词表...)
│ string/int/float/array │ 零拷贝:ds4_str 直接指向 mmap 区域
├──────────────────────────────┤
│ 张量目录 │ 每个张量的名称、维度、类型、偏移量
├──────────────────────────────┤
│ 对齐填充 │
├──────────────────────────────┤
│ 张量数据 │ 实际权重,支持多种量化格式
│ Q2_K / Q4_K / Q8_K / ... │ 通过 mmap 按需加载,不全部读入内存
└──────────────────────────────┘在 ds4.c 中的实现
c
// ds4.c — 游标模式(cursor)解析 GGUF
ds4_cursor cur = {data, end}; // 初始化游标,指向 mmap 内存
uint32_t magic = cursor_u32(&cur); // 读 4 字节,游标自动前进
ds4_str name = cursor_string(&cur); // 零拷贝:返回 {ptr, len},不复制字符串关键设计:
- 游标模式:
cursor_u32/cursor_string/cursor_skip等函数顺序读取,比 fseek + fread 简洁得多 - 零拷贝字符串:
ds4_str是{ptr, len}结构体,直接指向 mmap 区域 - 尽早失败:
config_validate_model执行 30+ 参数校验,加载阶段就发现不兼容的模型 - 按需加载:张量数据留在内核页缓存中,推理需要时才触发 page fault
相关概念
- mmap — GGUF 通过 mmap 加载,张量数据零拷贝访问
- page-fault — 大模型不会全部读入内存,靠 page fault 按需加载
- xmalloc — 游标和元数据结构使用 xmalloc 分配