附录A:AMDGPU SVM 属性类型

概述

kfd_ioctl_svm_attr_type 枚举定义了 SVM(Shared Virtual Memory)的所有属性类型,用于控制 GPU 对共享虚拟内存的访问行为、数据位置偏好、以及一致性模式。

c 复制代码
enum kfd_ioctl_svm_attr_type {
    KFD_IOCTL_SVM_ATTR_PREFERRED_LOC,    // 首选位置
    KFD_IOCTL_SVM_ATTR_PREFETCH_LOC,     // 预取位置(触发迁移)
    KFD_IOCTL_SVM_ATTR_ACCESS,           // GPU 访问权限(可迁移)
    KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE,  // GPU 访问权限(不迁移)
    KFD_IOCTL_SVM_ATTR_NO_ACCESS,        // 移除 GPU 访问权限
    KFD_IOCTL_SVM_ATTR_SET_FLAGS,        // 设置标志位
    KFD_IOCTL_SVM_ATTR_CLR_FLAGS,        // 清除标志位
    KFD_IOCTL_SVM_ATTR_GRANULARITY       // 迁移粒度
};

1. KFD_IOCTL_SVM_ATTR_PREFERRED_LOC

1.1 功能

设置内存的首选位置(preferred location),决定数据在空闲时应该驻留的位置。

1.2 Value 取值

含义
0 (KFD_IOCTL_SVM_LOCATION_SYSMEM) 系统内存(CPU)
GPU_ID 特定 GPU 的显存
0xffffffff (UNDEFINED) 未定义,由系统决定

1.3 内核处理

c 复制代码
case KFD_IOCTL_SVM_ATTR_PREFERRED_LOC:
    prange->preferred_loc = attrs[i].value;
    break;

1.4 作用

  • 当 GPU 发生 page fault 时,svm_range_best_restore_location() 会优先考虑 preferred_loc
  • 如果 preferred_loc 是一个 GPU,且该 GPU 可以访问,数据会迁移到该 GPU
  • 影响 page fault 恢复时的数据放置策略

1.5 使用示例

c 复制代码
// 设置首选位置为 GPU 0
attrs[0].type = KFD_IOCTL_SVM_ATTR_PREFERRED_LOC;
attrs[0].value = gpu_id_0;

2. KFD_IOCTL_SVM_ATTR_PREFETCH_LOC

2.1 功能

设置预取位置立即触发数据迁移

2.2 Value 取值

与 PREFERRED_LOC 相同。

2.3 内核处理

c 复制代码
case KFD_IOCTL_SVM_ATTR_PREFETCH_LOC:
    prange->prefetch_loc = attrs[i].value;
    break;

svm_range_set_attr() 中,设置 prefetch_loc 后会触发:

c 复制代码
r = svm_range_trigger_migration(mm, prange, &migrated);

2.4 与 PREFERRED_LOC 的区别

属性 行为
PREFERRED_LOC 设置偏好,不立即迁移,等 page fault 时生效
PREFETCH_LOC 设置位置并立即迁移数据

2.5 使用场景

  • 在 GPU 计算前,预先将数据迁移到目标 GPU 显存
  • 避免运行时 page fault 导致的性能抖动

2.6 使用示例

c 复制代码
// 立即将数据迁移到 GPU 0
attrs[0].type = KFD_IOCTL_SVM_ATTR_PREFETCH_LOC;
attrs[0].value = gpu_id_0;

3. KFD_IOCTL_SVM_ATTR_ACCESS

3.1 功能

授予指定 GPU 对内存的访问权限 ,数据可以被迁移到该 GPU。

3.2 Value 取值

GPU ID(指定哪个 GPU 获得访问权限)。

3.3 内核处理

c 复制代码
case KFD_IOCTL_SVM_ATTR_ACCESS:
    gpuidx = kfd_process_gpuidx_from_gpuid(p, attrs[i].value);
    bitmap_set(prange->bitmap_access, gpuidx, 1);    // 设置访问位
    bitmap_clear(prange->bitmap_aip, gpuidx, 1);     // 清除 in-place 位
    break;

3.4 作用

  • 设置 bitmap_access 位图中对应 GPU 的位
  • 当 GPU 访问该内存时,数据可能被迁移到该 GPU 的显存
  • page fault 恢复时,svm_range_best_restore_location() 检查此位图

3.5 迁移行为

复制代码
GPU 访问 → Page Fault → 检查 bitmap_access
                            ↓
                     如果 GPU 在 bitmap_access 中
                            ↓
                     数据可迁移到该 GPU 显存

4. KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE

4.1 功能

