AMD KFD的BO设计分析系列1-1:Buffer Object概览

本文简要描述了amdgpu bo的类型和用途,以及map、共享、同步等功能,看多了本专栏的文章,就会发现图形/计算的存储管理涉及存储子系统的方方面面,需久久为功是—— 唯有坚持技术深耕、实践复盘,才能在开发的产品中提升性能、保障稳定、达成预期。

1. amd bo类型和用途

AMDGPU 支持多种类型的 BO,分别服务于不同的使用场景:

  • 用户空间 BO:通过 GEM/DRM ioctl 由应用程序分配,用于图形渲染、OpenCL/Vulkan 计算、ROCm训练/推理等。

  • 内核空间 BO:驱动内部分配,用于 ring buffer、firmware、调度队列等,用户空间不可直接访问。

  • VM BO:专用于 GPU 虚拟内存页表管理。

  • ISP 用户 BO:用于 ISP(图像信号处理)等外部设备的 DMA-BUF 导入。

每种 BO 类型在分配、映射、销毁等环节有不同的参数和生命周期管理策略。这个是从使用场景分类BO类型,还有一个视角是:bo所在的物理空间的区域(内存分配位置)。内存分配位置视角更有技术研究价值,请参见:AMD KFD BO设计分析系列10:内存分配位置flags详解

2. BO 的创建与分配流程

2.1 用户空间 BO 创建

用户空间通过 ioctl(如 DRM_IOCTL_AMDGPU_GEM_CREATE)请求分配 BO,驱动调用 amdgpu_bo_create_user

int amdgpu_bo_create_user(struct amdgpu_device *adev,
              struct amdgpu_bo_param *bp,
              struct amdgpu_bo_user **ubo_ptr)
{
    bp->bo_ptr_size = sizeof(struct amdgpu_bo_user);
    bp->destroy = &amdgpu_bo_user_destroy;
    r = amdgpu_bo_create(adev, bp, &bo_ptr);
    *ubo_ptr = to_amdgpu_bo_user(bo_ptr);
    return r;
}
  • 用途:为用户空间应用(如 OpenCL、Vulkan、图形程序、AI)分配 BO,用户可通过 GEM/DRM ioctl 访问和管理这些 BO。

  • 参数:需要 amdgpu_bo_param,并指定 bo_ptr_size 为 sizeof(struct amdgpu_bo_user),destroy 回调为 amdgpu_bo_user_destroy

  • 实现:调用 amdgpu_bo_create 创建 BO,并返回 struct amdgpu_bo_user *

  • 特性
    • 支持元数据(metadata)、tiling flags 等用户空间属性。

    • 生命周期由用户空间控制,通常与 GEM handle 绑定。

    • 适合图形渲染、用户侧显存分配等场景。

2.2 内核空间 BO 创建

内核通过 amdgpu_bo_create_kernel 分配 BO,供驱动内部使用:

int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
                unsigned long size, int align,
                u32 domain, struct amdgpu_bo **bo_ptr,
                u64 *gpu_addr, void **cpu_addr)
{
    r = amdgpu_bo_create_reserved(adev, size, align, domain, bo_ptr,
                      gpu_addr, cpu_addr);
    if (*bo_ptr)
        amdgpu_bo_unreserve(*bo_ptr);
    return r;
}
  • 用途:为内核驱动自身分配 BO,供驱动内部使用(如 ring buffer、firmware、内核任务等),用户空间不可直接访问。

  • 参数:直接传递 BO 指针,destroy 回调为 amdgpu_bo_destroy,类型为 ttm_bo_type_kernel

  • 实现:调用 amdgpu_bo_create_reserved 创建并 pin 住 BO,随后 unreserve,返回 struct amdgpu_bo *

  • 特性

    • 通常分配 VRAM 或 GTT,支持内核直接映射(可选)。

    • 生命周期由内核管理,适合 GPU 驱动内部资源。

    • 可选返回 GPU 地址和 CPU 映射地址。

2.3 VM BO 创建

用于 GPU 虚拟内存页表管理:

  • 通常分配 VRAM,支持页表层级结构。

