OpenCL基础(一)

OpenCL基础(一)

  • OpenCL简介
  • OpenCL模型
    • 平台模型
    • 执行模型
      • 上下文
      • 命令队列
    • 存储模型
    • 编程模型

OpenCL简介

OpenCL是由Khronos Group针对异构计算装置进行并行化运算所设计的标准API以及程序语言。所谓的“异构计算在装置”,是指在统一电脑系统中,有两种以上架构差异很大的计算装置。OpenCL的主要设计目的是要提供一个容易使用且适用于各种不同装置的并行化平台。因此,它提供了两种并行化的模式,包括任务并行以及数据并行

OpenCL模型

OpenCL作为开放性的异构计算行业标准,计算平台可以是GPU、CPU,也可以是FPGA、DSP等,OpenCL将这些计算设备组织成一个统一的混合计算平台。OpenCL是一个完整的并行编程框架,为OpenCL开发人员提供了硬件抽象层API和面向内核的异构编程环境,便于开发者更方便地开发和优化他们的应用。
OpenCL框架主要包含4个模型,分别是平台模型、执行模型、存储模型和编程模型。

平台模型

如下图所示:OpenCL平台由两部分构成:宿主机和OpenCL设备。宿主机是异构计算的主控机,一般由CPU扮演该角色,只能存在一个宿主机。OpenCL设备主要进行数据运算操作,作为从设备接收宿主机的指令进行数据处理,可以是CPU、GPU、DSP或FPGA,以及OpenCL开发商支持的任何其他处理器,平台中可以有多个OpenCL设备。
OpenCL基础(一)_第1张图片
OpenCL设备内的计算资源由多个计算单元(CU)构成,这些计算单元进一步划分成多个更小的处理单元(PE),PE是OpenCL设备进行计算操作的最小单元
OpenCL宿主机负责管理所有的外部计算设备,计算任务通常由宿主机发起,选择特定的OpenCL外设并为之建立相应的执行环境,将计算任务和数据进行处理,等待计算完成后,宿主机读回运算结果,并结束该计算任务。

执行模型

OpenCL的平台模型为主从结构,其执行模型中的应用程序也相应分为宿主机程序和内核程序。宿主机程序完成应用中的主机运算部分,并通过上下文和命令队列来管理设备,控制内核程序在设备上的运行。**执行模型的核心就在于如何调度这些计算资源进行有效计算。**为了有效区分管理设备上的处理单元,宿主机将这些PE视作带有索引号的工作空间,工作空间中的每个节点代表一个work-item。实际中,**待处理的数据可能来自数组、图像或者立体图形,相应的工作空间也可以定义为一维、二维甚至三维的。**与坐标类似,工作节点在某一维度上的索引号称为节点在该维度上的全局ID(global ID),节点的全局ID与工作空间的维度定义是一致的。这些工作节点执行相同的内核程序,只是处理不同的数据。
此外,**还可以对工作空间进行粗粒度划分,将工作节点等分成多个小组,成为一个工作组(work group)。**工作组的维度与工作空间的维度和工作节点一样,每个工作组都有自己唯一的工作组(work group ID)。在工作组内部,节点也有唯一的工作组位置索引,称为局部ID(local ID)。全局ID、工作组ID和局部ID之间有严格的数学关系,有其中两个ID号可以推出另外一个ID号。

上下文

上下文主要包含如下一些硬件和软件资源:
1. 设备:OpenCL应用需要调用的计算设备。
2. 内核:在计算设备上执行的并行程序。
3. 程序对象:内核程序的源代码和可执行文件。
4. 内存对象:计算设备执行OpenCL程序所需的变量。

命令队列

