Hotdry.

Article

Gemma4-31B 在 16GB Mac 上的 Swap-Aware 内存管理:mmap 调优与逐层加载策略

在极端内存约束下运行大模型,探讨 mmap 内存映射、MoE 架构优势与量化策略的权衡,提供可落地的参数配置与监控方案。

2026-05-21ai-systems

在 16GB 内存的 MacBook 上运行 Gemma4-31B 这类 310 亿参数模型,本质是一场与操作系统内存管理器的博弈。模型权重本身在 Q4 量化下约需 17–20GB,加上 KV Cache 的 2–4GB 开销,远超物理内存容量。不加干预的直接加载会导致系统瞬间陷入重度 swap,token 生成速度从可用的 10+ tok/s 暴跌至不足 1 tok/s,甚至触发系统冻结。

但工程实践表明,通过精细的内存管理策略,16GB 设备确实可以承载远超其物理容量的模型。核心在于理解 mmap 内存映射机制、模型架构特性(MoE vs Dense)以及 macOS 统一内存架构的行为模式。

内存困境的本质:为什么 16GB 不够却又能运行

Gemma4-31B 的内存占用遵循一个简单的计算公式:模型权重 + KV Cache + 系统开销。Q4 量化将每个参数压缩至 4 比特,31B 参数约需 15.5GB 存储,加上推理过程中的激活值和缓存,实际工作集轻松突破 20GB。在 16GB 统一内存的 Apple Silicon 设备上,这意味着必然触发 swap。

swap 的问题不在于 "使用磁盘空间",而在于随机 page fault 的延迟累积。当模型推理需要访问尚未加载到内存的权重页时,系统必须从 SSD 读取,NVMe 的毫秒级延迟在 LLM 推理的上下文中被放大为秒级卡顿。一次 page fault 可能只延迟几毫秒,但在生成数百个 token 的过程中,累积效应使体验变得不可接受。

mmap 策略:用虚拟内存扩展有效容量

mmap(内存映射)是解决这一困境的关键技术。传统加载方式将模型文件完整读入内存,而 mmap 将模型文件映射为虚拟地址空间,由操作系统按需分页加载。这意味着:

  • 共享层常驻内存:注意力机制、嵌入层、归一化层等高频访问的权重保持在 RAM 中(约 4–6GB)
  • 专家权重按需分页:仅在激活时从 SSD 加载,使用完毕后由 OS 回收或保留在页缓存中
  • 零拷贝访问:Apple Silicon 的统一内存架构消除了 CPU-GPU 之间的数据复制开销

实际案例显示,在 16GB Mac Mini M4 上使用 --mmap 标志运行 Qwen3.5-35B-A3B(35B 总参数,3B 激活参数),可实现 17.3 tok/s 的生成速度,内存占用仅 19%,且零 swap。这证明了 mmap 配合 MoE 架构的可行性。

MoE vs Dense:架构决定内存策略的有效性

并非所有模型都能从 mmap 策略中同等受益。Mixture of Experts(MoE)架构与 Dense 架构在内存访问模式上存在本质差异:

MoE 模型(如 Qwen3.5-A3B、Gemma4-26B-A4B)每 token 仅激活部分专家网络(如 3.8B/26B)。这意味着在任意推理步骤中,大部分权重处于 "冷" 状态,无需常驻内存。mmap 的按需分页机制与这种稀疏激活模式完美契合。

Dense 模型(如 Gemma4-31B、Gemma4-12B)在推理过程中可能访问全部参数。虽然量化减少了单参数占用,但工作集仍然庞大。在 16GB 设备上运行 Dense 31B 模型时,mmap 只能延缓 swap 的发生,无法避免频繁的 page fault。

因此,在内存受限场景下,选择 MoE 变体往往比强行优化 Dense 模型更具性价比。Gemma4-26B-A4B 仅需约 8–10GB 内存即可流畅运行,而 31B Dense 版本在相同硬件上即便使用 mmap 也难以达到可用速度。

可落地的参数配置清单

基于实际部署经验,以下是针对 16GB Apple Silicon 设备的推荐配置:

llama.cpp 服务端配置(用于大模型 / Heavy Tier)

llama-server \
  --model ~/.local/share/llama-models/Qwen3.5-35B-A3B-UD-IQ3_XXS.gguf \
  --port 8081 \
  --ctx-size 16384 \
  --n-gpu-layers 0 \
  --mmap \
  --flash-attn on \
  --threads 8

关键参数说明:

  • --mmap:启用内存映射,避免完整加载模型
  • --n-gpu-layers 0:强制走 mmap 路径,由 OS 管理分页而非 GPU 显存
  • --flash-attn on:减少 KV Cache 内存占用
  • --ctx-size 16384:根据可用内存调整上下文窗口

Ollama 环境配置(用于中小模型 / Fast & Primary Tier)

export OLLAMA_FLASH_ATTENTION=1
export OLLAMA_KV_CACHE_TYPE=q8_0
export OLLAMA_KEEP_ALIVE=10m
export OLLAMA_MAX_LOADED_MODELS=1

关键参数说明:

  • OLLAMA_MAX_LOADED_MODELS=1:强制单模型驻留,避免多模型同时加载导致 OOM
  • OLLAMA_KV_CACHE_TYPE=q8_0:KV Cache 量化,减少长上下文时的内存压力
  • OLLAMA_KEEP_ALIVE=10m:空闲 10 分钟后卸载模型,释放内存

模型选择建议

硬件配置 推荐模型 量化级别 预期速度
16GB Gemma4-E4B (4.5B) Q4 80+ tok/s
16GB Qwen3.5-35B-A3B (MoE) IQ3_XXS 15–20 tok/s
16GB Gemma4-31B (Dense) Q4 <5 tok/s,不推荐
24GB Gemma4-26B-A4B (MoE) Q4 20–30 tok/s
36GB+ Gemma4-31B (Dense) Q4 8–12 tok/s

监控与回滚策略

在生产环境部署时,需要建立以下监控机制:

Swap 压力识别

  • 使用 vm_stat 1 观察 pageout 速率,持续非零值表明内存压力
  • 监控 Activity Monitor 中的 "内存压力" 图表,黄色 / 红色区域表示进入 swap
  • 当 token 生成速度低于阈值(如 5 tok/s)时触发告警

模型降级策略

  • 实现三级路由:Fast Tier (E2B/E4B) → Primary Tier (9B/26B MoE) → Heavy Tier (35B MoE)
  • 当检测到内存压力时,自动降级到更小模型或增加量化级别
  • 保留模型文件在本地磁盘,支持快速回滚

思考模式控制

  • 对于分类、路由等简单任务,显式禁用思考模式(think: false),可减少 30 倍延迟
  • 复杂推理任务保留思考模式,但限制上下文长度

权衡与边界

mmap 策略并非万能。它用磁盘 I/O 延迟换取内存容量,在以下场景存在局限:

  1. Sequential 访问模式:Dense 模型在生成过程中可能顺序访问大量权重,导致持续的 page fault 风暴
  2. 长上下文场景:KV Cache 随上下文长度线性增长,最终仍会挤占权重页的内存空间
  3. 多任务并发:同时运行多个模型或应用时,页缓存被频繁驱逐,命中率下降

在 16GB 设备上,建议将 mmap 策略限定于 MoE 架构的 "重载" 模型,而 Dense 模型应选择更小的变体(如 E4B)或升级硬件至 36GB+。

资料来源

ai-systems

内容声明:本文无广告投放、无付费植入。

如有事实性问题,欢迎发送勘误至 i@hotdrydog.com