原文地址: CoderDock.com本节介绍OpenCL的四个编程模型。
0.前言
OPenCL作为开放性的异构计算的标准,支持的平台有CPU、GPU、DSP、FPGA。支持的设备如此不同,那么需要对它们有一个统一的分层、模型划分,才能让各家更好的实现--平台模型、执行模型、内存模型、编程模型。
1.平台模型
- OpenCL设备有两部分组成,宿主机和OpenCL设备
- 宿主机负责整体流程控制,一般为CPU。
- OpenCL设备主要负责数据运算操作。
- OpenCL设备内部由多个计算单元(CU)组成,每一个CU可以继续划分为处理单元(PU)。
- 执行流程: 宿主机负责管理所有的OpenCL设备,宿主机发起计算任务,选择特定的OpenCL设备并建立计算环境。然后将计算任务和数据发送给OPenCL设备。设备调用内部计算单元进行计算,完成后将结果返还给宿主机,该次计算任务结束。
2.执行模型
2.1执行模型概念
OPenCL是一个主从处理模型,根本是宿主机如何利用OpenCL设备上大量的计算资源进行有效计算。所以OpenCL执行模型的任务就是
如何高效地调用这些计算资源。
- 宿主机将每一个处理单元(PE)分配一个索引号,这个唯一的索引号称为全局ID(Global ID),全体PE被看做一个工作空间的work-item。
- 因为我们可能处理数组、图形乃至三维图像,所以对应的工作空间也可以定义为一维、二维、三维。
- 为了更好的处理不同的数据,我们可以将工作空间进行粗粒度的划分,如将一部分ID划分到一组,这个组称为work-group,每一个组内也可以分配ID,不过这个ID称为局部ID(Local ID)。全局ID和局部ID存在映射关系。
- OpenCL规范中使用一个长度为N的整数数组来描述工作空间的大小(N<=3)。数组中的数值对应相应维度上工作点的个数。
- 如果将我们常见的三维魔方想象成一个工作空间,那么一维即为红 {MOD}的一行,即一维个数为3,二维为红 {MOD}那个面,二维个数为9,三维即为整个工作空间,三维个数为27。
2.2上下文
计算工作主要在OpenCL设备上进行,但宿主机也扮演着非常重要的角 {MOD}。宿主机主要通过上下文(Context)管理OpenCL设备。上下文指的是所管理硬件和软件资源,如下所示:
- 设备:OpenCL程序调用的计算设备
- 内核:在计算设备上执行的并行程序。
- 程序对象:内核程序的源代码(.cl文件)和可执行文件。
- 内存对象:计算设备执行OpenCL程序所需的变量。
上下文由宿主机使用API进行创建、管理、销毁。
2.3命令队列
宿主机主要通过命令对相应设备进行控制。根据计算量的大小,计算设备并不能立刻执行完被分配的计算任务。那么宿主机只能等着计算设备把任务计算完了才能继续分配新的任务么?显然不是,每一个计算设备都会有一个命令队列。
命令队列只能管理一个计算设备。通过命令队列,就实现了宿主机和计算设备的异步控制与执行。 队列中的命令主要有三种:
- 启动命令:OpenCL设备开始执行内核程序。
- 内存命令:在宿主机与内存设备之间移动数据,或者在两者之间进行内存映射。
- 同步命令:约束命令在计算设备上的执行:
- 乱序执行: 命令按照在命令队列中的顺序进行发射,但不保证计算设备是按照这个顺序进行执行的。
- 有序执行: 命令按照在命令队列中的顺序进行发射和执行,上一条命令执行完成后才能发射下一条命令。
宿主机程序可以为一个计算设备创建多个命令队列--
一个计算设备可以有多个命令队列。这些命令队列没有关联。这也就意味着一个计算设备可以执行多个种类的任务,如小明可以在等待游戏加载的事件背几个英语单词 ~_~。
3.存储模型
与通用计算程序的内存对象相似,OpenCL将设备中的存储器抽象成四层结构的存储模型:
- 全局内存:工作空间中的所有节点都可以读写。(全局变量)
- 全局变量:工作空间中的所有节点都可以读,但不可以写。(全局常量)
- 本地内存:同一个工作组中的工作节点可以进行读写,对其他工作组不可见。不能通过宿主机进行初始化。(当前文件的全局变量)
- 私有内存:只属于工作节点。(函数中的局部变量)
在程序运行期间,需要宿主机和计算设备进行数据交换,存在两种方式:
- 数据拷贝进行:将需要的数据拷贝到工作组空间,计算完成后再拷贝出去(传形参)
- 内存映射:将需要计算数据的地址传进去(传指针)
4.编程模型
前面已经提到计算的时候可以按照两种模型来进行计算:数据并行和任务并行。
- 数据并行:将需要计算的数据进行等分,分配给不同的计算设备进行计算。如需要进行两个很大矩阵的求和运算,那么就可以将矩阵数据分成几份,那么理论上计算事件缩减为原来的
1/N
。这适用与数据想关联不大的计算任务。 - 任务并行:如计算数据量不大,但每一个步骤前后依赖,如你必须先将水烧开才能下面条,如果你需要不断的煮面条,那么就可以将这个过程分成阶段,用好几个锅同时进行。具体细节参考工厂的流水线工作模式。
既然有数据或任务的并行,那么同步就成为一个绕不开的节点。并行是指在计算设备执行内核的过程中,对于其他的节点是绝对独立的,互不影响。OpenCL有三种方式进行同步:
- 同一个work-group的节点间进行数据同步。
- 同一个命令队列中的命令进行同步
- 同一个上下文中的命令队列进行同步。