《OpenCL异构并行计算:原理、机制与优化实践》笔记(一):OpenCL简介
[题外话]近期申请了一个微信公众号:平凡程式人生。有兴趣的朋友可以关注,那里将会涉及更多更新OpenCL+OpenCV以及图像处理方面的文章。
第1章 异构并行计算的过去、现状和未来
1、 异构并行计算包括两个方面的内容:异构和并行。异构是指:计算单元由不同的多种处理器组成,如X86CPU+GPU、ARM CPU+GPU、X86 CPU+FPGA、ARM CPU+DSP等。并行是指:要发挥异构硬件平台的全部性能必须要使用并行的编程方式。
2、 向量化:一种一条指令同时处理多个数据的方法,从这一点来说,它是一种数据并行技术。主流的向量化技术有两种:SIMD(Single Instruction Multiple Data,单指令多数据)和SIMT(SingleInstruction Multiple Thread,单指令多线程)。大多数CPU都使用SIMD的向量化技术,而大多数GPU都使用SIMT向量化技术。
3、 多核:在一块芯片上,集成多个处理器核心,这多个处理器核心共享或不共享缓存层次结构。
4、 多路:硬件生产商会将多个多核处理器互联在同一个主板上,各个多核处理器之间通常共享缓存或内存来交换数据。
第2章 OpenCL的基本介绍
1、 2008年,苹果公司向KhronosGroup提交了一份关于跨平台计算框架的草案,该草案由苹果公司开发,并与AMD、IBM、Intel和NVIDIA公司合作逐步完善。这个跨平台计算框架就是OpenCL(Open Computing Language,开放计算语言)。2008年12月8日,OpenCL 1.0技术规范发布。2010年6月14日,OpenCL 1.1发布。2011年11月19日,OpenCL 1.2发布。2013年11月19日,OpenCL 2.0发布。
2、 OpenCL是一个为异构并行计算平台编写程序的工业标准,此异构计算平台可映射到CPU、GPU、DSP和FPGA等计算设备。OpenCL提供了底层硬件结构的抽象模型,旨在提供一个通用的开放API。
3、 Khronos Group将OpenCL异构并行计算架构划分为平台模型(platform model)、存储器模型(memory model)、执行模型(execution model)和编程模型(programming model)。
4、 OpenCL平台模型由主机及其相连的一个或多个OpenCL设备组成。通常主机是指包含X86或ARM处理器的计算平台。OpenCL设备可以是CPU(也可以将主机端的CPU作为OpenCL设备)、GPU、DSP、FPGA或硬件商提供、OpenCL开发商支持的任何其他处理器。
5、 每个OpenCL设备有一个或者多个计算单元(Compute Units,CU),而每个计算单元又由一个或多个处理单元(Processing Element,PE)组成,处理单元是设备上执行数据计算的最小单元。
6、 目前OpenCL设备主要通过PCI-e总线和主机相连接。
7、 OpenCL程序包括主机端程序和设备端内核(kernel)程序。主机端程序运行在主机处理器上,主机端程序运行在主机处理器上,主机端程序以命令方式将内核程序从主机提交到OpenCL设备,OpenCL设备在处理单元上执行计算。
8、 OpenCL中定义了三种内核:OpenCL内核:用OpenCL C编程语言编写,并用OpenCLC编译器编译的函数。原生内核:OpenCL之外创建的函数,在OpenCL中可以通过一个函数指针来访问。内建内核:被绑定到特定设备,并不需要源码编译成程序对象的函数。
9、 程序开始执行时,数据通常都在主机上,故OpenCL设备需要从主机上获得数据,在OpenCL设备计算完成后,又需要将数据从OpenCL设备复制回主机。
10、 主机使用OpenCL API来创建和管理上下文,内核在此上下文中执行。上下文定义了内核执行的环境,包含了:设备:OpenCL平台包含的一个或多个设备。内核对象:在OpenCL设备上运行的OpenCL内核函数。程序对象:实现整个内核程序的源代码和目标二进制码。存储器对象:对主机和OpenCL设备可见的对象,内核执行时操作这些对象的实例。
11、 OpenCL提供了两种方式从代码中构建对象:一种是从程序源代码中构建,另一种是从源代码中已经编译好的代码上构建。
12、 命令队列由主机或运行在设备中的内核(该功能需要支持OpenCL2.0的设备)提交给命令队列。
13、 放入命令队列中的命令分为下列三种类型:内核入队命令:将一个内核入队关联到同一个OpenCL设备的命令队列中。存储器入队命令:将在主机与设备内存对象间传输数据,或将内存对象映射到主机地址空间,或从主机地址空间取消映射提交给命令队列。同步命令:对命令队列中需要执行的命令施加执行顺序约束。
14、 命令队列中命令执行有两种模式:按序执行:命令按其排入命令队列中的先后顺序执行,并按顺序完成。乱序执行:命令以任意顺序执行,通过显示的同步点或显式事件依赖项来约束顺序。
15、 索引空间是OpenCL支持的一个N维值的网格,称为NDRange ,其中N为1,2或3。三个长度为N的数据确定了NDRange的以下特征:每个维度索引空间(或全局大小)的范围;一个偏移指数F表明每个维度的初始索引值(默认为0);一个工作组(局部大小)每个维度大小。
16、 我们将执行内核的各个实例称为一个工作项(work-item),工作项将由它在索引空间中的坐标来标识,这个坐标就是工作组的全局ID,值从F到F加上该维度元素个数减1。
17、 多个工作项组织为工作组(work-group),工作组中工作项的数量由内核入队时的参数决定。
OpenCL异构平台由主机端和设备端构成,存储器区域包含主机与设备的内存。OpenCL中的存储区域分为:A、主机内存(host memory):主机直接可用的内存。B、全局存储器(global memory):允许上下文中任何设备中所有工作组的所有工作项的读写。全局存储器的读写可能会被缓存,这取决于设备能力。C、常量存储器(constant memory):全局存储器中的一块区域,在内核实例执行期间其保存的数据保持不变。对工作项而言它是只读的,主机负责对其进行分配和初始化。D、局部存储器(local memory):其对工作组是局部可见的,可以用来分配由该工作组中所有工作项共享的变量。E、私有存储器(private memory):它是一个工作项的私有区域。其中定义的变量对其他工作项是不可见的。
18、 一个存储器对象就是对全局存储器区域的一个引用。在OpenCL中,存储器对象分为三种不同类型:A、缓冲(buffer):内核可用的一个连续的存储器区域,通过指针来访问缓冲区。B、图像(image):图像对象用于存储基于标准格式的图像。它是一个不透明的数据结构,使用OpenCL API函数来管理。C、管道(pipe):它是数据项有序的队列。管道有两个端点:一个是写端点,用于插入数据项;另一个是读端点,数据项从读端点被移除。
19、 在主机和设备间有三种交互方式:读/写/填充、映射和解映射以及拷贝。
20、 在OpenCL 2.0中,OpenCL通过共享虚拟存储器(Shared Virtual Memory, SVM)机制扩展了全局存储器区域到主机内存区域的方式。在OpenCL 2.0中定义了三种SVM类型:A、粗粒度SVM:共享发生在OpenCL缓冲存储器对象区域的粒度;B、细粒度SVM:共享发生在OpenCL缓冲存储器对象里独立地以字节加载/存储的粒度;C、细粒度系统SVM:共享发生在主机内存内任何地方独立地以字节加载/存储的粒度。粗粒度内存SVM是OpenCL的核心规范,而对于后两种细粒度实现是可选的。
OpenGL定义了一个跨编程语言、跨平台的应用程序接口规范,它用于生成二维、三维图像。这个接口由近350个不同的函数调用组成,用来从简单的图像比特绘制到复杂的三维景象。