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模式的核心目标是:在指定的base和limit区间内,预留一块足够大的、连续的虚拟地址空间,供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 链表管理,支持动态分配和释放。

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

  • 释放时要保留区间。

相关推荐
一条破秋裤12 小时前
【1114】【并发控制】【笔记】
linux
2035去旅行13 小时前
ADB的底层原理
linux·adb·嵌入式·arm·soc
武子康13 小时前
单卡 A6000 跑 Qwen-Drive:怎样留下可比较的第一条基线?
linux·人工智能·深度学习
女神下凡13 小时前
芯参谋(107):杰理AC_中科蓝讯_开发指南
linux·服务器·网络·单片机·嵌入式硬件
落羽的落羽13 小时前
【C++】C++17的主要特性
linux·服务器·开发语言·c++·算法·机器学习
爱和冰阔落18 小时前
【Linux网络】TCP 半包粘包怎么解决?从长度报头、JSON 拆包到网络计算器完整实战
linux·运维·网络·tcp/ip
say_fall20 小时前
【Linux网络编程】UDP套接字编程:系统编程组件、基础回显服务、InetAddr与地址转换、翻译服务与线程池聊天室
linux·服务器·网络·udp·vr
ö Constancy20 小时前
一台电脑的硬件组成与作用:按功能分类详解(Windows 与 Linux 视角)
linux·windows·电脑
江湖有缘20 小时前
基于Ubuntu部署SoduWork:企业级 AI 原生协同平台实战全流程
linux·人工智能·ubuntu·ai·soduwork
无奈笑天下1 天前
银河麒麟上nproc命令教程详解
linux·运维·服务器