第六章:异步访问的同步:6.4 显式同步

1. 引言:显式同步的兴起

1.1 为什么需要显式同步

传统的隐式同步虽然简化了应用开发,但在现代图形应用中暴露出明显的局限:

性能问题

  • 驱动无法知晓应用的真实意图,只能保守地插入同步点
  • 过度同步导致GPU流水线停顿
  • 难以实现细粒度的并行优化

延迟问题

  • VR应用需要严格控制每一帧的时序
  • 关键路径上的隐式等待增加不可预测的延迟

灵活性问题

  • 应用无法表达复杂的依赖关系(如多GPU渲染)
  • 无法跨进程高效传递同步信息
  • 难以与专用硬件(如视频编码器)协同

显式同步(Explicit Synchronization)应运而生,将同步点的控制权交还给应用。

1.2 显式 vs 隐式对比

维度显式同步隐式同步
同步点管理应用显式创建和传递驱动自动管理
fence可见性用户态可见(fd/handle)仅驱动可见
API支持Vulkan、Metal、DX12OpenGL、X11
性能可精细优化保守,易过度同步
复杂度高,易出错低,自动化
跨进程高效(传递fd)通过dma-buf间接
典型对象sync_file、drm_syncobjdma_resv

1.3 Linux中的显式同步对象

Linux内核提供两种主要的显式同步对象:sync_file和drm_syncobj。

2. sync_file

sync_file是Linux内核中用于显式同步的核心机制之一,最初由Android引入用于解决图形系统中的同步问题,后来被合并进主线内核。它提供了一种基于文件描述符的轻量级同步原语,允许用户空间显式地管理GPU工作的依赖关系。

2.1 核心结构

struct sync_file {
    struct file *file;  // 关联的文件对象
    char user_name[32]; // 用户指定的名称
    
    wait_queue_head_t wq; // 等待队列
    unsigned long flags; // 标志位(如POLL_ENABLED)
    
    struct dma_fence *fence; // 封装的dma_fence
    struct dma_fence_cb cb; // fence完成时的回调
};

设计要点

  1. 文件抽象:利用Linux文件系统基础设施,自动引用计数(通过struct file),poll/select支持(通过wait_queue)以及跨进程传递(通过fd);

  2. 单一fence:每个sync_file封装一个fence,可能是单个fence,也可能是fence_array(合并多个fence);

  3. 只读语义:创建后fence不可变,这章设计简化了生命周期管理,避免竞态条件。

3. drm_syncobj

drm_syncobj是DRM子系统中用于显式同步的核心机制,最初为实现Vulkan的fence和semaphore而设计。与一次性的sync_file不同,drm_syncobj提供了可更新、可重置的同步原语,并支持复杂的时间线语义。

3.1 核心结构

struct drm_syncobj {
    struct kref refcount;               // 引用计数
    struct dma_fence __rcu *fence;      // RCU保护的fence指针
    struct list_head cb_list;           // fence更新时的回调列表
    struct list_head ev_fd_list;        // eventfd通知列表
    spinlock_t lock;                    // 保护cb_list和fence
    struct file *file;                  // 关联的文件对象
};

设计要点

  • 可重用性:同一个syncobj可以在多次GPU提交中重复使用
  • 时间线支持:通过fence_chain实现类似Vulkan timeline semaphore的功能
  • 灵活更新:支持替换、重置、信号等多种操作
  • 跨进程共享:通过DRM handle或fd机制在进程间传递
  • 高效等待:支持主机端等待、eventfd通知等多种机制

4. sync_file与drm_syncobj 的区别

特性sync_filedrm_syncobj
创建方式从fence创建显式创建后设置fence
可变性不可变可重置/更新
标识符fd(文件描述符)handle(DRM对象)
生命周期绑定文件显式创建/销毁
时间线不支持支持(通过fence_chain)
回调仅内部使用支持用户回调

初看这两个结构体的定义,长得很像。单看本节有点理论,还是要结合用户态如何使用的场景来理解。后面两节分开专讲。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DeeplyMind

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

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

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

打赏作者

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

抵扣说明:

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

余额充值