Skip to content

将文件内容直接映射到进程的虚拟地址空间,像操作内存数组一样访问文件,无需 read/write 系统调用。

为什么用 mmap 加载模型

DeepSeek V4 Flash 的模型文件约 81GB。如果用 fread 加载,需要:

  1. 分配 81GB 用户空间内存
  2. 从内核空间拷贝到用户空间(81GB 的内存拷贝)
  3. 等待全部拷贝完成才能开始推理

mmap 避免了这一切:文件直接映射到虚拟地址,内核按需加载页面,无需拷贝。Metal GPU 还能直接引用 mmap 内存,实现真正的零拷贝。

核心原理

传统 read:                mmap:
磁盘 → 内核缓冲区          磁盘 ←→ 物理内存
      → 用户空间缓冲区              ↕ (页表映射)
      → 使用                        用户空间指针直接访问

mmap 后,访问 ptr[0] 就像访问数组。如果对应页面还没加载到物理内存,CPU 触发 page fault,内核自动从磁盘读入,对程序透明。

在 ds4.c 中的实现

c
// ds4.c — model_open 中的 mmap 调用
void *map = mmap(NULL, st.st_size, PROT_READ, flags, fd, 0);

两种 flags 策略:

平台flags原因
Metal(macOS)MAP_SHAREDGPU 可直接零拷贝引用同一块物理内存
CPU onlyMAP_PRIVATE避免 macOS VM 内核 bug(写时复制)

张量数据通过偏移访问,始终在 mmap 区域内:

c
void *tensor_data(model, tensor) = model->map + tensor->abs_offset;

预热优化:model_warm_weights() 逐页(每 4096 字节)读取触发 page fault,将延迟集中在启动阶段,避免推理时的延迟抖动。

相关概念

  • page-fault — mmap 的按需加载依赖 page fault 机制
  • gguf — GGUF 文件通过 mmap 加载,游标直接在映射区解析
  • xmalloc — 预热后的数据结构用 xmalloc 分配,与 mmap 区域配合

详见 Part 1 — 内存管理与 mmap