您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
AMD OpenCL大学课程(2)
 
译者:迈克老狼2012,火龙果软件 发布于:2014-11-04
   次浏览      
 

1、OpenCL架构

OpenCL可以实现混合设备的并行计算,这些设备包括CPU,GPU,以及其它处理器,比如Cell处理器,DSP等。使用OpenCL编程,可以实现可移植的并行加速代码。[但由于各个OpenCL device不同的硬件性能,可能对于程序的优化还要考虑具体的硬件特性]。

通常OpenCL架构包括四个部分:

1.平台模型(Platform Model)

2.执行模型(Execution Model)

3.内存模型(Memory Model)

4.编程模型(Programming Model)

2、OpenCL平台模型

不同厂商的OpenCL实施定义了不同的OpenCL平台,通过OpenCL平台,主机能够和OpenCL设备之间进行交互操作。现在主要的OpenCL平台有AMD、Nvida,Intel等。OpenCL使用了一种Installable Client Driver模型,这样不同厂商的平台就能够在系统中共存。在我的计算机上就安装有AMD和Intel两个OpenCL Platform[现在的OpenCL driver模型不允许不同厂商的GPU同时运行]。

OpenCL平台通常包括一个主机(Host)和多个OpenCL设备(device),每个OpenCL设备包括一个或多个CU(compute units),每个CU包括又一个或多个PE(process element)。 每个PE都有自己的程序计数器(PC)。主机就是OpenCL运行库宿主设备,在AMD和Nvida的OpenCL平台中,主机一般都指x86 CPU。

对AMD平台来说,所有的CPU是一个设备,CPU的每一个core就是一个CU,而每个GPU都是独立的设备。

3、OpenCL编程的一般步骤

下面我们通过一个实例来了解OpenCL编程的步骤,假设我们用的是AMD OpenCL平台(因为本人的GPU是HD5730),安装了AMD Stream SDK2.6,并在VS2008中设置好了include,lib目录等。

首先我们建立一个控制台程序,最初的代码如下:

#include "stdafx.h"
2: #include <CL/cl.h>
3: #include <stdio.h>
4: #include <stdlib.h>
5:
6: #pragma comment (lib,"OpenCL.lib")
7:
8: int main(int argc, char* argv[])
9: {
10: return 0;
11: }

第一步,我们要选择一个OpenCL平台,所用的函数就是

通常,这个函数要调用2次,第一次得到系统中可使用的平台数目,然后为(Platform)平台对象分配空间,第二次调用就是查询所有的平台,选择自己需要的OpenCL平台。代码比较长,具体可以看下AMD Stream SDK 2.6中的TemplateC例子,里面描述如何构建一个robust的最小OpenCL程序。为了简化代码,使程序看起来不那么繁琐,我直接调用该函数,选取系统中的第一个OpenCL平台,我的系统中安装AMD和Intel两家的平台,第一个平台是AMD的。另外,我也没有增加错误检测之类的代码,但是增加了一个status的变量,通常如果函数执行正确,返回的值是0。

#include "stdafx.h"
2: #include <CL/cl.h>
3: #include <stdio.h>
4: #include <stdlib.h>
5:
6: #pragma comment (lib,"OpenCL.lib")
7:
8: int main(int argc, char* argv[])
9: {
10: cl_uint status;
11: cl_platform_id platform;
12:
13: status = clGetPlatformIDs( 1, &platform, NULL );
14:
15: return 0;
16: }

第二步是得到OpenCL设备,

这个函数通常也是调用2次,第一次查询设备数量,第二次检索得到我们想要的设备。为了简化代码,我们直接指定GPU设备。

#include "stdafx.h"
2: #include <CL/cl.h>
3: #include <stdio.h>
4: #include <stdlib.h>
5:
6: #pragma comment (lib,"OpenCL.lib")
7:
8: int main(int argc, char* argv[])
9: {
10: cl_uint status;
11: cl_platform_id platform;
12:
13: status = clGetPlatformIDs( 1, &platform, NULL );
14:
15: cl_device_id device;
16:
17: clGetDeviceIDs( platform, CL_DEVICE_TYPE_GPU,
18: 1,
19: &device,
20: NULL);
21:
22: return 0;
23: }

下面我们来看下OpenCL中Context的概念:

通常,Context是指管理OpenCL对象和资源的上下文环境。为了管理OpenCL程序,下面的一些对象都要和Context关联起来:

—设备(Devices):执行Kernel程序对象。

—程序对象(Program objects): kernel程序源代码

—Kernels:运行在OpenCL设备上的函数。