int amdgpu_bo_create_vm(struct amdgpu_device *adev,
            struct amdgpu_bo_param *bp,
            struct amdgpu_bo_vm **vmbo_ptr)
{
    r = amdgpu_bo_create(adev, bp, &bo_ptr);
    *vmbo_ptr = to_amdgpu_bo_vm(bo_ptr);
    return r;
}

2.4 ISP 用户 BO 创建

用于 ISP 设备的 DMA-BUF 导入:

int amdgpu_bo_create_isp_user(struct amdgpu_device *adev,
               struct dma_buf *dma_buf, u32 domain, struct amdgpu_bo **bo,
               u64 *gpu_addr)
{
    gem_obj = amdgpu_gem_prime_import(&adev->ddev, dma_buf);
    *bo = gem_to_amdgpu_bo(gem_obj);
    amdgpu_bo_reserve(*bo, false);
    amdgpu_bo_pin(*bo, domain);
    amdgpu_ttm_alloc_gart(&(*bo)->tbo);
    *gpu_addr = amdgpu_bo_gpu_offset(*bo);
    amdgpu_bo_unreserve(*bo);
    return 0;
}

3. BO 的内存分配与域管理

BO 支持多种内存域(domain),如 VRAM、GTT、CPU、DOORBELL、GDS、GWS、OA 等。分配时通过 amdgpu_bo_placement_from_domain 设置 BO 的物理位置和属性:

void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
{
    // 根据 domain 设置 TTM placement 和 flags
}
  • VRAM:GPU 专用显存,适合高带宽任务。

  • GTT:系统内存,通过 IOMMU 映射到 GPU。

  • DOORBELL:队列通知机制专用内存。

  • GDS/GWS/OA:特殊硬件资源。

4. BO 的映射与访问

4.1 GPU 地址映射

BO 分配后可通过 amdgpu_bo_gpu_offset 获取其在 GPU 地址空间的偏移,用于命令提交和显存访问。

4.2 CPU 地址映射

内核可通过 amdgpu_bo_kmap 映射 BO 到内核虚拟地址,实现 CPU 直接访问:

int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)
{
    // 调用 ttm_bo_kmap 设置内核虚拟映射
}
  • 受 BO flags 控制,部分 BO 不允许 CPU 访问。

4.3 用户空间 mmap

用户空间可通过 mmap ioctl 映射 BO,实现显存直接访问,底层通过 DRM/GEM 和 TTM 管理页表和权限。

5. BO 的生命周期与同步机制

1. Pin/Unpin: BO 可通过 amdgpu_bo_pin 固定在物理内存,防止被驱逐或移动,适合帧缓冲等关键资源。

2. Fence 与同步:BO 支持 fence 机制,通过 amdgpu_bo_fence 关联 DMA fence,确保命令提交和内存访问的正确顺序。

3. 驱逐与回收: 当显存紧张或 BO 失效时,驱动可通过状态链表和锁机制驱逐 BO,释放资源。

4.bo共享:bo支持通过 DMA-BUF fd 导入导出,实现多进程、多设备间的显存共享。驱动通过 drm_gem_prime_import 和相关接口管理生命周期和映射关系。

5. 销毁与释放:BO 销毁时,调用 destroy 回调(如 amdgpu_bo_destroy 或 amdgpu_bo_user_destroy),释放所有资源并解除映射。

6. 总结对比

这里对user和kernel bo做了对比。

项目amdgpu_bo_create_useramdgpu_bo_create_kernel
用途用户空间 BO内核空间 BO
返回类型struct amdgpu_bo_user *struct amdgpu_bo *
生命周期用户空间控制(GEM handle)内核控制
destroy 回调amdgpu_bo_user_destroyamdgpu_bo_destroy
典型场景图形渲染、用户显存、AIring buffer、firmware、内核任务
是否 pin/保留通常不自动 pin自动 pin 并可选 CPU 映射
是否支持元数据/tiling flags支持通常不支持

一句话总结:amdgpu_bo_create_user 用于分配用户空间可管理的 BO,amdgpu_bo_create_kernel 用于分配内核驱动内部使用的 BO,二者在生命周期、访问权限和分配方式上有本质区别。


技术交流,欢迎加入社区:GPUers

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeeplyMind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值