前言
在《移动端异构运算技术-GPUOpenCL编程(基础篇)》中,介绍了移动端GPU计算现状以及OpenCL编程的基础概念。本文将进一步阐述OpenCL的一些深入的知识,同时结合移动端主流GPU厂商之一的高通Adno芯片设计,阐述移动端OpenCL编程的优化的一些通用的手段。备注:高通GPU系列之外,华为麒麟、联发科天机等芯片采用的是ARM公司设计的Mali系列GPU,因为篇幅限制本文不做单独阐述。
基础概念
丨OpenCLOpenCL是由Khronos组织开发和维护的开放的、免费的标准,服务于异构系统中的跨平台并行编程。这种设计可以帮助开发者在利用现代异构系统来发挥出强大的并行计算能力,同时一定程度上也是跨平台的。
丨OpenCL高通高通是最早完全支持移动端OpenCL运算能力的芯片厂商之一,并且在国内及国际市场上占据了一定的市场份额。
OpenCL结构
一个抽象的OpenCL应用,通常包含以下几个部分:
CPUHost:作为整个OpenCL应用的管理、调度者,控制整个OpenCL的执行流程。
OpenCLDevices:具体的OpenCL硬件设备,比如GPU、DSP、FPGA等等。
OpenCLKernels:承担执行任务的OpenCL内核代码,会被OpenCLHost进行编译,并在对应的硬件进行执行。
丨移动端设备OpenCL目前的经验来看,Android阵营中的移动端设备,OpenCL通常使用GPU作为硬件加速端。高通的建议是在移动端选择GPU作为OpenCL的加速设备(注:其实多数情况并无选择可能,有且只能获得到一个GPU的device)。
OpenCL兼容性
丨程序可移植性OpenCL提供了不错的程序兼容性,一套OpenCL的代码,在不同的设备上都可以正常运行。当然,少部分基于硬件拓展能力,取决于当前硬件的支持情况。
丨性能可移植性与程序兼容性不同,OpenCL的性能可移植性通常是比较差的。作为一种高级的计算标准,OpenCL硬件部分的实现是依赖厂商的,每个厂商都会有各自的优点和缺点。因此,针对不同的硬件平台,如高通Adno或者ArmMali,同样的代码的性能表现是不同的。即使是相同的产商,随着硬件的迭代,相应的驱动也会有对应的微调,以充分利用新一代硬件的全部能力。针对不同的设备或者硬件针对性优化是非常必要的。当然这个是一个ROI(投入回报)问题。
丨向后兼容性OpenCL的设计尽可能的保证向后兼容性。如果要使用已经过时的能力的话,只需要引入特定的头文件即可。值得注意的是:OpenCL的拓展是不完全向后兼容的,这些拓展通常由硬件厂商结合硬件特性来提供,因此应用时需要考虑到不同硬件之间的拓展兼容性。
高通AdnoOpenCL架构
图中为高通AdnoGPUOpenCL(AdnoA5xGPUS)上层架构,OpenCL在执行过程中涉及到几个关键的硬件模块。
丨Shader(orstaming)processor(SP)(着色器、流处理器)AdnoGPU的核心模块,包含众多硬件模块,如算数逻辑单元、加载存储单元、控制流单元、寄存器文件等。
运行图形着色器(如顶点着色器、片元着色器、计算着色器等),运行计算负载,如OpenCL内核等。
每个SP对应一个或多个OpenCL的运算单元。
AdnoGPU可能包含一个或者多个SP,取决于芯片的档次,上图中展示的是单个SP的情况。
SP加载和读取Buffer类型或者带有__ad_write标记的Image类型数据对象时,可以利用L缓存。
SP加载只读的Image类型的数据对象时,可以利用L1缓存或者纹理处理器。
丨TextuProcesser(TP)(纹理处理器)根据内核的调度来进行纹理操作,如纹理的读取、过滤等。
TP和L1缓存相结合,减少从L缓存中读取数据时的缓存丢失几率。
丨UnifiedLCache(UCHE)(统一L缓存)响应SP对于Buffer类型的读取和加载,以及L1对于Image类型的数据的加载操作。
如何编写高性能OpenCL代码
丨性能兼容性前文提及了OpenCL的性能兼容性,由于不同硬件的特性并不相同,因此在一块芯片上的调优后的OpenCL代码在另一块芯片上性能可能并非最优的。需要参考对应硬件的文档来进行特异性的优化工作。对于不同的芯片,针对性的优化是必要的。
丨手段总览OpenCL程序的优化通常可以分为以下三类:
程序、算法级别优化
API级别优化
OpenCL内核优化
程序算法以及API层级的优化手段是较为通用的,此处主要展开OpenCL内核的优化手段。
OpenCL的优化问题本质上一个如何利用内核带宽和计算能力的问题。即合理的利用全局内存、本地内存、寄存器、多级缓存等,以及合理的利用逻辑运算单元、纹理单元等等。
丨程序是否适用OpenCL开发者需要确定程序是否适合使用OpenCL编写,可以通过以下几个方面来判断:
是否存在较大的数据输入
程序本身是否是计算密集型
程序是否对并行计算亲和
程序中的控制流操作相对较少
丨将CPU代码改造为GPU代码时性能Tips明确了上述的几个关键点之后,开发者可以着手将CPU的代码转化为OpenCL的代码,为了达到一个最优的性能,需要