摘要
本文系统分析 AMD GPU 计算栈中 KFD(Kernel Fusion Driver,亦称 amdkfd)子系统所实现的 SVM(Shared Virtual Memory,共享虚拟内存)机制。重点阐述其基于 Linux HMM(Heterogeneous Memory Management)框架的地址空间共享模型、GPU 页错误(retry fault)处理流程、MMU notifier 驱动的地址一致性维护,以及跨设备内存迁移策略,并结合工作流程图说明各模块间的协同关系。
1 引言
在异构计算体系中,CPU 与 GPU 传统上各自维护独立的虚拟地址空间,数据交换依赖显式的内存拷贝(hipMemcpy/clEnqueueWriteBuffer)与固定映射(pinned memory)。这种模型编程复杂、迁移开销大,难以支撑指针链表、图结构等不规则数据结构的高效跨设备访问。
KFD 是 Linux amdgpu 内核驱动中负责计算队列管理与用户态直接提交(user-mode queue submission)的子模块,ROCm 运行时通过 /dev/kfd 与之交互。SVM 是 KFD 在此基础上提供的地址空间统一能力,使 GPU 可以直接解引用一段与 CPU 进程共享的虚拟地址,由内核按需完成物理页的绑定与迁移。
2 背景机制
2.1 HMM 框架
Linux HMM 提供两类核心能力:
- •
hmm_range_fault:允许设备驱动查询一段虚拟地址对应的物理页帧,若页面不在内存中(换出或从未分配),触发常规缺页处理后再返回。 - • 镜像页表(mirror page table):设备驱动维护一份与 CPU 页表逻辑一致的映射表,通过
mmu_notifier 感知 CPU 侧的失效/迁移事件,保持二者同步。
2.2 IOMMU 与 ATC
MI 系列等支持 SVM 的 AMD GPU 依赖 IOMMUv2 提供的 ATS/PRI(Address Translation Service / Page Request Interface):GPU 可直接使用进程的 CPU 虚拟地址发起访存,若地址未映射,通过 PRI 向 IOMMU 发起页请求,IOMMU 转发给内核缺页处理路径,处理完成后回填并唤醒等待的 GPU wavefront。
2.3 XNACK 机制
GPU 硬件对未就绪页面的访问会返回 XNACK(重试应答),指令流水线挂起对应 wavefront 而非直接产生致命异常,待内核完成映射后由硬件自动重放访存请求。这是 SVM“按需缺页”得以实现的硬件基础。
3 KFD 中的 SVM 架构
3.1 核心数据结构
- •
svm_range:描述一段注册为 SVM 的虚拟地址区间,记录其当前驻留位置(System RAM 或某块 VRAM)、优先级提示(prefetch/preferred location)以及关联的 mm_struct。 - •
svm_range_list:每个进程一份,以区间树(interval tree)组织所有 svm_range,支持地址重叠查询与合并。 - •
kfd_process:进程级上下文,持有 SVM 区间列表及与之绑定的多个 GPU 设备的页表实例。
3.2 注册路径
应用通过 HSA_MEM_ALLOC 或 hipMallocManaged/hsaKmtSVMSetAttr 等接口注册地址区间,KFD 在 svm_range_list 中插入对应节点,但此时并不立即建立 GPU 页表映射——真正的映射延迟到首次访存触发缺页时才进行,体现“按需”特性。
4 页错误处理流程(核心工作原理)
关键点说明:
- 1. 异步性:整个流程由内核工作队列(workqueue)异步处理,不阻塞其他 wavefront,保证 GPU 整体吞吐。
- 2. 迁移决策:KFD 根据访问热度、
preferred_location 属性以及 XNACK 重试统计,决定页面是留在系统内存(通过 ATS 直接访问)还是迁移到本地 VRAM(通过 migrate_vma_setup/migrate_vma_pages 完成,底层使用 DMA 引擎拷贝)。 - 3. 粒度:迁移以 2MB 大页为倾向粒度,减少页表项数量与迁移次数,但也支持 4KB 粒度回退。
5 地址一致性维护:MMU Notifier
CPU 侧对页面的任何变更(munmap、mprotect、swap-out、THP 拆分、NUMA 迁移等)都会触发 mmu_notifier 回调链:
这保证了 GPU 页表始终是 CPU 页表的"最终一致"镜像:GPU 不会持有已被 CPU 释放或迁移的陈旧物理地址映射,避免出现"野指针"式的跨设备内存踩踏。
6 关键工程权衡
| 维度 | 设计选择 | 收益 | 代价 |
|---|
| 缺页触发时机 | 首访问才建立映射 | 节省预注册开销、支持超额订阅 | 首次访问延迟(cold fault) |
| 迁移粒度 | 2MB 大页优先 | 减少页表项、提升 TLB 命中 | 可能过度迁移(false sharing) |
| 一致性维护 | MMU notifier 主动失效 | 严格一致性、避免踩踏 | 频繁失效带来的抖动开销 |
| 硬件依赖 | 依赖 XNACK/ATS/PRI | 无需驱动轮询,硬件级重放 | 仅特定架构(如 MI 系列)支持 |
7 与传统显式管理模型的对比
- • 显式拷贝模型(
hipMalloc + hipMemcpy):地址空间独立,迁移时机由程序员完全控制,峰值性能可预测,但编程复杂、无法支持超额订阅。 - • SVM 模型:地址空间统一,迁移由内核按访问模式自动决策,显著简化编程模型,支持比显存更大的工作集,但引入缺页延迟与迁移抖动的不确定性,对访存局部性差的负载可能出现性能倒退(thrashing)。
二者并非互斥——ROCm 运行时通常允许在同一进程中混合使用,由开发者针对关键路径显式管理,非关键路径使用 SVM 简化开发。
8 结论
KFD 的 SVM 子系统本质上是 HMM 通用异构内存管理框架 + AMD GPU 硬件级页请求重放能力(XNACK/ATS/PRI) 的结合体:前者提供软件层面的地址空间镜像与一致性维护逻辑,后者提供硬件层面"缺页可重放"的执行语义,二者共同将传统上需要程序员显式管理的跨设备内存一致性问题下沉到内核与硬件协同处理,是当前 GPU 计算栈向"类 NUMA"统一内存模型演进的代表性实现路径。