宿主机通过命令对OpenCL设备进行管理和控制,这些命令被送入命令队列,OpenCL设备通过读取命令队列中命令进行相应的操作。命令队列由宿主机创建,与上下文可以管理多个OpenCL设备不一样,命令队列只能管理所关联的唯一一个设备,队列中的命令可以是以下三种:
1. 内核启动命令:在OpenCL设备上开始执行内核。
2. 内存命令:在宿主机与OpenCL设备之间移动数据,在宿主机地址空间与内存对象之间进行映射或解映射。
3. 同步命令:对命令执行顺序加以约束。同一个队列中的命令在执行时有乱序执行和有序执行两种模式:
乱序执行:命令按照其在命令队列中的顺序依次发射,但是执行顺序却没有固定的顺序,可以通过特定的同步机制来保证其执行顺序。
有序执行:命令按照其在命令队列中的顺序进行发射和执行,上一条命令执行完毕后才发射执行下一条命令。
有序执行是OpenCL命令的基本执行方式,只有特定的一些平台支持乱序执行方式。

存储模型

OpenCL将设备中的内部存储器抽象成四层结构的存储模型:
**全局内存(global memory):**同一个工作空间内的所有工作节点都可以进行读写,宿主机可以对其进行初始化,特点是存储容量大、访问速度慢。
**常亮内存(constant memory):**工作空间内所有工作节点都可以进行读操作,却不能进行写操作。由宿主机进行初始化,在kernel执行过程中保持不变。
**本地内存(local memory):**同一个工作组中所有的工作节点都可以进行读写操作,对其他工作组内的工作节点不可见,不可以通过宿主机进行初始化。
私有内存(private memory):工作节点的专属内存,对其他工作节点完全不可见,只能通过内核程序分配。
下表描述了宿主机和设备对内存的的分配和访问规则。
OpenCL基础(一)_第2张图片
下图描述了四层存储模型的作用区域以及与平台的对应关系。

OpenCL基础(一)_第3张图片
在运行OpenCL应用时,宿主机需要将待处理的数据送到OpenCL设备,OpenCL设备运算完成后需要把结构返回给宿主机,这就需要在宿主机与OpenCL设备之间进行数据交互,这种交互有两种方式:拷贝数据法和内存映射法。
OpenCL规定了一个松散的内存模型,它不保证所有的工作节点访问的内存状态是一致的,它只规定在一个工作节点内部访问内存必须是一致的;在工作组内,可以通过同步点来保证组内节点的内存访问一致性。在不同工作组的访问内存一致性上,OpenCL不提供任何保证。

编程模型

OpenCL支持数据并行的编程模型和按任务并行的编程模型,同时也支持混合编程模型。在OpenCL中,按数据并行的编程能够获得更好的性能,研究也最为广泛。
数据并行是指当大量的数据进行相同的运算操作时,可以通过同时在多个计算单元上运行相同的指令,分别处理不同的数据,最终共同完成这些数据的运算。工作节点通过自己的索引号来处理特定范围内的数据,即工作节点和它所处理的数据是一一对应的。对于这种对应关系,OpenCL提供了两种方法来确定:显式规定和隐式规定。显式规定要求用户不仅要规定工作组的总数目,还要具体规定到节点与工作组之间的对应关系。隐式规定则规定每个节点所属的工作组,这一任务交由编译器或者设备完成。
任务并行是指工作空间内每个工作节点在执行kernel程序时相对于其他节点是绝对独立的,并分别完成不同的任务。用户可以通过执行多个内核程序来实现任务并行。
任何多线程并行计算都要考虑数据一致性,为此OpenCL采用了三种同步方式:

1. 同一个work-group中所有节点间的数据同步。
2. 同一个command queue的不同commans之间的数据同步。
3. 同一个context中不同的command queues之间的数据同步。
单个工作组内的数据同步是通过local fence来实现,而在工作组之间是无法动态同步的。
在同一个命令队列中,OpenCL为其提供了clFinsh和clFlush函数来保证之前的命令执行完毕,对设备内存的读写命令也可以采用这种方式。
在同一上下文中的不同命令队列间,OpenCL没有提供相应的API来进行同步操作,用户可以通过与命令相关联的事件来进行同步。

你可能感兴趣的:(OpenCL)