关于OpenCL
OpenCL是Open Computing Language的简写,目前已经形成了标准,是跨平台的,通常由图形处理器(GPU)提供硬件层面支持。OpenCL的设计目的,主要是为了将GPU强大的浮点和并行运算能力,以及能与CPU协作的能力,从软件层面开放给用户使用。用法跟OpenGL类似。
通常情况下,对同一组数据进行并行运算,使用OpenCL比执行普通CPU端程序,要快很多倍。
站在应用软件的角度,OpenCL简单来说,就是一组API函数名称,操作系统通常会提供具体实现库,以及运行于GPU之上的程序(OpenCL中称为kernel),文件后缀通常为.cl,基于OpenCL语法编写的程序,由CPU加载编译后,传输到OpenCL设备的内存供GPU执行。各个图形处理器厂商,针对自己的具体芯片,在GPU驱动程序中适配这些API,用户就可以基于这些标准的API进行相关的OpenCL应用程序开发。
需要指出的是:跟OpenGL的shader程序类似,OpenCL的kernel程序也是具体GPU芯片相关的,不能跨GPU型号使用。同一段代码,可能换了GPU型号之后就不能编译通过,第一个GPU使用的二进制kernel程序,不应该直接加载到第二个不同型号GPU上面使用。
OpenCL应用运行框图
OpenCL设备内部,通常会有大量的并行计算单元(上图中的CU),每个计算单元内部又包含有若干个处理单元(图中的PE),PE可以同时并行地执行相同OpenCL代码,从而实现高性能并行运算,具体CU以及PE数量已经运算性能,跟具体GPU厂商的具体GPU型号有关。
OpenCL代码被CPU加载到设备内存之后,CPU通过相应的OpenCL API来启动OpenCL设备的运行,同时还能查询执行状态,实现CPU-GPU之间的同步,设备关闭等操作。
RZ/G2L上的OpenCL支持
RZ/G2L微处理器配备Cortex-A55(1.2 GHz)CPU、16 位 DDR3L/DDR4接口、带Arm Mali-G31的3D图形加速引擎以及视频编解码器(H.264),如下图红色框所示。此外,这款微处理器还配备有大量接口,如摄像头输入、显示输出、USB 2.0和千兆以太网,因此特别适用于入门级工业人机界面(HMI)和具有视频功能的嵌入式设备等应用。
此GPU支持2D/3D图形,以及通用GPU运算(GPGPU)。具体支持如下标准API:
● OpenCL 2.0 Full Profile
● OpenGL ES 1.1 2.0 3.0 3.1 and 3.2
RZ/G2L上的OpenCL Library及其使用
RZ/G2L的VLP开发环境里面有提供Linux版OpenCL Library(需要从官网另外下载)以及对应头文件。
RZ/G2L的OpenCL库支持3种运行模式:
● CPU Mode:并行运算在CPU端完成,应用程序仍然需要调用OpenCL库API,OpenCL库内部会基于ARMv8 NEON SIMD指令集做针对性优化。
● GPU Mode:并行运行在GPU端完成,驱动程序会充分利用OpenCL设备的PE单元,提示并行性和运算效率。
● BOTH Mode:上面两种模式的结合。
通常情况下,BOTH Mode能提供最佳性能,典型做法是将待处理的并行数据,平均分成连续的两部分,CPU和GPU各自处理一半的数据(BOTH模式)。结合CPU模式,是因为CPU端有高主频,大Cache,高DDR带宽等优势。由于GPU端PE的特殊性,对待处理的数据,要求是,所有输入数据运算方法相同,没有依赖性,比如:两组输入数组A[1024]和B[1024]分别存放有1024字节的float类型数据,将A和B同序号的数据分别做乘法,结果保存于浮点数组C[1024],即:
C[0] = A[0] * B[0];
C[1] = A[1] * B[1];
… …
因为所有PE只能并行执行相同的kernel程序。
OpenCL库的使用,主要分为如下步骤:
● 获取平台信息
● 获取设备信息
● 创建上下文
● 创建命令队列
● 创建和编译kernel程序
● 创建kernel对象
● 创建内存对象
● 设置kernel参数
● 执行kernel程序
● 同步操作
● 获取处理结果
● 清理资源
部分OpenCL API介绍
OpenCL API通常以 cl_ 开头,很容易识别。
获取平台信息
cl_int clGetPlatformIDs(cl_uint num_entries,
cl_platform_id *platforms,
cl_uint *num_platforms);
这个函数是OpenCL应用程序必须调用的第一个API,用来获取可使用的Platform ID数组,当平台数未知时,第一次调用clGetPlatformIDs函数获取平台数量,第二次调用clGetPlatformIDs函数获取平台对象,供后续API使用。
cl_int clGetPlatformInfo(cl_platform_id platform,
cl_platform_info param_name,
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret);
用于获取OpenCL的Profile信息、版本、平台制造商、支持的扩展等。
获取设备信息
cl_int clGetDeviceIDs(cl_platform_id_platform,
cl_device_type device_type,
cl_uint num_entries,
cl_device_id *devices,
cl_uint *num_devices);
这个API用来获取平台可使用的设备对象数组。可用于获取CPU/GPU/专用加速器等OpenCL设备数量等。
cl_int clGetDeviceInfo(cl_device_id device,
cl_device_info param_name,
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret);
用于获取选定设备相关信息,如并行计算单元最大数量、设备端全局内存大小等信息。
由于OpenCL API涉及的内容比较多,另一方面,OpenCL相关标准已经很成熟,网上有很多的示例资源可供参考,瑞萨也可以提供MPU上的OpenCL例子给到客户,剩下的OpenCL应用程序步骤相关API,就不进一步介绍了。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !