AMD rocr-libhsakmt分析系列3-4:svm-reserve模式实现分析

1. 背景与原理

在AMD ROCm平台的内存管理中,SVM(Shared Virtual Memory)允许CPU和GPU共享统一的虚拟地址空间。init_svm_apertures函数负责初始化SVM地址空间(aperture),以便后续的内存分配和映射操作。该函数支持两种模式:

  • mmap模式:直接利用操作系统的虚拟地址分配能力,适用于GFXv9及以上架构,虚拟地址空间充足。

  • reserve模式 :在指定区间内预留一块连续的虚拟地址空间,适用于旧架构或特殊需求(如环境变量HSA_RESERVE_SVM启用)。

本文重点分析reserve模式的实现原理和具体流程。

2. 实现原理与应用场景

2.1 实现原理

Reserve模式的核心目标是:在指定的baselimit区间内,预留一块足够大的、连续的虚拟地址空间,供SVM使用。

  • 预留空间的大小优先为整个区间,若无法分配则逐步减半,直到满足最小要求(4GB)。

  • 预留空间必须对齐到GPU的Huge Page Size,保证性能和兼容性。

  • 预留空间的至少一半必须在GPU可寻址范围内,确保GPU能够访问大部分分配的SVM空间。

预留空间的实现很简单,就是mmap。当计算出起始地址和大小后,就可以申请了,关键实现函数如下:

cpp 复制代码
static void *reserve_address(void *addr, unsigned long long int len)
{
	void *ret_addr;

	if (len <= 0)
		return NULL;
    
    //匿名映射,请关注映射参数
	ret_addr = mmap(addr, len, PROT_NONE,
				 MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE, -1, 0);
	if (ret_addr == MAP_FAILED)
		return NULL;

	return ret_addr;
}

2.2 适用场景

  • 兼容性强:适用于虚拟地址空间有限或驱动/硬件不支持mmap模式的场景。

  • 可控性高:通过环境变量可强制启用reserve模式,便于调试和特殊需求。

  • 性能保障:Huge Page对齐和空间预留减少碎片,提高访问效率。

3. bo的svm地址分配与释放

reserve SVM 区域作为统一的虚拟地址池,所有分配和映射都在该区域内完成。在reserve SVM地址区间内申请memory,配套的申请和释放函数是reserved_aperture_allocate_aligned和reserved_aperture_release。原理与drm_mm的管理地址空间类似。使用list维护分配区间的元数据。

3.1 申请函数实现流程

1. 对齐处理

  • 如果请求的对齐小于 aperture 的默认对齐,则提升到默认对齐。

  • 对于大块分配,自动提升对齐到更高的2的幂(最多到 GPU_HUGE_PAGE_SIZE),以优化TLB性能。

  • 如果没有指定对齐(或对齐小于等于PAGE_SIZE),则采用"尾部对齐"策略:通过 offset 变量将分配区间尾部对齐到目标对齐边界,解决部分旧GPU的TLB问题。

2 分配区间扩展

  • 分配区间大小会加上 guard pages(保护页),防止越界访问。

3. 查找空闲区间

  • 遍历 aperture 的 vm_ranges 链表,查找足够大的"洞"。

  • 如果指定了 address,则从该地址开始查找,否则从 aperture base 开始按对齐递增查找。

  • 如果找到的空闲区间足够大,则分配;否则继续查找下一个区间。

4. 分配区间插入

  • 如果分配区间正好与前一个已分配区间相邻,则扩展该区间。

  • 否则,创建新的 vm_area_t 节点插入到链表中,维护分配区间元数据。

5 返回分配结果

3.2 释放函数的实现流程

  1. 区间对齐处理

    首先将释放的大小加上 guard pages(保护页),确保释放区间与分配时一致。

  2. 查找对应区间

    通过 vm_find 在 aperture 的 vm_ranges 链表中查找包含该地址的区间(vm_area_t)。

  3. 区间释放与调整

    • 如果释放区间正好等于整个已分配区间,则直接移除该区间节点(vm_remove_area)。

    • 如果释放区间是已分配区间的一部分,则根据释放位置(区间头、区间尾或中间)调整区间边界或拆分区间(vm_split_area)。

  4. 物理内存和 NUMA 策略处理

    • 如果 aperture 支持 CPU 访问(is_cpu_accessible),则重置 NUMA 策略(mbind),并用 mmap(PROT_NONE) 重新映射释放区间,保持地址空间预留但不可访问。

    • 如果 mmap 失败且 errno == ENOMEM,则先 munmap 再尝试 mmap,确保释放成功。

3.3 关键点

  • 所有分配和释放都在 aperture 的 fmm_mutex 保护下,保证线程安全。

  • 分配区间通过 vm_area_t 链表管理,支持动态分配和释放。

  • 对齐和保护页策略保证了分配区间的性能和安全性。

  • 释放时要保留区间。

相关推荐
MATLAB代码顾问3 小时前
MATLAB 实现图像边缘检测与轮廓提取(Canny、Sobel、Prewitt 算子对比)
1024程序员节
神秘的土鸡3 小时前
从数据仓库到数据中台再到数据飞轮:我的数据技术成长之路
java·服务器·aigc·数据库架构·1024程序员节
烦恼归林3 小时前
学习经验分享篇(4)——硕士入门电机控制的经历经验分享
经验分享·电机·电力电子·1024程序员节·电机控制·永磁同步电机·simulink仿真
sponge'3 小时前
opencv学习笔记6:SVM分类器
人工智能·机器学习·支持向量机·1024程序员节
allnlei3 小时前
使用CLion进行远程开发(Remote Development)
ide·1024程序员节
Jeled3 小时前
「高级 Android 架构师成长路线」的第 1 阶段 —— 强化体系与架构思维(Clean Architecture 实战)
android·kotlin·android studio·1024程序员节
vir023 小时前
P1928 外星密码(dfs)
java·数据结构·算法·深度优先·1024程序员节
旋转小马3 小时前
XGBoost完整学习指南:从数据清洗到模型调参
机器学习·scikit-learn·xgboost·1024程序员节
大米粥哥哥3 小时前
Qt QProcess基于Linux的命令管道符号无效问题【已解决】
linux·qt·shell·qprocess·1024程序员节·管道符号