授予指定 GPU 对内存的访问权限 ,但数据保持原地不迁移

4.2 Value 取值

GPU ID。

4.3 内核处理

c 复制代码
case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE:
    gpuidx = kfd_process_gpuidx_from_gpuid(p, attrs[i].value);
    bitmap_clear(prange->bitmap_access, gpuidx, 1);  // 清除访问位
    bitmap_set(prange->bitmap_aip, gpuidx, 1);       // 设置 in-place 位
    break;

4.4 与 ACCESS 的区别

属性 bitmap_access bitmap_aip 数据迁移
ACCESS ✅ 设置 ❌ 清除 可迁移到 GPU
ACCESS_IN_PLACE ❌ 清除 ✅ 设置 不迁移,远程访问

4.5 适用场景

  • 多 GPU 共享访问同一内存
  • 避免数据在 GPU 间来回迁移(ping-pong)
  • CPU 内存被多个 GPU 远程访问

4.6 性能考虑

复制代码
ACCESS:          数据迁移到 GPU 显存,带宽高,延迟低
ACCESS_IN_PLACE: 远程访问(PCIe/XGMI),带宽受限,但避免迁移开销

5. KFD_IOCTL_SVM_ATTR_NO_ACCESS

5.1 功能

移除指定 GPU 对内存的访问权限。

5.2 Value 取值

GPU ID。

5.3 内核处理

c 复制代码
case KFD_IOCTL_SVM_ATTR_NO_ACCESS:
    gpuidx = kfd_process_gpuidx_from_gpuid(p, attrs[i].value);
    bitmap_clear(prange->bitmap_access, gpuidx, 1);  // 清除访问位
    bitmap_clear(prange->bitmap_aip, gpuidx, 1);     // 清除 in-place 位
    break;

5.4 作用

  • 同时清除 bitmap_accessbitmap_aip
  • GPU 尝试访问时会触发 page fault,且无法恢复(返回 -EACCES)

5.5 使用场景

  • 安全性:限制特定 GPU 访问敏感数据
  • 资源管理:在 GPU 不再需要访问时释放权限

6. KFD_IOCTL_SVM_ATTR_SET_FLAGS

6.1 功能

设置(OR)指定的标志位。

6.2 Value 取值

标志位掩码,可以是以下值的组合:

标志 说明
KFD_IOCTL_SVM_FLAG_HOST_ACCESS 0x01 保证 CPU 可访问
KFD_IOCTL_SVM_FLAG_COHERENT 0x02 细粒度一致性
KFD_IOCTL_SVM_FLAG_HIVE_LOCAL 0x04 使用同 hive 的任意 GPU
KFD_IOCTL_SVM_FLAG_GPU_RO 0x08 GPU 只读,允许复制
KFD_IOCTL_SVM_FLAG_GPU_EXEC 0x10 允许 GPU 执行
KFD_IOCTL_SVM_FLAG_GPU_READ_MOSTLY 0x20 GPU 主要读取
KFD_IOCTL_SVM_FLAG_GPU_ALWAYS_MAPPED 0x40 保持 GPU 映射始终有效
KFD_IOCTL_SVM_FLAG_EXT_COHERENT 0x80 扩展一致性(device-scope atomics)

6.3 内核处理

c 复制代码
case KFD_IOCTL_SVM_ATTR_SET_FLAGS:
    *update_mapping = true;
    prange->flags |= attrs[i].value;  // OR 操作
    break;

6.4 标志详解

FLAG_COHERENT (0x02)
  • 启用细粒度一致性
  • CPU 和 GPU 看到一致的内存视图
  • 性能开销较高
FLAG_EXT_COHERENT (0x80)
  • 扩展一致性,使用 device-scope atomics
  • 比 COHERENT 更强的一致性保证
  • 用于跨设备原子操作
FLAG_GPU_ALWAYS_MAPPED (0x40)
  • 即使 XNACK 开启,也保持 GPU 页表映射有效
  • 避免 page fault 开销
  • 类似于 XNACK 关闭的行为
FLAG_GPU_RO (0x08)
  • GPU 只读访问
  • 允许数据复制到多个 GPU(replication)
  • 优化多 GPU 读取同一数据的场景

7. KFD_IOCTL_SVM_ATTR_CLR_FLAGS

7.1 功能

清除(AND NOT)指定的标志位。

7.2 Value 取值

与 SET_FLAGS 相同的标志位掩码。

7.3 内核处理

c 复制代码
case KFD_IOCTL_SVM_ATTR_CLR_FLAGS:
    *update_mapping = true;
    prange->flags &= ~attrs[i].value;  // AND NOT 操作
    break;

