# 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向量相加


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://chenxiaowei.gitbook.io/heterogeneous-computing-with-opencl2-0/3.0-chinese/3.6-chinese.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
