GPU内核驱动杂谈
GPU内核驱动杂谈
不同CPU相比,GPU中包含了大量的并行计算单元,适合处理像素,矩阵,坐标等大量同类型的数据,因此,很多LINUX上的应用程序为了能够利用GPU的加速功能,都试图和GPU直接打交道,因此,系统中可能有多个组件或者程序同时使用GPU,比如桌面系统中OpenGL的实现MESA。这样会带来一个问题,就是多个进程并发访问GPU,如果控制不好,势必会造成系统工作不稳定,为了解决这样的问题,LINUX内核开发者在内核中设计了DRM模块,所有访问GPU的操作都通过DRM统一管理,由DRM来统一协调对GPU的访问,所以,在Linux系统中,各类GPU驱动,包括NVIDIA,AMD等大厂的GPU驱动都是集成在DRM框架中的。如图9.4.1所示,以AMD GPU驱动为例,AMD GPU的内核驱动结构上是一个复杂的软件堆栈,负责管理和控制AMD图形硬件,以便应用程序可以与GPU进行通信并利用其图形处理能力,这些能力都是通过DRM提供的,DRM屏蔽了不同显卡厂家的硬件差异,以统一一致的接口向上层提供服务。
图9.4.1 GPU的内核驱动结构
以下是AMD GPU内核驱动的主要组成部分:
1)硬件抽象层(HAL)
HAL是位于底层的部分,负责与GPU硬件之间的通信。它提供了一个抽象的接口,使上层的驱动和应用程序可以访问GPU的功能和寄存器,而不需要了解具体的硬件细节。
2)图形命令处理器(GCP)
GCP负责接收、解析和执行应用程序发送的图形命令。它将应用程序的图形请求翻译成GPU硬件可以理解的指令,以执行绘图操作和渲染任务。
3)AMDGPU内核驱动
这是AMD GPU驱动的核心部分,运行在操作系统的内核空间。它与硬件通信,管理GPU资源(如显存和显卡寄存器),执行调度和任务分配,以确保多个任务在GPU上正确运行。
4)GPU用户空间驱动
GPU用户空间驱动是运行在操作系统的用户空间的组件,它与AMDGPU内核驱动协同工作,提供对GPU的高级控制。它包括OpenGL和Vulkan驱动程序,以及OpenCL运行时库,允许应用程序与GPU进行图形和通用计算任务的交互。
5)AMDGPU-PRO
AMDGPU-PRO是AMD的专业级GPU驱动,主要用于支持专业应用程序和工作负载,如CAD、3D建模和科学计算。它提供了更丰富的特性和支持,包括对专业图形API和库的更好的兼容性。
6)AMD ROCm
AMD ROCm(Radeon Open Compute)是一个开源的GPU计算平台,旨在支持GPU加速的深度学习和高性能计算工作负载。它包括ROCm内核驱动和ROCm用户空间工具,为GPU计算提供了强大的支持。
总之,AMD GPU的内核驱动结构是一个多层次的系统,由硬件抽象层、内核驱动、用户空间驱动和专业级组件组成,以便应用程序可以有效地利用AMD GPU的图形和计算能力。这些组件共同协作,确保GPU能够执行各种图形和计算任务。
如图9.4.2所示,箭头表示源模块会调用箭头指向的目标模块中的函数或者符号,这种调用通常和LINUXN内核中的框架驱动注册相对应,即由架构中低层次的模块向框架中高层次的模块注册操作句炳,所以实际的架构层次应该是上下颠倒的,也就是说,从架构上看,应该是DRM在上,而AMDGPU在最底层,只有扇入口,没有扇出口。
图9.4.2 GPU与DRM间数据交互的内核驱动结构
9.4.2 GPU任务调度内核态分析
1.简介
内核态的GPU驱动需要处理用户态驱动下发的渲染命令,对于每个用户态的进程,在提交渲染命令前首先通过mesa驱动创建属于自己的上下文,然后往上下文关联的cmdbuf中填入渲染命令然后下发。渲染命令并不是一条一条下发给内核,而是批量统一放到一个内存chunk中,这个chunk内存空间是用户态已经向内核申请好的,由内核DRM框架管理,因此用户态下发的实际动作就是下发ioctl命令字然后把chunk的指针告诉内核,内核只要获取到这个地址将其放到内核的IB对象中就可以了。
2.GPU调度示意图
GPU调度示意图,如图9.4.3所示。每个应用程序下发渲染命令前先创建自己的渲染上下文,然后下发渲染命令,渲染命令到达mesa驱动层后,mesa会对应地找到该命令所属的GPU硬件模块,然后下发ioctl命令将渲染命令提交到对应IP的令牌缓冲器上。
图9.4.3 GPU调度内核结构
在图9.4.3中,渲染命令在下发到内核之后会被封装成一个job,然后找到其所属的渲染上下文,更具体地,找到该job所属的GPU IP的令牌缓存区,获取该job应该加入的调度实体,然后加入调度实体上的调度队列。一个job代表一个应用程序下发的渲染命令,不同job可能来自不同的应用程序。
3.数据结构组织图
数据结构组织图,如图9.4.4所示。
图9.4.4 数据结构组织图
9.4.3 GPU 内核驱动分析同步工作模型
在Linux内核的AMDGPU驱动实现中,dma-fence扮演着重要角色,AMDGPU的渲染/解码操作可能涉及到多个方面同时引用缓存区的情况,以渲染/视频解码场景为例,应用将渲染/解码命令写入和GPU共享的缓存区之后,需要将任务提交给GPU的运行队列等待执行,这个时候,应用不仅要监听缓存区中任务的执行情况,还要保证在任务执行完毕之前,不能再去修改缓存区中的数据。而AMDGPU也需要排它性地执行缓存区命令。在GPU执行结束,应用希望及时得到执行完的信息,以便回收缓存区重新利用,通知一般由绑定到某个缓存区上的中断完成。这些操作,如果使用经典的共享缓存区+锁的方式进行保护和同步,不但效率十分低下,而且各类内核机制杂糅在一起,缺乏一个统一的管理框架,使代码难以维护。
dma-fence则提供了一套简单便捷的机框架,将原子操作,休眠唤醒,同步/异步事件通知等功能嵌入到各种类型的缓存区管理框架中,将各类机制有机的结合在一起,减少了用户态空间的忙等,使缓存区使用更加智能高效。
以AMDGPU解码视频为例,利用dma-fence令牌缓冲器隔离了应用解码请求和解码任务任务本身,提交任务和解码完成通知均通过缓存区绑定的dma-fence进行交互,如图9.4.5所示。
图9.4.5 AMDGPU解码视频中dma-fence令牌缓冲器结构
人工智能芯片与自动驾驶