openEuler 23.09 白皮书
https://www.openeuler.org/whitepaper/openEuler%2023.09%20%E6%8A%80%E6%9C%AF%E7%99%BD%E7%9A%AE%E4%B9%A6.pdf 异构通用内存管理框架(GMEM)特性
1> 背景和问题
在后摩尔时代,GPU、TPU 和 FPGA 等专用异构加速器设备正不断涌现,它们与 CPU 类似,需要将数据放在本地内存(例 如 LPDDR 或 HBM)中以提高计算速度。加速器厂商们也不可避免地需要开发复杂的内存管理系统。
现行加速器内存管理方案存在诸多缺陷:
• CPU 侧内存管理与加速器侧分离,数据显式搬移,加速器内存管理的易用性和性能难以平衡。
• 大模型场景下加速器设备 HBM 内存(Hign BandWidth Memory)严重不足,现有的手动 swap 方案性能损耗大且 通用性差。
• 搜推、大数据场景存在大量无效数据搬移,缺少高效内存池化方案。
1
2
3
4
5
6
7
HMM设计初衷:
设备有大量的板载内存,历来都是专有驱动的API管理,使得驱动程序的内存使用与常规应用内存使用断开,存在分裂。
1、大型程序需要依赖大量的库,使得程序维护复杂
2、复杂数据,例如:复杂数据集(列表、树……),在驱动与应用之间copy的话,由于重复的数据集和地址,这很容易出错并且程序更难调试。
3、由于各种内存副本,大型项目会受到这种影响并浪费资源。
复制每个库 API 以接受由每个设备特定分配器分配的输入或输出内存不是一个可行的选择。这将导致库入口点的组合爆炸。
随着高级语言结构(在 C++ 中,但在其他语言中)的进步,编译器现在可以在没有程序员知识的情况下利用 GPU 和其他设备。某些编译器识别的模式仅适用于共享地址空间。对所有其他模式使用共享地址空间也更合理。
Linux 现有的 HMM 框架,编程复杂度高且依赖人工调优,性能和可移植性差,引发OS社区反弹,最终导致HMM方案搁浅。异构加速器领域亟需高效的统一内存管理机制。
1
2
https://gitee.com/openeuler/docs/blob/master/docs/zh/docs/GMEM/%E8%AE%A4%E8%AF%86GMEM.md //gitee上介绍
https://gmem.tech/ //首页
3> 解决方案
1> HMM 异构内存管理
共享地址空间及迁移
Hmm提供两个功能:
1、统一虚拟地址空间:通过复制设备页表中的 CPU 页表来共享地址空间,因此对于进程地址空间中的任何有效主内存地址,相同的地址指向相同的物理内存;
2、ZONE_DEVICE 内存:它允许为设备内存的每个页面分配一个结构页面,管理设备内存。
地址空间镜像
1、页表同步:mmu_interval_notifier_insert
2、设备驱动程序想要填充一个虚拟地址范围:hmm_range_fault
内存迁移
由于 CPU 无法直接访问设备内存,因此设备驱动程序必须使用硬件 DMA 或设备特定的加载/存储指令来迁移数据。migrate_vma_setup()、migrate_vma_pages() 和 migrate_vma_finalize() 函数旨在使驱动程序更易于编写并集中跨驱动程序的通用代码。
简单来说:HMM提供一堆驱动上层API,异构设备根据规定的API进行实现,接入HMM的机制比较复杂。
2> OpenEuler GMEM 统一内存管理
内存管理划分:
1> 虚拟地址分配(与硬件无关)
2> 物理映射创建(与硬件强相关)
3> 物理地址分配(与硬件无关)
基本思想:
将硬件无关抽离出来作为统一框架,与硬件相关的MMU操作、物理地址范围由驱动注册、pagefault触发机制;
可以达成的目的:
1> 节省各家异构设备的重复代码开发,减少驱动开发工作量
2> 向用户程序提供统一的内存使用接口, 用户态可以提供统一的编程接口
逻辑映射系统:为了屏蔽异构设备MMU的物理映射差异, 新增逻辑映射层(记录虚拟地址所映射的物理地址,是HOST内存,也可能是某个设备上的物理地址)。 在没有逻辑映射之前,内核通过虚拟地址查找物理地址,都只能通过walk pagetable, 与硬件强相关,而且性能极差。
GMEM 建立了一套新的逻辑页表去维护这个统一虚拟地址空间,通过利用逻辑页表的信息,可以维护不同处理器、不同微架构间多份页表的一致性。基于逻辑页表的访存一致性机制,内存访问时,通过内核缺页流程即可将待访问内存在主机与加速器进行搬移。
页表协同: mmu映射/接映射, tlb失效等硬件相关操作。
并发缺页, 内存超分 – 优化项
GMEM API: 向用户层提供统一的申请接口 mmap/hmadivse。
基于GMEM框架,其中与硬件无关的的优化项, 内核优化(并发缺页, 内存超分)、用户态优化(统一虚拟地址空间, 应用prefetch优化,内存分配优化)可以快速扩展到不同的异构设备上。