1 前言
1.1 目的
这篇文档的主要目的是,向原始设备制造商(OEMs),独立软件供应商(ISVs),第三方开发者们,提供在基于高通骁龙400系列、600系列,和800系列的手机平台和芯片上进行开发和优化Opencl应用程序的一些准则。
1.2 惯例
函数声明,函数名字,类型声明,属性,和代码示例会用不同的字体格式出现,比如#include
变量会用尖括号表示,比如 < number>
命令会用不同的格式出现,比如 copy a:*.* b:.
按钮和键盘名字会用粗体表示,比如点击Save 或者按下 Enter
(按照翻译作者也就是我自己的理解,会针对有些不好理解的地方进行一些补充说明,会使用斜体)
1.3 技术支持
针对这篇文档中内容的支持和解释,您可以向高通技术部提交疑问,地址是https://createpoint.qti.qualcomm.com/ 。
如果您无法访问这个技术支持页面,您可以在技术支持页面进行注册再访问或者向邮箱 [email protected] 发送邮件。
2 Opencl的简介
这一章主要讨论Opencl标准中的关键概念和在手机平台上开发Opencl程序的基础知识。如果想知道关于Opencl更详细的知识,请查阅参考文献中的《The OpenCL Specification》。对于已经有OpenCL的基础知识和经验的开发者可以跳过这一章,直接跳到下一章阅读即可。
2.1 OpenCL背景和概述
Opencl是由Khronos group开发和维护的一个开源的和完全免费的标准,针对是如何在异构系统上进行跨平台的程序并行。OpenCL设计理念是帮助开发者利用最新的异构系统的巨大的计算能力,并使跨平台的应用开发变的容易。
骁龙平台上使用的高通Adreno GPU系列是最早全面支持Opencl的手机GPU之一。
图2-1 使用Opencl的异构系统
图2-1表示了一个支持Opencl的典型异构系统。这个系统包含了3个主要部分:
n 一个主CPU,实质上就是一个指挥者/控制者,管理和控制应用程序。
n 多个OpenCL设备,包括GPU,DSP,FPGA和一个硬件加速器。
n Kernel代码,主设备编译Kernel代码,并下载到OpenCL设备中执行。
2.2 手机上的OpenCL
最近这些年,手机的片上系统(SOCs)已经在计算能力、复杂度和功能性上取得了显著的进步。手机SOCs上的GPU(手机的GPU)是非常强大的,某些顶级的手机GPU的原始计算能力能够达到控制台/分布式GPU(电脑的GPU)的水平。
开发者将面临这样的挑战:如何有效的利用GPU如此强大的计算能力,如何在不知道GPU的底层实现细节的情况下快速开发应用程序,同时能保持应用程序在不同SOCs上兼容性?
OpenCL的创造就是为了解决上面的问题,OpenCL的跨平台支持能够让开发者很方便的利用手机SOCs上的计算能力。通过使用OpenCL,许多领域的高级用例能够方便的在手机SOCs上使用,比如图像/音频处理,计算机视觉和机器视觉等。
在高通,在Andreno GPUs上使用OpenCL已经成功加速了许多案例,也展示了出色的性能、功耗和可移植行。针对在骁龙SOCs上开发的应用程序,强烈建议在GPU上使用OpenCL使其加速。
2.3 OpenCL 标准
OpenCL标准主要包两个方面:OpenCL的实时运行的API 和OpenCL的C语言规范(就是.cl文件)。API定义了一系列运行在Host上的函数,主要包括资源管理,内核分发(将kernel函数分发到不同的GPU上运行)以及许多其他的任务;OpenCL的C语言是用来写kernel函数的,kernel函数是运行在OpenCL设备(OpenCL设备参见图2-1)上。API和C语言将会在接下来的章节中说明。
(对照图2-1,OpenCL就是定义一些API,这些运行在主CPU上,将任务划分成一个个的kernel函数,将kernel函数分发到OpenCL设备上运行。)
2.3.1 OpenCL的API函数
OpenCL的API函数可以分成两种,平台层和实时运行层。表2-1 和表2-2分别总结了平台层和实时运行的一些高阶功能。
表2-1 OpenCL平台层的功能
功能 |
详细描述 |
发现平台 |
检查当前的OpenCL平台是否可用 |
发现OpenCL设备 |
在GPU,CPU或者其他设备上找到可用的OpenCL设备 |
查询OpenCL设备的信息 |
查询OpenCL设备信息包括:全局内存大小(global memory size),本地内存大小(local memory size),最大的工作组数量(maximun workgroup size)等。并且检查该设备支持的扩展功能(OpenCL定义了标准功能和扩展功能)。 |
上下文 |
上下文管理,比如上下文(context)的创建,保留和释放 |
表2-2 OpenCL的实时运行层的功能
功能 |
详细描述 |
命令队列的管理(Command queue) |
命令队列用于OpenCL设备(比如GPU)和主设备(比如主CPU)之间的通信,一个应用程序中可以有多个队列。 |
创建和编译OpenCL程序和kernel(内核),(编译.cl文件) |
检查kernel是否下载和编译正确 |
为kernel准备要执行的数据,创建内存对象,并对其初始化 |
使用什么样的内存标志(比如只读只写等)?是否有能直接创建0拷贝的内存(0拷贝在第7章将会详细说明)? |
创建一个kernel调用,并将它提交到对应的OpenCL设备上 |
使用多大的workgroup(工作组)? |
同步 |
内存同步(需要等OpenCL运行完后再进行结果拷贝)。 |
资源管理 |
传递运行结果(将OpenCL设备上运行结果拷贝到主设备)和释放资源。 |
理解这两个API层是写OpenCL应用程序的基本要求。参照参考文档获取更多细节信息。
2.3.2 OpenCL 的C语言(规定如何写.cl文件)
作为C99 标准的一个子集,OpenCL的C语言是用来写能编译和能在设备(以后OpenCL设备就简称设备)上运行的kernel函数的。有C语言编程经验的开发者能够很快上手OpenCL的C语言编程。但是,为了避免一些常见的错误,理解C99标准和OpenCL C语言之间的差别也是至关重要的。下面是两个关键的不同点:
n 由于硬件的限制和OpenCL的执行模型,一些C99的特性在OpenCL上并不支持。比如函数指针,动态内存分配(malloc/calloc等)
n OpenCL语言在某些方面扩展了C99标准,是为了更好的服务编程模型和方便开发。比如:
o OpenCL添加了内建函数来查询OpenCL内核的执行参数。
o 为了更好的使用GPU硬件,添加了图片加载和存储函数。
2.3.3 OpenCL的版本和概述
当前的OpenCL v2.2和临时SPIR-V 1.2标准包含了许多改进的特性。可参照参考目录获取更多细节。
OpenCL定义了两种profiles(不好翻译),嵌入式的profiles和完整的profiles。嵌入式的profiles主要是用于手机设备,相比于传统的计算设备比如台式机的GPUs,手机设备的计算精度更低,硬件特性更少。参考文档列出了嵌入式profiles和完整profiles之间的主要不同点。
2.4 OpenCL的可移植性和向后兼容性
2.4.1 程序的可移植性
作为一个被严格定义的计算标准,OpenCL有很好的可移植性。如果程序没有使用任何供应商特有的特性或者平台特有的扩展或特性,针对一个供应商平台写的OpenCL程序可以很好地在另一个供应商平台上运行。
OpenCL程序的兼容性已经被Khronos的验证程序保证了。如果OpenCL供应商声称他们是符合OpenCL标准的,Khronos的验证程序会要求OpenCL供应商在他们的平台上通过严格的一致性测试。
2.4.2 性能的可移植性
不像程序的可以执行,OpenCL的性能并不是可移植的。作为一个高级别的计算标准,OpenCL的硬件实现是取决于供应商的。不同的硬件供应商有不同的硬件架构,每一种架构都有它自己的优势和劣势。所以,针对某一个供应商平台开发和优化的OpenCL的应用程序,在另一个供应商的平台上可能不会有同样的性能
甚至对于同一个供应商,他们的不同系列的GPU硬件在微观架构和特性上都会有所不同,这样也会导致OpenCL程序表现出显著的性能差异。所以,针对老一代的硬件优化的程序经常需要进行一些调整,来充分发挥新一代硬件的运算能力。
2.4.3 向后兼容性
OpenCL能够完全向后兼容,来保证针对OpenCL旧版本的代码能够毫无问题的运行在新版本的OpenCL上。不过需要注意,因为有些API函数在新版本已经废弃不使用了,所以如果包含了OpenCL2.x版本头文件中并且使用了OpenCL 1.1 或者OpneCL1.2中过时的APIs,那么需要定义宏 CL_USE_DEPRECATED_OPENCL_1_1_APIS 或者CL_USE_DEPRECATED_OPENCL_1_2_APIS。
OpenCL的扩展并不保证在新的设备上能够继续使用,所以使用扩展功能的应用程序必须检查新的设备是否支持他们。
原文地址:https://www.cnblogs.com/xiajingwang/p/10981437.html