全文字,预计阅读时间10分钟。一、前言
随着移动端芯片性能的不断提升,在移动端上实时进行计算机图形学、深度学习模型推理等计算密集型任务不再是一个奢望。在移动端设备上,GPU凭借其优秀的浮点运算性能,以及良好的API兼容性,成为移动端异构计算中非常重要的计算单元。现阶段,在Android设备市场,高通Adreno和华为Mali已经占据了手机GPU芯片的主要份额,二者均提供了强劲的GPU运算能力。OpenCL,作为Android的系统库,在两个芯片上均得到良好的支持。
目前,百度APP已经将GPU计算加速手段,应用在深度模型推理及一些计算密集型业务上,本文将介绍OpenCL基础概念与简单的OpenCL编程。(注:Apple对于GPU推荐的使用方式是Metal,此处暂不做展开)
二、基础概念
2.1异构计算
异构计算(HeterogeneousComputing),主要是指使用不同类型指令集和体系架构的计算单元组成系统的计算方式。常见的计算单元类别包括CPU、GPU等协处理器、DSP、ASIC、FPGA等。
2.2GPU
GPU(GraphicsProcessingUnit),图形处理器,又称显示核心、显卡、视觉处理器、显示芯片或绘图芯片,是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上执行绘图运算工作的微处理器。传统方式中提升CPU时钟频率和内核数量而提高计算能力的方式已经遇到了散热以及能耗的瓶颈。虽然GPU单个计算单元的工作频率较低,却具备更多的内核数及并行计算能力。相比于CPU,GPU的总体性能-芯片面积比,性能-功耗比都更高。
三、OpenCL
OpenCL(OpenComputingLanguage)是一个由非盈利性技术组织KhronosGroup掌管的异构平台编程框架,支持的异构平台涵盖CPU、GPU、DSP、FPGA以及其他类型的处理器与硬件加速器。OpenCL主要包含两部分,一部分是一种基于C99标准用于编写内核的语言,另一部分是定义并控制平台的API。
OpenCL类似于另外两个开放的工业标准OpenGL和OpenAL,二者分别用于三维图形和计算机音频方面。OpenCL主要扩展了GPU图形生成之外的计算能力。
3.1OpenCL编程模型
使用OpenCL编程需要了解OpenCL编程的三个核心模型,OpenCL平台、执行和内存模型。
平台模型(PlatformModel)
Platform代表OpenCL视角上的系统中各计算资源之间的拓扑联系。对于Android设备,Host即是CPU。每个GPU计算设备(ComputeDevice)均包含了多个计算单元(ComputeUnit),每个计算单元包含多个处理元素(ProcessingElement)。对于GPU而言,计算单元和处理元素就是GPU内的流式多处理器。
执行模型(ExecutionModel)
通过OpenCL的clEnqueueNDRangeKernel命令,可以启动预编译好的OpenCL内核,OpenCL架构上可以支持N维的数据并行处理。以二维图片为例,如果将图片的宽高作为NDRange,在OpenCL的内核中可以把图片的每个像素放在一个处理元素上执行,借此可以达到并行化执行的目地。
从上面平台模型部分可以知道,为了提高执行效率,处理器通常会将处理元素分配到执行单元中。我们可以在clEnqueueNDRangeKernel中指定工作组大小。同一个工作组中的工作项可以共享本地内存,可以使用屏障(Barriers)去进行同步,也可以通过特定的工作组函数(比如async_work_group_copy)来进行协作。
内存模型(MemoryModel)
下图中描述了OpenCL的内存结构:
宿主内存(HostMemory):宿主CPU可直接访问的内存。全局/常量内存(Global/ConstantMemory):可以用于计算设备中的所有计算单元。本地内存(LocalMemory):对计算单元中的所有处理元素可用。私有内存(PrivateMemory):用于单个处理元素。
3.2OpenCL编程
OpenCL的编程实际应用中需要一些工程化的封装,本文仅以两个数组相加作为举例,并提供一个简单的示例代码作为参考ARRAY_ADD_SAMPLE(