Skip to content

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 分配

详见 Part 1 — GGUF 二进制格式