第一章 OpenCL介绍

1.1 什么是OpenCL,或者为什么需要这本书

OpenCL是面向由CPU、GPU和其它处理器组合构成的计算机进行编程的行业标准框架。

1.2 多核的未来:异构平台

1.3 多核世界中的软件

并发性(concurrency):并发性是计算机科学中一个古老的概念。软件系统包含多个活动的操作流时,如果这些操作流同时向前推进,则称这个软件系统时并发的。

当并发软件在拥有多个处理单元的计算机上运行时,线程实际上可以同时运行,从而可以实现并行计算。硬件支持的并发性就是并行性。

程序员找出问题中的并发性是关键所在。

两个并行程序设计模型:任务并行(task paralelism)和数据并行(data parallelism)。

通用GPU(General-Purpose GPU, GPGPU)编程中,图形以外的算法会修改为适合于GPU处理。CPU完成计算并管理I/O,不过所有“实质性的”的计算都“分摊”给GPU。基本上,异构平台会背忽略,而把重点放在系统的一个组件上:GPU。OpenCL不建议采用这种方法。实际上,既然用户已经为系统中的“所有OpenCL设备”付了钱,有效的程序就应该使用所有这些设备。这正是OpenCL鼓励程序员采用的做法,也是我们对异构平台设计编程环境的期望。

1.4 OpenCL的概念基础

OpenCL支持大量不同类型的应用。无论哪一种情况,面向异构平台的应用都必须完成以下步骤:

1)发现构成异构系统的组件;

2)探查这些组件的特征,使软件能够适应不同硬件单元的特定特性;

3)创建将在平台上运行的指令块(内核);

4)建立并管理计算中涉及的内存对象;

5)在系统中正确的组件上按正确的顺序执行内核;

6)收集最终结果。

这些步骤通过OpenCL中的一系列API再加上一个面向内核的编程环境来完成。我们将采用一种“分而治之”的策略解释以上步骤的所有工作。我们把问题分解为一下模型:

平台模型(platform model):异构系统的高层描述。

执行模型(execution model):指令流在异构平台上执行的抽象表示。

内存模型(memory model):OpenCL中的内存区域集合以及一个OpenCL计算期间这些内存区域如何交互。

编程模型(programming model):程序员设计算法来实现一个应用时使用的高层抽象。

1.4.1 平台模型

OpenCL平台模型定义使用了OpenCL的异构平台的一个高层表示。

OpenCL设备进一步划分为计算单元(compute unit),而计算单元还可以更进一步划分为一个或多个处理单元。设备上的计算都在处理单元中完成。

1.4.2 执行模型

OpenCL应用由两个不同部分组成:一个宿主机程序(host program)以及一个或多个内核(kernel)组成的集合。

OpenCL定义了两类内核:

OpenCL内核:用OpenCL C编程语言编写并用OpenCL编译器编译的函数。所有OpenCL实现都必须支持OpenCL内核。

原生内核:OpenCL之外创建的函数,在OpenCL中可以通过一个函数指针来访问。例如,这些函数可以是宿主机源代码中定义的函数,或者是从一个专用库导出的函数。 

内核在宿主机上定义。宿主机程序发出一个命令,提交内核在一个OpenCL设备上执行。由宿主机发出这个命令时,OpenCL运行时系统会创建一个整数索引空间。对应这个索引空间中的各个点将分别执行内核的一个实例。我们将执行内核的各个实例称为一个工作项(work-item),工作项由它在索引空间中的坐标来标识。这些坐标就是工作项的全局ID。

OpenCL只能确保一个工作组中的工作项并发执行。

索引空间是一个N维的值网格,因此也称为NDRange。目前,这个N维索引空间中的N可以是1、2或3。在一个OpenCL程序中,NDRange由一个长度为N的整数数组定义,N指定索引空间各维度的大小。各个工作项的全局和局部ID都是一个N维元组。在最简单的情况下,全局ID中各个值的取值范围从0开始,到该维度元素个数为1。

上下文

宿主机的第一个任务是为OpenCL应用定义上下文。顾名思义,上下文定义了一个环境,内核就在这个环境中定义和执行。更准确地说,由以下资源定义上下文:

设备(device):宿主机使用的OpenCL设备集合。

内核(kernel):在OpenCL设备上运行的OpenCL函数。

程序对象(program object):实现内核的程序源代码和可执行文件。

内存对象(memory object):内存中对OpenCL设备可见的一组对象,包含可以由内核实例处理的值。

上下文由宿主机使用OpenCL API函数创建和管理。宿主机程序在在CPU上运行。

上下文中还包括一个或多个程序对象(program object),程序对象包括内核的代码。

命令队列

宿主机与OpenCL设备之间的交互是通过命令完成的,这些命令由宿主机提交给命令队列(command-queue)。这些命令会在命令队列中等待,直到在OpenCL设备上执行。命令队列有宿主机创建,并在定义上下文之后关联到一个OpenCL设备。宿主机将命令放入命令队列,然后调度这些命令在关联设备上执行。OpenCL支持3种类型的命令:

内核执行命令(kernel execution command):在OpenCL设备的处理单元上执行内核。

内核命令(memory command):在宿主机和不同内存对象之间传递数据,在内存对象之间移动数据,或者将内存对象映射到宿主机地址空间,或者从宿主机地址空间解映射。

同步命令(sysnchronization command):对命令执行的顺序施加约束。

1.4.3 内存模型

OpenCL定义了两种类型的内存对象:缓冲区对象(buffer object)和图像对象(image object)。

OpenCL内存模型定义了5种不同的内存区域:

宿主机内存(host memory):这个内存区域只对宿主机可见。与有关宿主机的大多数细节问题一样,OpenCL只定义了宿主机内存与OpenCL对象和构造如何交互。

全局内存(global memory):这个存储区域允许读、写所有工作组中的所有工作项。工作项可以读、写全局内存中一个内存对象的任何元素。读、写全局内存可能会缓存,这取决于设备的容量。

常量内存(constant memory):全局内存的这个区域在执行一个内核期间保持不变。宿主机分配并初始化放在常量内存中的内存对象。这些对象对于工作项是只读的。

局部内存(local memory):这个内存区域对工作组是局部的。这个内存区域可以用来分配该工作组中所有工作项共享的变量。它可以实现OpenCL设备上的专用内存区域。或者,局部内存区域也可以映射到全局内存的区域(section)。

私有内存(private memory):这个内存趋于是一个工作项私有的区域。一个工作项私有内存中定义的变量对其他工作项不可见。

OpenCL中内存模型的总结,展示了不同内存区域与平台模型如何交互

1.4.4 编程模型

任务并行和数据并行

1.6 OpenCL的内容

 OpenCL框架可以划分为以下组成部分:

OpenCL平台API:平台API定义了宿主机程序发现OpenCL设备所用的函数以及这些函数的功能,另外还定义了为OpenCL应用创建上下文的函数。

OpenCL运行时API:这个API管理上下文来创建命令队列以及运行时发生的其他操作。例如,将命令提交到命令队列的函数来自OpenCL运行时API。

OpenCL编程语言:这是用来编写内核代码的编程语言。

1.6.1 平台API

平台(platform)一词在OpenCL中有非常特定的含义。它表示宿主机、OpenCL设备和OpenCL框架的组合。一个异构计算机上可以同时存在多个OpenCL平台。

1.6.2 运行时API

平台API中的函数为OpenCL应用定义上下文。运行时API则强调使用这个上下文满足应用需求的函数。

原文地址:https://www.cnblogs.com/tcsong24/p/7602950.html