OpenCL 2.0 异构计算 [第三版] (中文)
  • Introduction
  • 序言
  • 第1章 简介异构计算
    • 1.1 关于异构计算
    • 1.2 本书目的
    • 1.3 并行思想
    • 1.4 并发和并行编程模型
    • 1.5 线程和共享内存
    • 1.6 消息通讯机制
    • 1.7 并行性的粒度
    • 1.8 使用OpenCL进行异构计算
    • 1.9 本书结构
  • 第2章 设备架构
    • 2.1 介绍
    • 2.2 硬件的权衡
    • 2.3 架构设计空间
    • 2.4 本章总结
  • 第3章 介绍OpenCL
    • 3.1 简介OpenCL
    • 3.2 OpenCL平台模型
    • 3.3 OpenCL执行模型
    • 3.4 内核和OpenCL编程模型
    • 3.5 OpenCL内存模型
    • 3.6 OpenCL运行时(例子)
    • 3.7 OpenCL C++ Wapper向量加法
    • 3.8 CUDA编程者使用OpenCL的注意事项
  • 第4章 OpenCL案例
    • 4.1 OpenCL实例
    • 4.2 直方图
    • 4.3 图像旋转
    • 4.4 图像卷积
    • 4.5 生产者-消费者
    • 4.6 基本功能函数
    • 4.7 本章总结
  • 第5章 OpenCL运行时和并发模型
    • 5.1 命令和排队模型
    • 5.2 多命令队列
    • 5.3 内核执行域:工作项、工作组和NDRange
    • 5.4 原生和内置内核
    • 5.5 设备端排队
    • 5.6 本章总结
  • 第6章 OpenCL主机端内存模型
    • 6.1 内存对象
    • 6.2 内存管理
    • 6.3 共享虚拟内存
    • 6.4 本章总结
  • 第7章 OpenCL设备端内存模型
    • 7.1 同步和交互
    • 7.2 全局内存
    • 7.3 常量内存
    • 7.4 局部内存
    • 7.5 私有内存
    • 7.6 统一地址空间
    • 7.7 内存序
    • 7.8 本章总结
  • 第8章 异构系统下解析OpenCL
    • 8.1 AMD FX-8350 CPU
    • 8.2 AMD RADEON R9 290X CPU
    • 8.3 OpenCL内存性能的考量
    • 8.4 本章总结
  • 第9章 案例分析:图像聚类
    • 9.1 图像聚类简介
    • 9.2 直方图的特性——CPU实现
    • 9.3 OpenCL实现
    • 9.4 性能分析
    • 9.5 本章总结
  • 第10章 OpenCL的分析和调试
    • 10.1 设置本章的原因
    • 10.2 使用事件分析OpenCL代码
    • 10.3 AMD CodeXL
    • 10.4 如何使用AMD CodeXL
    • 10.5 使用CodeXL分析内核
    • 10.6 使用CodeXL调试OpenCL内核
    • 10.7 使用printf调试
    • 10.8 本章总结
  • 第11章 高级语言映射到OpenCL2.0 —— 从编译器作者的角度
    • 11.1 简要介绍现状
    • 11.2 简单介绍C++ AMP
    • 11.3 编译器的目标 —— OpenCL 2.0
    • 11.4 C++ AMP与OpenCL对比
    • 11.5 C++ AMP的编译流
    • 11.6 编译之后的C++ AMP代码
    • 11.7 OpenCL 2.0提出共享虚拟内存的原因
    • 11.8 编译器怎样支持C++ AMP的线程块划分
    • 11.9 地址空间的推断
    • 11.10 优化数据搬运
    • 11.11 完整例子:二项式
    • 11.12 初步结果
    • 11.13 本章总结
  • 第12章 WebCL:使用OpenCL加速Web应用
    • 12.1 介绍WebCL
    • 12.2 如何使用WebCL编程
    • 12.3 同步机制
    • 12.4 WebCL的交互性
    • 12.5 应用实例
    • 12.6 增强安全性
    • 12.7 服务器端使用WebCL
    • 12.8 WebCL的状态和特性
  • 第13章 其他高级语言中OpenCL的使用
    • 13.1 本章简介
    • 13.2 越过C和C++
    • 13.3 Haskell中使用OpenCL
    • 13.4 本章总结
