OpenCL 通用编程与优化(1)
1. 引言
1.1. 目的
本文档为oem、isv和第三方开发人员提供了指南,以便在基于高通®骁龙™400-、600-和800的移动平台和芯片组上开发和优化OpenCL应用程序。
1.2. 约定
函数声明、函数名称、类型声明、属性和代码示例会以不同的字体出现,例如,cp armcc armcpp。
代码变量显示在角括号中,例如,<编号>。要输入的命令会以不同的字体显示,例如,复制 a:. b:。
按钮和键名称以粗体显示,例如,单击保存或按Enter键。
1.3. 技术援助
对于本文档中的信息的帮助或澄清,请在https://support.qualcomm.com/上打开一个技术支持案例。
您将需要注册一个高通ID帐户,您的公司必须启用支持才能访问我们的案例系统。https://qualcomm.com/support上还列出了其他系统和支持资源。
如果你需要进一步的帮助,你可以发送电子邮件到qualcomm.support@qti.qualcomm.com。
2. OpenCL简介
本章讨论OpenCL标准的关键概念,并试图传达OpenCL的基本知识。要更详细地了解OpenCL标准,请参阅参考文献中的OpenCL规范。之前拥有OpenCL知识和经验的开发人员可以跳过本章,转到下一章。
2.1. OpenCL的背景和概述
由Openos集团开发和维护,OpenCL是一个用于异构系统中的跨平台并行编程的开放和免费的标准。它旨在帮助开发人员利用现代异构系统中可用的巨大计算能力,并促进跨平台的应用程序开发。骁龙平台上的高通®肾上腺素TMGPU系列是最早完全支持OpenCL的移动GPU之一。
图2-1使用OpenCL的异构系统
图2-1显示了一个支持OpenCL的典型异构系统。在这个系统中,有三个部分:
- 一个主机CPU,它是一个管理和控制应用程序的指挥官/主机。
- OpenCL设备,包括GPU、DSP、FPGA,和一个硬件加速器。
- 由主机编译并加载到OpenCL设备以执行的内核代码。
2.2. 移动上的OpenCL
近年来,移动芯片系统(soc)在计算能力、复杂性和功能方面都取得了显著的进步。移动soc(移动gpu)中的gpu非常强大,而顶级的移动gpu在原始计算能力方面达到了控制台/离散gpu的水平。在不了解gpu的底层细节的情况下,使用它们的计算能力开发应用程序,并在不同的soc之间维护应用程序的兼容性,这成为开发人员面临的一个巨大挑战
OpenCL是为了解决这些问题而创建的,由于它的跨平台支持,它使得开发人员能够轻松地利用移动soc的计算能力。通过使用OpenCL,移动soc可以很容易地在图像/视频处理、计算机视觉、机器学习等领域实现高级用例。
Adrenogpu通过OpenCL极大地加速了许多用例,展示了卓越的性能、性能和可移植性。强烈建议使用OpenCL来加速它们在骁龙soc中的应用。
2.3. OpenCL标准
OpenCL标准主要包含两个组件,即OpenCL运行时API和OpenCL C语言。API定义了一组运行在主机上的函数,用于资源管理、内核分派和其他任务,而OpenCL C语言则用于编写在OpenCL设备上执行的内核。下面的部分将快速回顾OpenCL API和OpenCL C语言。
2.3.1 OpenCL API functions
OpenCL API功能可以分为平台层和运行时两类。下表分别总结了平台层和运行时层的高级功能。
表2-1 OpenCL平台层功能
功能 | 明细 |
---|---|
发现平台 | 是否有一个OpenCL平台可用? |
发现OpenCL设备 | OpenCL是否在GPU、CPU或其他设备上可用? |
OpenCL是否在GPU、CPU或其他设备上可用? | 全局内存大小、本地内存大小、最大工作组大小等。检查设备支持的扩展名。 |
上下文 | 上下文管理,如上下文创建、保留和发布 |
表2-2 OpenCL运行时层功能
功能 | 明细 |
---|---|
命令队列管理 | 用于设备和主机之间的通信,并且在应用程序中可以有许多队列。 |
创建和构建OpenCL程序和内核 | 内核的加载和构建是否成功? |
准备好可供内核执行的数据,创建内存对象并初始化它们 | 要使用什么内存标志?有没有一种方法可以创建零复制内存对象? |
创建一个内核调用,并将其提交给计算设备 | 使用的工作组规模? |
同步 | 内存一致性。 |
资源管理 | 交付结果和发布资源。 |
2.3.2 OpenCL C语言
作为C99标准的一个子集,OpenCL C语言用于编写可以在设备上进行编译和执行的内核。有C语言编程经验的开发人员可以很容易地开始使用OpenCL C编程。然而,理解C99标准和OpenCL C语言之间的区别是避免常见错误的至关重要。以下是两个关键的区别:
- 由于硬件限制和OpenCL执行模型,C语言不支持C99中的一些特性。例如,函数指针和动态内存分配(malloc/calloc等)。
- OpenCL C语言在几个方面扩展了C99标准,以便它可以更好地服务于其编程模型并促进开发,例如:
- 它添加了内置函数来查询OpenCL内核执行参数。
- 它具有可以利用GPU硬件的映像加载/存储功能。
2.3.3 OpenCL版本和配置文件
带有临时SPIR-V 1.2标准的OpenCL 3.0包含了比上一代相比的许多改进。有关更多详细信息,请参阅参考资料。
OpenCL定义了两个配置文件(嵌入式概要文件和完整配置文件)。嵌入式配置文件的目标是移动设备,这些设备通常具有较低的精度能力,比传统计算设备更少的硬件功能更少。有关嵌入式和完整配置文件之间的关键差异的列表,请参考文献。
2.4 OpenCL的可移植性和向后兼容性
2.4.1程序可移植性
作为一个严格定义的计算标准,OpenCL具有良好的程序可移植性。为一个供应商的平台编写的OpenCL应用程序应该在其他供应商的平台上运行良好,如果它们不使用任何供应商专有的或特定于平台的扩展或特性。
OpenCL的程序可移植性是由Khronos的认证程序确保的,该程序要求OpenCL供应商在其平台上通过严格的一致性测试,然后他们声称OpenCL是“一致性”。
2.4.2 性能可移植性
与程序可移植性不同,OpenCL性能是不可移植的。作为一个高级计算标准,OpenCL的硬件实现依赖于供应商。不同的硬件供应商有不同的设备架构,每个供应商可能都有其优缺点。因此,为一个供应商的平台编写和优化的OpenCL应用程序不太可能具有与在其他供应商的平台上相同的性能。
即使对于相同的供应商,不同一代的GPU硬件在微架构和特性上也可能有所不同,这可能导致OpenCL程序的显著性能差异。因此,针对旧代硬件进行优化的应用程序通常需要进行微调,以利用新一代硬件的全部容量。
2.4.3 向后兼容性
OpenCL完全支持向后兼容性,以确保对旧代码的投资可以在新版本的OpenCL上运行。由于一些API函数在新版本中可能被弃用,如果使用OpenCL 1.1或1.2被弃用的API,则需要定义像CL_USE_DEPRECATED_OPENCL_1_1_APIS或CL_USE_DEPRECATED_OPENCL_1_2_APIS这样的宏。x头文件。如果OpenCL2。类似的规则适用于OpenCL 3.0头文件中使用x宏。OpenCL扩展可能无法转发到新设备,而使用扩展的应用程序需要检查新设备是否支持它们。这将在第9章中进行更详细的讨论