免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

第八章:GPUVM:GPU 内存管理是 CPU MM 的“平行宇宙”

第八章:GPUVM:GPU 内存管理是 CPU MM 的“平行宇宙” 在深入分析drm gpuvm的设计和实现前我想先给出理解这个领域的一个视角视角对了一切设计就是水到渠成。视角如下 Linux 内核 GPU 内存管理子系统TTM、GEM、GPUVM与经典 CPU 内存管理MM子系统之间的结构和功能具有高度相似性。我们认为GPU 内存栈不仅仅是受 CPU MM 启发——它是在不同硬件约束下对相同基本原则的重新推导。这种类比并非偶然而是架构上的必然它通过共享的术语、相同的算法模式以及趋同的设计轨迹深深嵌入内核的 DRM 子系统中。1. 论点Linux GPU 内存管理子系统TTM/GEM/GPUVM构成了经典 CPU 虚拟内存概念的领域特定重新实现——包括虚拟地址空间、按需分页、基于 LRU 的驱逐和交换——以适应离散加速器内存层次结构的约束。这一论点由以下证据支持直接的词汇借用swap_storage、TTM_TT_FLAG_SWAPPED、ttm_tt_swapin()同构的数据结构设计drm_gpuvm↔mm_structdrm_gpuva↔vm_area_struct相同的算法策略LRU 驱逐扫描、shrinker 集成、故障驱动的填充趋同的演化GPU 故障处理通过 SVM/HMM 向 CPU 风格的按需分页发展2. 论证2.1 地址空间管理CPU MMGPU MMDRM结构角色mm_structstruct drm_gpuvm每上下文的虚拟地址空间容器vm_area_structstruct drm_gpuva映射到后备对象的连续 VA 区域VMA 红黑树GPUVM 区间红黑树用于快速查找的空间索引mmap()/munmap()drm_gpuvm_sm_map()/drm_gpuvm_sm_unmap()面向用户的 VA 空间变更部分解映射时的 VMA 分割/合并drm_gpuva_op_remap分割维护 VA 空间一致性drm_gpuvm文档指出“DRM GPU VA 管理器使用 maple_tree 结构来跟踪 GPU 的虚拟地址空间……每个 GPU 虚拟地址空间应该有一个管理器实例。”这在功能上与mm_struct管理进程的虚拟地址空间完全相同。drm_gpuvm中的kernel_alloc_node直接对应于进程 VA 空间中的内核保留地址范围。2.2 后备存储和放置CPU MMGPU MMTTM结构角色物理 RAMzonesVRAMTTM_PL_VRAM快速、有限的主存储交换设备系统内存TTM_PL_SYSTEM较慢、较大的溢出存储struct pagestruct ttm_resource物理分配跟踪单元页帧分配buddygpu_buddy_alloc_blocks()二的幂次方物理分配器NUMA 节点亲和性ttm_place.mem_type放置偏好层次结构TTM 放置系统包含有序struct ttm_place数组的struct ttm_placement类似于 NUMA 内存策略——表达内存应该物理驻留位置的偏好层次。2.3 交换类比这是最明确的类比TTM 直接采用了 CPU MM 的术语structttm_tt{structpage**pages;#defineTTM_TT_FLAG_SWAPPEDBIT(0)// ← CPU 交换术语structfile*swap_storage;// ← shmem 后备类似交换...};TTM 中驱逐到系统内存的路径在结构上与页面换出完全相同CPU 换出GPU 驱逐TTM通过 LRU 扫描选择受害者通过ttm_resource_manager.lru[]选择 BO将页面内容写入交换设备将 BO 内容移动到系统内存 / shmemswap_storage用交换条目替换 PTE更新ttm_resource放置设置TTM_TT_FLAG_SWAPPED释放物理页帧释放 VRAM 分配换入/故障恢复路径CPU 换入GPU 重新验证页面故障触发do_swap_page()命令提交触发drm_gpuvm_validate()从交换读取分配页帧调用ttm_bo_validate()→ 分配 VRAM复制回来安装指向新帧的 PTE更新 GPU 页表条目清除交换条目清除TTM_TT_FLAG_SWAPPED调用ttm_tt_swapin()GEM VRAM 文档明确指出“如果 VRAM 中没有更多空间不活跃的 GEM 对象可以移动到系统内存。”这句话是以下 CPU 等价表述的 GPU 版本“如果没有更多物理 RAM不活跃的页面可以移动到交换空间。”2.4 基于 LRU 的驱逐和回收两个子系统都使用 LRU最近最少使用作为主要的驱逐策略CPU MM每个内存区的活跃/不活跃 LRU 列表kswapd守护进程执行后台回收slab 缓存的 shrinker 回调lru_gen多代 LRU用于改进老化GPU MMTTM/GEMttm_resource_manager.lru[TTM_MAX_BO_PRIORITY]— 每种内存类型的优先级感知 LRU带有drm_gem_lru_scan()的drm_gem_lru— GEM 对象的 shrinker 集成ttm_pool_type.shrinker_list— TTM 页面池注册为内核 shrinkerdrm_mm_scan_init()/drm_mm_scan_add_block()— 用于连续驱逐的 LRU 扫描DRM MM 文档描述了驱逐扫描模式“使用drm_mm_scan_add_block()添加驱逐候选者直到找到合适的空洞或没有更多可驱逐的对象。”这在算法上与 CPU MM 的shrink_inactive_list()扫描候选者直到释放足够内存完全相同。2.5 按需分页和故障处理CPU MMGPU MM结构角色handle_mm_fault()GEM 故障处理器vm_operations_struct.fault按需页面/BO 填充延迟分配首次访问时分配首次使用时的ttm_tt_populate()推迟物理分配FAULT_FLAG_WRITE→ CoW写时锁定 / 访问时迁移访问类型特定处理GEM 文档指出“驱动程序负责通过为每个页面调用shmem_read_mapping_page_gfp()来实际分配物理页面。注意他们可以选择在初始化 GEM 对象时分配页面或者推迟分配直到需要内存时例如当发生页面故障时。”这是标准的按需分页移植到了 GPU 领域。2.6 Madvise 和可清除性CPU MMGPU MM结构角色madvise(MADV_DONTNEED)DRM_GEM_OBJECT_PURGEABLE/shmem.madv提示内存可以被回收madvise(MADV_WILLNEED)预取操作DRM_GPUVA_OP_PREFETCH提示内存即将被需要页面标记为干净 → 无需写回即可释放ttm_backup_flags.purge— 无需备份即可释放优化跳过写回2.7 休眠作为完全换出TTM 甚至通过将系统休眠视为完全换出来处理intttm_device_prepare_hibernation(structttm_device*bdev);// 将 GTT BO 移动到 shmem 以进行休眠这是 CPU MM 在挂起到磁盘期间将所有活跃页面写入交换的 GPU 等价操作。2.8 趋同GPU SVM 和 HMM这种类比不是静态的——它正在趋同。现代 GPU 驱动程序AMD KFD SVM、Intel Xe SVM现在实现了真正的共享虚拟内存其中GPU 和 CPU 共享相同的虚拟地址空间GPU 页面故障像 CPU 页面故障一样处理HMMhmm_range_fault()桥接了这两个世界设备私有页面MEMORY_DEVICE_PRIVATE在 CPU 页表中表现为类似交换的条目这种趋同验证了论点GPU 内存子系统一直在解决与 CPU MM 相同的问题而两者现在正通过 HMM 真正合并。3. 架构映射这里总结下整个架构中元素的对应关系。CPU MMGPU MMDRM/TTM结构角色mm_structdrm_gpuvm每进程虚拟地址空间容器vm_area_structdrm_gpuva连续 VA 区域描述符struct page/foliottm_resource/drm_gem_object物理分配跟踪单元物理 RAMVRAMTTM_PL_VRAM快速本地存储交换空间系统内存TTM_PL_SYSTEM溢出存储页表PGD→PTEGPU 页表驱动程序特定虚拟→物理地址转换Buddy 分配器drm_buddy/drm_mm范围分配器物理内存分配LRU 列表 kswapdttm_resource_manager.lru[] shrinker驱逐候选者排序与回收do_swap_page()ttm_tt_swapin()换入/重新填充路径PTE 中的交换条目TTM_TT_FLAG_SWAPPED标记内容已换出madvise(MADV_DONTNEED)DRM_GEM_OBJECT_PURGEABLE可回收提示handle_mm_fault()ttm_tt_populate()/ GEM 故障处理器按需分配/填充migrate_pages()ttm_bo_validate()在内存间移动跨存储层迁移mmu_notifierdrm_gpuvm_bo_evict()回调映射失效通知/proc/pid/mapsdebugfs GPU VA 转储地址空间调试接口OOM killer驱逐失败 →-ENOMEM资源耗尽处理4. 为什么这种类比在架构上是必然的这种趋同并非巧合。两个子系统解决的是相同的抽象问题给定一个虚拟地址空间大于其快速本地内存的处理器使用间接寻址页表、延迟分配按需分页和容量管理驱逐/交换在竞争的消费者之间复用有限的物理存储。唯一的区别是粒度CPU MM 以页面粒度4KB–2MB操作GPU MM 通常以缓冲对象粒度KB–GB操作。一致性模型CPU 具有硬件缓存一致性GPU 需要显式刷新/无效化或域转换。故障延迟容忍度CPU 页面故障会阻塞单个线程GPU “故障”驱逐重新验证在提交时批量处理尽管现代 GPU 现在支持真正的页面故障。复用单位CPU 在进程之间复用GPU 在缓冲对象之间复用尽管 GPUVM 现在提供每进程的 GPU VA 空间。5. 文档来源5.1 主要内核文档DRM 内存管理— 权威参考。TTM、GEM、GPUVM、DRM MM、Buddy 分配器都在这里有文档。包含swap_storage、LRU、shrinker 和驱逐 API。DRM GPUVM— 记录了带有驱逐跟踪、分割/合并和验证的 GPU 虚拟地址空间管理器。5.2 树内源代码自文档化文件相关类比drivers/gpu/drm/ttm/ttm_tt.cttm_tt_swapin()、ttm_tt_swapout()、swap_storagedrivers/gpu/drm/ttm/ttm_bo.cLRU 驱逐、ttm_bo_validate()drivers/gpu/drm/ttm/ttm_pool.c带 shrinker 的页面池对应 slab shrinkerdrivers/gpu/drm/drm_gpuvm.cGPU VA 空间管理、驱逐列表drivers/gpu/drm/drm_gem.cdrm_gem_lru_scan()— GEM 对象的 shrinkerinclude/drm/ttm/ttm_tt.hTTM_TT_FLAG_SWAPPED、struct ttm_tt5.3 会议演讲和文章XDCX.Org 开发者大会— Christian König 关于 TTM 重构的演讲明确讨论了内存层次结构和驱逐模型。LWN.net— 关于 DRM 内存管理、GPUVMDanilo Krummrich 的系列文章2023年和 VM_BIND 的文章使用 CPU MM 开发者熟悉的术语讨论 GPU VA 管理。“GEM - 图形执行管理器”LWN2008年— 建立 GEM 围绕 shmem 后备对象的设计理念的基础性文章。5.4 HMM 桥梁HMM异构内存管理子系统是这种类比的最终证据因为它字面上桥接了两者设备私有页面在 CPU 页表中表现为类似交换的条目hmm_range_fault()为设备内存镜像handle_mm_fault()migrate_vma_*()将migrate_pages()扩展到设备内存6. 结论Linux 中的 GPU 内存管理子系统不仅仅是与 CPU 内存管理类似——它是对物理稀缺下虚拟内存管理这一根本问题的趋同重新推导。证据如下词汇层面TTM 使用 CPU MM 术语swap、swapin、populate、evict、LRU、shrinker。结构层面drm_gpuvm/drm_gpuva在角色和实现上镜像mm_struct/vm_area_struct。算法层面基于 LRU 的驱逐扫描、按需填充和 shrinker 集成遵循相同的模式。演化层面两个子系统正通过 HMM/SVM 积极趋同GPU 驱动程序现在直接参与 CPU MM 的页面故障和迁移基础设施。对于内核开发者来说理解 CPU MM 为理解 GPU 内存管理提供了直接的概念框架——反之亦然。DRM 子系统的内存管理最好被理解为不是一种新颖的设计而是应用于不同类型处理器的经典虚拟内存理论。实际上这也给理解TTM的设计提供了一个视角可以从这个视角再去理解下第四章的TTM分析。参考文献Linux 内核文档DRM 内存管理Linux 内核源码include/drm/ttm/ttm_tt.hLinux 内核源码drivers/gpu/drm/ttm/ttm_tt.cLinux 内核源码drivers/gpu/drm/drm_gpuvm.cKrummrich, D. “DRM GPUVM” — 内核补丁和文档2023年Corbet, J. “GEM - 图形执行管理器” — LWN.net2008年Linux 内核文档异构内存管理HMM
返回列表