Use your Nvidia GPU's VRAM as swap space on Linux - infra 架构解读
作者:dodo
原文:https://github.com/c0dejedi/nbd-vram 发布时间:2026-06-01 解读视角:大模型基础建设架构设计 沉淀时间:2026-06-04
一句话核心
本项目通过 CUDA API + NBD 协议,将 GPU VRAM 挂载为 Linux swap 设备,在稀疏访问场景下实现 27x 低于 NVMe 的延迟,为大模型推理服务的内存分层管理提供了一种无需内核模块的轻量工程范式。
文章背景与问题域
现代 AI 笔记本/服务器普遍面临"算力过剩、内存不足"的矛盾:GPU VRAM 在推理空闲期大量闲置,而系统 RAM 频繁溢出到 NVMe SSD,导致 4K page fault 平均延迟高达 9ms(APST 唤醒代价)。
问题:能否将 GPU VRAM 作为比 NVMe 更快的 swap tier,在不修改内核的前提下实现零侵入接入?
这个问题对大模型基建的意义在于:大模型推理服务在低并发时需要将 KV cache、模型权重以外的内存高效释放,而 VRAM 的高带宽低延迟恰好适合作为中间层 buffer。
核心架构 / 方案解析
数据路径
kernel swap subsystem
│
▼
/dev/nbdX (block device)
│
▼
nbd kernel driver (built-in, no module needed)
│ Unix socket
▼
nbd-vram daemon (userspace)
│ CUDA API
▼
GPU VRAM (cuMemcpyHtoD / DtoH)
关键设计选择
为什么用 NBD 而不是直接 ioremap?
项目作者明确排除了两种"显然"方案:
nvidia_p2p_get_pages_persistent:在 BAR1 pinning VRAM pages,GeForce 上 NVIDIA 驱动 RM 层强制返回 EINVAL(仅 Quadro/数据中心 SKU 开放)- 直接
ioremap_wcBAR1 物理地址:GPU 内部页表仅 MAP 了 ~16 MiB(显示帧缓冲区),其余读取返回零
NBD 方案通过 cuMemcpy{HtoD,DtoH} 绕开以上限制,适用任意消费级 CUDA GPU,无特权驱动接口依赖。
服务架构
- daemon 通过 CUDA driver API(非 CUDA Toolkit)分配 VRAM,并通过 Unix socket 暴露 NBD 协议
- systemd 服务管理生命周期,支持 AC/电池状态自动启停
- 降级策略:若 GPU 内存不足,以 512 MiB 步长回退,尽量填满可用空间(ceiling 而非硬性要求)
关键工程决策与权衡
| 决策点 | 选择 | 放弃的方案 | 理由 |
|---|---|---|---|
| VRAM 访问方式 | CUDA cuMemcpy (userspace) | nvidia_p2p / ioremap | GeForce 驱动封锁内核 P2P 路径 |
| 传输协议 | NBD over Unix socket | 直接内核模块 | 无需修改内核,跨驱动版本生存 |
| 部署方式 | systemd daemon | 内核模块 / eBPF | 不依赖内核符号,升级不重编译 |
| 容量策略 | 软 ceiling + 步长回退 | 硬性失败 | 提高在多租户 GPU 场景下的成功率 |
大模型基建视角专项解读
性能与资源优化
基准测试数据揭示了一个与直觉相悖的结论:
| 指标 | NVMe | VRAM (nbd) |
|---|---|---|
| 顺序写带宽 | 2.7 GB/s | 1.1 GB/s |
| 4K 随机 IOPS | 45.4k | 28.7k |
| 平均延迟(稀疏) | 9.05 ms | 335 µs(27x 更快) |
NVMe 在大块连续 I/O 上占优,VRAM 在稀疏访问上以 27x 优势胜出。原因是 NVMe 的 APST(自主电源状态转换)在每秒仅 1 次请求时几乎每次都需要冷唤醒(~9ms),而 VRAM 无 power state 概念。
大模型基建启示:AI 推理服务的内存溢出特征正好是稀疏 page fault(长上下文、多轮对话 KV cache 逐渐填满),VRAM swap 在此场景下的延迟优势会被完整发挥。
系统架构与分层设计
本项目本质上实现了一个三层内存分层架构:
层级 | 设备 | 优先级 | 特性
RAM | DRAM | 最高 | 最快,直接访问
VRAM | GPU VRAM | 次高 | PCIe 延迟,但无 power state 问题
zram | CPU 压缩 | 再次 | 牺牲 CPU 换内存
SSD swap | NVMe | 最低 | 容量最大,延迟最高
这与大模型推理中的 KV cache 分层卸载策略(GPU HBM → CPU DRAM → NVMe offload)在设计模式上高度同构。
容错与可靠性
- VRAM 容量弹性:daemon 以 512 MiB 步长降级分配,确保在 GPU 已被推理任务占用部分显存时仍能成功初始化
- 电源感知:AC 断开时自动停止 swap 服务,恢复时重启,防止在电池供电下产生意外 PCIe 带宽消耗
- 无构建依赖:NBD 协议内置于 Linux 内核 3.0+,daemon 仅依赖 libcuda.so.1(无 CUDA Toolkit),服务在内核/驱动升级后无需重建
工程模式提炼
| 模式名 | 文章中的实现 | 大模型基建启示 |
|---|---|---|
| 硬件分层 Tiered Memory | RAM→VRAM→zram→SSD 优先级链 | KV cache offload 分级策略(HBM→DRAM→NVMe) |
| 协议间接层 Protocol Indirection | NBD over Unix socket 绕开驱动封锁 | 当硬件直连 API 受限时,用标准协议封装能力 |
| Soft Ceiling + Step Backoff | 512 MiB 步长降级 VRAM 分配 | 多租户 GPU 内存分配:失败前尽量利用剩余空间 |
| Power-Aware Lifecycle | AC/Battery 状态驱动服务启停 | AI 推理服务在低负载时回收硬件资源的自动化策略 |
| Userspace Driver Bypass | CUDA userspace API 替代内核 P2P | 用计算框架 API 绕开受限内核接口,降低权限依赖 |
反常识点梳理
| 反常识点 | 常规认知 | 文章实际做法 | 背后原因 |
|---|---|---|---|
| VRAM 比 NVMe 快 27x | NVMe PCIe 4.0 随机 I/O 快 | 稀疏访问场景 VRAM 延迟 27x 更低 | NVMe APST 唤醒代价 9ms,VRAM 无 power state |
| 消费级 GPU 无法直接映射 VRAM | BAR1 ioremap 可以直接访问 | GeForce 内部页表只映射了 ~16MB | NVIDIA 在 RM 层封锁 P2P,仅 Quadro/数据中心开放 |
| NBD 性能不如内核模块 | 用户态协议有额外 socket 开销 | Unix socket round-trip 在实测中可接受 | 延迟瓶颈在 NVMe APST,而非 NBD 协议本身 |
延伸思考
-
推理服务 VRAM 分时复用:当推理框架(如 vLLM)未完全填满 GPU 显存时,是否可以动态将剩余 VRAM 挂载为 KV cache overflow 池?与 nbd-vram 的区别在于直接走 CUDA 共享内存而非 swap,需要推理框架侧显式支持。
-
多 GPU 协作 swap 网络:在多卡推理节点中,每张 GPU 的 VRAM 都可以通过 NVLink/PCIe 为其他 GPU 的溢出内存服务,本质上是 GPU 间的分布式 swap ring。nbd-vram 的 NBD 协议可以扩展到 TCP 而非 Unix socket,实现跨节点 VRAM pool。
-
延迟分布不均问题:文章 benchmark 显示 VRAM 最大延迟 490µs、NVMe 最大 10.1ms,但实际 swap 压力下的 p99/p999 如何?在大模型推理对 token 生成延迟敏感的场景,需要更细粒度的延迟分位数测量。