—内存对象(Memory objects): device处理的数据对象。

—命令队列(Command queues): 设备之间的交互机制。

注意:创建一个Context的时候,我们必须把一个或多个设备和它关联起来。对于其它的OpenCL资源,它们创建时候,也要和Context关联起来,一般创建这些资源的OpenCL函数的输入参数中,都会有context。

这个函数中指定了和context关联的一个或多个设备对象,properties参数指定了使用的平台,如果为NULL,厂商选择的缺省值被使用,这个函数也提供了一个回调机制给用户提供错误报告。

现在的代码如下:

#include "stdafx.h"
2: #include <CL/cl.h>
3: #include <stdio.h>
4: #include <stdlib.h>
5:
6: #pragma comment (lib,"OpenCL.lib")
7:
8: int main(int argc, char* argv[])
9: {
10: cl_uint status;
11: cl_platform_id platform;
12:
13: status = clGetPlatformIDs( 1, &platform, NULL );
14:
15: cl_device_id device;
16:
17: clGetDeviceIDs( platform, CL_DEVICE_TYPE_GPU,
18: 1,
19: &device,
20: NULL);
21: cl_context context = clCreateContext( NULL,
22: 1,
23: &device,
24:
25:
26: return 0;
27: }

接下来,我们要看下命令队列。在OpenCL中,命令队列就是主机的请求,在设备上执行的一种机制。

在Kernel执行前,我们一般要进行一些内存拷贝的工作,比如把主机内存中的数据传输到设备内存中。

另外要注意的几点就是:对于不同的设备,它们都有自己的独立的命令队列;命令队列中的命令(kernel函数)可能是同步的,也可能是异步的,它们的执行顺序可以是有序的,也可以是乱序的。

命令队列在device和context之间建立了一个连接。

命令队列properties指定以下内容:

1.是否乱序执行(在AMD GPU中,好像现在还不支持乱序执行

2.是否启动profiling。Profiling通过事件机制来得到kernel执行时间等有用的信息,但它本身也会有一些开销。

如下图所示,命令队列把设备和context联系起来,尽管它们之间不是物理连接。

添加命令队列后的代码如下:

#include "stdafx.h"
2: #include <CL/cl.h>
3: #include <stdio.h>
4: #include <stdlib.h>
5:
6: #pragma comment (lib,"OpenCL.lib")
7:
8: int main(int argc, char* argv[])
9: {
10: cl_uint status;
11: cl_platform_id platform;
12:
13: status = clGetPlatformIDs( 1, &platform, NULL );
14:
15: cl_device_id device;
16:
17: clGetDeviceIDs( platform, CL_DEVICE_TYPE_GPU,
18: 1,
19: &device,
20: NULL);
21: cl_context context = clCreateContext( NULL,
22: 1,
23: &device,
24: NULL, NULL, NULL);
25:
26: cl_command_queue queue = clCreateCommandQueue( context,
27: device,
28: CL_QUEUE_PROFILING_ENABLE, NULL );
29:
30: return 0;
31: }
   
次浏览       
相关文章

企业架构、TOGAF与ArchiMate概览
架构师之路-如何做好业务建模?
大型网站电商网站架构案例和技术架构的示例
完整的Archimate视点指南(包括示例)
相关文档

数据中台技术架构方法论与实践
适用ArchiMate、EA 和 iSpace进行企业架构建模
Zachman企业架构框架简介
企业架构让SOA落地
相关课程

云平台与微服务架构设计
中台战略、中台建设与数字商业
亿级用户高并发、高可用系统架构
高可用分布式架构设计与实践
最新活动计划
LLM大模型应用与项目构建 12-26[特惠]
QT应用开发 11-21[线上]
C++高级编程 11-27[北京]
业务建模&领域驱动设计 11-15[北京]
用户研究与用户建模 11-21[北京]
SysML和EA进行系统设计建模 11-28[北京]

专家视角看IT与架构
软件架构设计
面向服务体系架构和业务组件
人人网移动开发架构
架构腐化之谜
谈平台即服务PaaS


面向应用的架构设计实践
单元测试+重构+设计模式
软件架构师—高级实践
软件架构设计方法、案例与实践
嵌入式软件架构设计—高级实践
SOA体系结构实践


锐安科技 软件架构设计方法
成都 嵌入式软件架构设计
上海汽车 嵌入式软件架构设计
北京 软件架构设计
上海 软件架构设计案例与实践
北京 架构设计方法案例与实践
深圳 架构设计方法案例与实践
嵌入式软件架构设计—高级实践
更多...