Panfrost GPU性能调优
文档目的,目标
本文档主要是目的是总结自己最近这段时间的学习成果。假设目前自己接手一个Mali GPU芯片项目该如何入手,重要的不是具体实现细节,而是通过理顺实现思路,搞清楚实现过程中的技术难点,对于这些技术难点进行分类,有过相关经验的暂时放弃,不太理解的则尝试实现一个简化版功能,借此来理解此技术实现的原理和实现要点。
测试环境
硬件:rk3399
Kernel:6.1.63
Mesa: mesa_22.3.7
GPU框架分析
主要硬件模块
图1
图2
图1表示Mali GPU为代表的移动GPU硬件框图,一般4部分组成,其中GPU和GPU-FW可以理解为一个硬件模块,但是为了理解Panfrost,特意将分为两个部分。当然移动GPU也可以是上图2组成,即添加PCIe总线和GPU独占GDDR模块。一般认为图2组成性能比图1性能要高,但是功耗也高,代码实现相对复杂。
代码功能模块框图
图3
上图3中App代表OpenGL的功能实现,比如一个图片GPU显示;
Mesa代表OpenGL的中间库实现,主要实现应用层图片内存拷贝到内核内存;
Panfrost代表内核驱动实现,主要是将图片内存拷贝到GPU内存中用于显示;
GPUFW代表GPU的firmware部分,负责GPUFW中各种功能处理,这里的单纯图片显示不处理(不是很确定);
HDMI代表图片真正的显示在HDMI显示器上,完全依赖于DRM显示框架代码。
Panfrost
Panfrost 是 Linux ARM Mali GPU 开源驱动,主线从5.2开始支持,但是想要完美运行最好更新到5.10版本以后,更要根据本身拥有的硬件来选择合适的版本。具体可以参考如下网址: https://en.opensuse.org/ARM_Mali_GPU
Panfrost最开始主要由 Alyssa Rosenzweig 小姐姐逆向实现,OpenGL 性能高于 ARM 闭源驱动(对于这句话我持怀疑态度,怀疑的基础是不能在Panfrost中添加任何优化功能,即不能添加DMA等加速模块;怀疑理由,闭源驱动实际运行在硬件上,但是Panfrost实际却运行在主机CPU上,一般的经验是软件速度会低于硬件速度)。
Panfrost 的 Vulkan 驱动部分叫 panvk,2021年3月诞生,目前主要功能还没完整实现。
2022年初,原Intel公司的Vulkan开源驱动工程师 Jason Ekstrand,为了实现更好的开源GPU驱动,辞职加入 Collabora。近期 Jason Ekstrand 在 panvk 驱动的开发上很活跃,增加了 panvk compute shader 支持,使得让 ncnn 的 Vulkan GPU 加速成为可能。
目前我只接触过三家Mali GPU,RK,全志和菊花厂,RK目前已经可以编译运行Panfrost和Mesa,全志的不能编译,只能运行。菊花厂的没有GPU,据说全力推广本身的NPU。这里说明全志和菊花厂的也许也可以,但是我没有继续深入研究而已。所以目前已经验证的GPU测试硬件环境是RK3399,我们只是想一个学习的硬件测试环境而已。
Panfrost驱动本身代码其实相对比较简单。dts中的配置信息与驱动中的id匹配则加载probe函数,probe函数中实现gpu,mmu,Job,drm和gem等主要功能,其他电源管理和devreq管理代码等暂时忽略。这里面与性能优化相关的主要是drm和gem模块,而且是drm和gem被RK3399的DC代码调用。
RK3399的显示DRM框架代码在gpu/drm/rockchip/中rockchip_drm_drv.c文件,它本身也是一个DRM框架的代码,DRM本身也比较复杂我们只关系与性能优化部分相关的代码。推测dumb_create,gem_prime_import_sg_table和fops等都需要使用Panfrost中的drm结构体类似函数申请方法来申请内存,后面有时间实践一下在补充上。
static const struct drm_driver rockchip_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
.dumb_create = rockchip_gem_dumb_create,
.open = rockchip_open,
.postclose = rockchip_postclose,
.release = rockchip_release,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table,
.gem_prime_mmap = drm_gem_prime_mmap,
.fops = &rockchip_drm_driver_fops,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
};
IOMMU
Rk3399集成IOMMU,这里只是说一下对IOMMU的理解,MMU统一管理内存,避免碎片化,提高内存使用效率,防止申请内存不足的情况。IOMMU则是对物理内存的管理,尽量给设备提高足够的连续内存的方法。两者都不可避免降低运行效率。(如果不对请指出)
如果系统本身不支持IOMMU,如何申请大段连续物理内存?CMA机制。
DMA
Linux 内核本身有DMA子系统,一般开发板都已经将DMA模块集成好,我们这里直接使用即可,但是要DMA实现memset和texture拷贝功能,则需要修改DMA子系统来支持memset和texture两个功能。
Mesa
Mesa一直是GPU框架中的核心,linux中要求驱动开源,所以各个GPU商家就将核心放入到Mesa和专有的firmware中,Mesa和firmware都闭源来保护自己的商业机密。所有的GPU玩家都这样,N家A家I家,Arm和IMG无不如此,不过苹果好像已经放弃Mesa,转而主攻自己专有框架Metal。
根据各家的策略,Mesa其实大体分为两种,默认Mesa框架(目前是gallium);另外一种是IMG这样的玩法,通过ICD方式来提供和加载Mesa,可以理解是在Mesa公版的基础上添加自己功能实现。
分析Mesa的代码就要提到Xorg和Wayland,这里不展开具体内容,只要清楚两者只是调用的代码不同而已即可。
Mesa中涉及图片拷贝的代码比较多,src/util/format/u_format.c文件中的util_copy_rect函数是关键,dst和src分别表示目标内存和源内存,这里需要使用DMA函数来代替memcpy实现内存拷贝功能。估计这个功能完成后glmark2分数会提升不少。
Xorg和Wayland检测方法:
echo $XDG_SESSION_TYPE,
一般结果:wayland x11 tty。
OpenGL应用程序
OpenGL程序开发本身具有一定的复杂度,verison3.0前后变化很大,vertex,shader,光照技术,2D和3D显示等等很多需要了解的技术点。我觉得搞懂如下几个程序即可:1.1.window 1.2.points_lines 1.3.triangle 1.4.shader 1.5.texture。这里优化首先考虑的是图片数据拷贝功能,因为这里的数据量最大,其他诸如shader等内存不大,而且不易优化,需要根据处理流程深入研究优化点。
结合应用层代码和Mesa代码可以明确OpenGL(Mesa)性能优化可以使用DMA的根本关键点。性能优化不需要修改OPenGL层代码。
性能调优测试
glmark2运行是一个最简单,有效的方法。
总结
学习和工作中,不断总结文档是非常好的学习方法。
参考链接:
- 点赞
- 收藏
- 关注作者
评论(0)