Powered by GitBook
On this page

Was this helpful?

  1. 第3章 介绍OpenCL

3.6 OpenCL运行时(例子)

OpenCL的四种模型在之前的章节中已经全部讨论了,OpenCL通过运行时API让应用开发者了解这些模型。平台模型用来使能一个主机,以及一个或多个设备,让其参与到OpenCL应用的执行中。应用开发者使用编程模型来让OpenCL内核实现其核心计算部分。内核执行时如何获取需要的数据,则有内存模型定义。开发者通过执行模型提交相应的命令到设备端(执行内存搬运或执行内核任务)。本节会将这些内容融合到一个完整的OpenCL应用中。

创建并执行一个简单的OpenCL应用大致需要以下几步:

  1. 查询平台和设备信息

  2. 创建一个上下文

  3. 为每个设备创建一个命令队列

  4. 创建一个内存对象(数组)用于存储数据

  5. 拷贝输入数据到设备端

  6. 使用OpenCL C代码创建并编译出一个程序

  7. 从编译好的OpenCL程序中提取内核

  8. 执行内核

  9. 拷贝输出数据到主机端

  10. 释放资源

下面的代码将具体实现以上总结的每一步。OpenCL应用中,大部分的通用代码对OpenCL的执行进行设置,这样就允许跨硬件平台(不同的供应商)架构来执行OpenCL内核。因此,其中的大部分代码可以直接在其他的应用中直接使用,并且可以抽象成用户定义函数。之后的章节,将展示OpenCL C++ API,其冗余要小于C API。

现在我们来讨论逐个步骤。本节之后,将会提供完整的程序代码。

1. 查询平台和设备

OpenCL内核需要执行在设备端,那么就需要至少一个平台和一个设备可以查询。

之后的完整代码中,我们将默认使用首先找到的平台和设备。这样的源码看起来更加简单明了。

2. 创建一个上下文

找到平台和设备之后,就可以在主机端对上下文进行配置。

3. 为每个设备创建一个命令队列

创建完上下文,就要为每个设备创建一个命令队列(每个命令队列只关联其对应的设备)。主机端需要设备端执行的命令将提交到命令队列中,由命令队列管理执行。

4. 创建设备数组用于存储数据

创建一个数组需要提供其长度,以及与该数组相关的上下文;该数组能对该上下文所有设备可见。通常,调用者需要提供一些标识,来表明数据是可只读、只写或读写。如果第四个参数传NULL,OpenCL将不会在这步对数组进行初始化。

5. 拷贝输入数据到设备端

下一步就是将主机端指针指向的数组拷贝到设备端。该API需要一个命令队列对象作为参数,所以数据通常都是直接拷贝到设备端。将第三个参数设置为CL_TRUE,我们将等待该API将数据全部拷贝到设备端之后才返回。

6. 使用OpenCL C代码创建并编译出一个程序

代码列表3.3中的向量相加内核存储在一个字符数组中,programSource,当可以用来创建程序对象(之后需要编译)。当我们编译一个程序时,我们需要提供目标设备的信息。

7. 从编译好的OpenCL程序中提取内核

内核通过提供内核函数名,在程序上进行创建。

8. 执行内核

内核创建完毕,数据都已经传输到设备端,数组需要设置到内核的参数上。之后,一条需要执行内核的命令就进入了命令队列。内核的执行方式需要指定的NDRange进行配置。

9. 拷贝输出数据到主机端

10. 释放资源

内核执行完成后,并且输出已经传出到主机端,OpenCL分配的资源需要进行释放。这点和C/C++程序中的内存操作、文件处理以及其他资源的处理,都需要开发者显式释放。OpenCL为不同的对象提供了不同的释放API。OpenCL上下文需要最后释放,因为数组和命令队列都绑定在上下文上。这点与C++删除对象有些相似,成员数组需要在成员释放前释放。

3.6.1 向量相加的完整代码

下面将完整的展示向量相加这个例子。其具有上一节的所有步骤,不过这个例子中使用了第一个平台对象和设备对象。

代码清单3.4 使用C API实现的OpenCL向量相加

Previous3.5 OpenCL内存模型Next3.7 OpenCL C++ Wapper向量加法

Last updated 6 years ago

Was this helpful?