7.4 使用示例

c 复制代码
// 设置细粒度一致性
attrs[0].type = KFD_IOCTL_SVM_ATTR_SET_FLAGS;
attrs[0].value = KFD_IOCTL_SVM_FLAG_COHERENT;

// 清除细粒度一致性(改为粗粒度)
attrs[0].type = KFD_IOCTL_SVM_ATTR_CLR_FLAGS;
attrs[0].value = KFD_IOCTL_SVM_FLAG_COHERENT;

8. KFD_IOCTL_SVM_ATTR_GRANULARITY

8.1 功能

设置迁移粒度,控制 page fault 时迁移的内存块大小。

8.2 Value 取值

log2(页数),范围 0-63(实际限制为 0x3F)。

Value 迁移大小
0 1 页 = 4KB
1 2 页 = 8KB
4 16 页 = 64KB
9 512 页 = 2MB

8.3 内核处理

c 复制代码
case KFD_IOCTL_SVM_ATTR_GRANULARITY:
    prange->granularity = min_t(uint32_t, attrs[i].value, 0x3F);
    break;

8.4 作用

在 page fault 处理中:

c 复制代码
size = 1UL << prange->granularity;
start = ALIGN_DOWN(addr, size);
last = ALIGN(addr + 1, size) - 1;

8.5 权衡

粒度 优点 缺点
精确,避免不必要迁移 频繁 fault,开销大
减少 fault 次数,预取效果好 可能迁移不需要的数据

9. 属性总结表

属性类型 存储位置 作用 触发迁移
PREFERRED_LOC prange->preferred_loc 设置首选位置 ❌ 延迟
PREFETCH_LOC prange->prefetch_loc 设置位置并迁移 ✅ 立即
ACCESS prange->bitmap_access 授权 GPU 访问,可迁移 按需
ACCESS_IN_PLACE prange->bitmap_aip 授权 GPU 访问,不迁移
NO_ACCESS 清除两个 bitmap 移除 GPU 访问权限 N/A
SET_FLAGS prange->flags 设置标志 N/A
CLR_FLAGS prange->flags 清除标志 N/A
GRANULARITY prange->granularity 迁移粒度 N/A

10. 典型使用场景

10.1 单 GPU 计算

c 复制代码
// 1. 设置首选位置为 GPU
attrs[0].type = KFD_IOCTL_SVM_ATTR_PREFERRED_LOC;
attrs[0].value = gpu_id;

// 2. 授权 GPU 访问
attrs[1].type = KFD_IOCTL_SVM_ATTR_ACCESS;
attrs[1].value = gpu_id;

// 3. 预取数据到 GPU
attrs[2].type = KFD_IOCTL_SVM_ATTR_PREFETCH_LOC;
attrs[2].value = gpu_id;

10.2 多 GPU 共享读取

c 复制代码
// 所有 GPU 就地访问,数据保持在 CPU
for (int i = 0; i < num_gpus; i++) {
    attrs[i].type = KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE;
    attrs[i].value = gpu_ids[i];
}

10.3 细粒度一致性

c 复制代码
// 设置细粒度一致性
attrs[0].type = KFD_IOCTL_SVM_ATTR_SET_FLAGS;
attrs[0].value = KFD_IOCTL_SVM_FLAG_COHERENT;
相关推荐
DeeplyMind8 小时前
04 - SVM核心数据结构详解
svm·amdgpu·kfd
DeeplyMind2 天前
02 - SVM相关的Linux内核基础
hmm·rocm·kfd·共享虚拟内存·amdgpu svm
DeeplyMind3 天前
01 - 什么是SVM
svm·amdgpu·rocm·kfd
DeeplyMind7 天前
AMD ROCm-SVM技术的实现与应用深度分析目录
svm·rocm·kfd
DeeplyMind24 天前
AMD KFD的BO设计分析系列8-7:TLB管理与刷新
amdgpu·tlb·kfd
DeeplyMind1 个月前
AMD KFD的BO设计分析系列7-2:GPU GART 实现深度解析--绑定机制与性能优化
驱动开发·amdgpu·kfd·gart
DeeplyMind2 个月前
AMD rocr-libhsakmt分析系列3-1: Apertures
linux·amdgpu·rocm·kfd·rocr
DeeplyMind2 个月前
AMD rocr-libhsakmt分析系列6-2:共享机制-import
linux·amdgpu·dma-buf·rocm·kfd·rocr
DeeplyMind3 个月前
linux drm子系统专栏介绍
linux·驱动开发·ai·drm·amdgpu·kfd