Appearance
将文件内容直接映射到进程的虚拟地址空间,像操作内存数组一样访问文件,无需 read/write 系统调用。
为什么用 mmap 加载模型
DeepSeek V4 Flash 的模型文件约 81GB。如果用 fread 加载,需要:
- 分配 81GB 用户空间内存
- 从内核空间拷贝到用户空间(81GB 的内存拷贝)
- 等待全部拷贝完成才能开始推理
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_SHARED | GPU 可直接零拷贝引用同一块物理内存 |
| CPU only | MAP_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 区域配合