现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

OpenCL的框架

2014-09-16 05:10 工业·编程 ⁄ 共 2592字 ⁄ 字号 暂无评论

面向异构平台的应用都必须完成的步骤:

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

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

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

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

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

6)收集最终结果。

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

本文主要讨论OpenCL框架,其组成可划分为以下三个部分:

  • OpenCL平台API:平台API定义了宿主机程序发现OpenCL设备所用的函数以及这些函数的功能,另外还定义了为OpenCL应用创建上下文的函数。
  • OpenCL运行时API:这个API管理上下文来创建命令队列以及运行时发生的其他操作。例如,将命令提交到命令队列的函数就来自OpenCL运行时API。
  • OpenCL编程语言:这是用来编写内核代码的编程语言。它基于ISO C99标准的一个扩展子集,因此通常称为OpenCL C编程语言。

OpenCL平台API

平 台(platform)一词在OpenCL中有非常特定的含义。它表示宿主机、OpenCL设备和OpenCL框架的组合。一个异构计算机上可以同时存在 多个OpenCL平台。例如,CPU开发商和GPU开发商可以在一个系统上分别定义自己的OpenCL框架。程序员需要一种方法查询系统中可用的 OpenCL框架。他们需要查找哪些OpenCL设备可用,这些OpenCL设备有什么特性。另外,他们还需要控制这些框架和设备的哪个子集构成给定 OpenCL应用中使用的平台。

这些功能由OpenCL平台API中的函数解决。在后面的章节中将会看到,我们重点讨论OpenCL程序员为宿主机程序编写代码时,每个OpenCL应用程序都以类似的方式打开,调用平台API的函数为OpenCL计算定义上下文。

OpenCL运行时API

平台API中的函数为OpenCL应用定义上下文。运行时API则强调使用这个上下文满足应用需求的函数。这是一个庞大而且确实相当复杂的函数集。运行时API的第一个任务是建立命令队列。可以将命令队列关联到一个设备,不过一个上下文中可以同时有多个活动的命令队列。有 了命令队列,就可以使用运行时API来定义内存对象和管理内存对象所需要的所有其他对象(如对于图像对象还需要采样器对象)。管理内存对象是一个很重要的 任务。为了支持垃圾回收,OpenCL会跟踪多少个内核实例使用这些对象(也就是说,持有一个内存对象),以及内核何时用完一个内存对象(即释放一个内存 对象)。

运行时API管理的另一个任务是创建构建动态库所用的程序对象,内核就由这些动态库定义。程序对象、编译程序对象的编译器以及内核定义都在运行时层处理。最后,与命令队列交互的命令都由运行时层的函数发出。管理数据共享和对内核执行施加约束的同步点也由运行时API处理。可以看到,运行时API函数完成了宿主机程序的大部分具体工作。要想一次掌握运行时API,从第一个函数开始学完所有函数,这是很有压力的。我们发现,更好 的做法是使用一种实用的方法。掌握真正要使用的函数。过一段时间,你就会把它们全面覆盖到,并完全掌握,不过要根据OpenCL应用的具体需要来学习这些 函数。

OpenCL编程语言

宿主机程序非常重要,不过完成OpenCL中实际工作的是内核。有些OpenCL实现允许你与非OpenCL编写的原生内核交互,不过,大多数情况下都需要编写内核来完成应用中的特定工作。OpenCL中的内核编程语言称为OpenCL C编程语言,因为我们希望过一段时间后可以定义符合规范的其他语言。它由ISO C99语言派生而来。在OpenCL中,要对支持可移植性特别当心。这要求我们标准化不同类的OpenCL设备之间的最小公共子集。由于C99中有些特性只有CPU能够支持,所以在定义OpenCL C编程语言时,我们去掉了C99的一些语言特性。删除的主要语言特性包括:1)递归函数;2)函数指针;3)位域。另外,我们不支持完整的标准库集合。OpenCL编程语言中不支持的标准头文件很多,不过程序员最有可能遗漏的是stdio.h和stdlib.h。再次说明,一旦不再将通用处理器作为OpenCL设备,这些库将很难获得支持。

由于需要保持OpenCL核心抽象的真实性,所以会带来另外一些限制。例如,OpenCL定义了一组内存地址空间。联合(union)或结构 (structure)不能混合类型。另外,OpenCL还定义了一些不透明的类型,例如,支持图像的内存对象。OpenCL C编程语言除了允许将这些类型作为参数传递给函数外,不允许对它们做任何其他处理。不过,在异构世界中,如果脱离CPU,那么对浮点算术运算的支持会有更多的选择。过去通过与硬件开发商的紧密合作,我们希望大力推动他们完善对IEEE浮点标准的支持。 与此同时,我们不希望对这些开发商过于苛刻,所以赋予他们一定的灵活性可以避开IEEE标准中一些不常使用但实现很困难的特性。

关于浮点数异常还有很多其他规则,不过它们对大多数人来说都过于复杂、深奥,没有必要在这里多做说明。关键是要了解我们已努力满足IEEE 754的大多数内容,同时省略了很少使用而且(在配有矢量单元的异构平台上)难以支持的一些特性。OpenCL规范并不仅限于IEEE标准。在OpenCL规范中,还有一些表格详尽地定义了数学函数中允许的相对误差。要想了解所有这些错误确实难度很大,不过对于编写详细数值代码的程序员来说,定义这些错误是至关重要的。综合以上浮点数需求、限制和扩展,就得到了一个非常适合当前异构平台的编程语言,随着这些平台中使用的处理器继续发展,并变得更为通用,OpenCL C编程语言也会随之发展。

小结

我们已经介绍了核心OpenCL框架的基本组成。要单独地了解这些组成部分(我们介绍时就主要采用了这种方式)很重要。为了把这些单独的部分汇集起来,形成OpenCL的一个全景图,下面对应用在OpenCL框架中的基本工作流做个小结,如图所示。

参考文献

[1] Aaftab Munshi , Benedict R. Gaster , Timothy G. Mattson , James Fung  and Dan Ginsburg “ OpenCL Programming Guide”.

作者:松子茶

给我留言

留言无头像?