AMD OpenCL大学课程(2)

1、OpenCL架构

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

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

  • 平台模型(Platform Model)
  • 执行模型(Execution Model)
  • 内存模型(Memory Model)
  • 编程模型(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 SDK 2.6,并在VS2008中设置好了include,lib目录等。

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












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

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

















 

第二步是得到OpenCL设备

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
























下面我们来看下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,厂商选择的缺省值被使用,这个函数也提供了一个回调机制给用户提供错误报告。

现在的代码如下:




























接下来,我们要看下命令队列。在OpenCL中,命令队列就是主机的请求,在设备上执行的一种机制。Kernel执行前,我们一般要进行一些内存拷贝的工作,比如把主机内存中的数据传输到设备内存中。

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

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

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

  • 是否乱序执行(在AMD GPU中,好像现在还不支持乱序执行)
  • 是否启动Profiling。Profiling通过事件机制来得到kernel执行时间等有用的信息,但它本身也会有一些开销。

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

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
































 

时间: 2024-08-03 05:43:22

AMD OpenCL大学课程(2)的相关文章

AMD OpenCL大学课程(6)

GPU架构 内容包括: 1.OpenCLspec和多核硬件的对应关系 AMD GPU架构 Nvdia GPU架构 Cell Broadband Engine 2.一些关于OpenCL的特殊主题 OpenCL编译系统 Installable client driver   首先我们可能有疑问,既然OpenCL具有平台无关性,我们为什么还要去研究不同厂商的特殊硬件设备呢? 了解程序中的循环和数据怎样映射到OpenCL Kernel中,便于我们提高代码质量,获得更高的性能. 了解AMD和Nvdia显卡

AMD OpenCL大学课程(5)

OpenCL内存模型     OpenCL的内存模型定义了各种各样内存类型,各种内存模型之间有层级关系.各种内存之间的数据传输必须是显式进行的,比如从host memory到device memory,从global memory到local memory等等.     WorkGroup被映射到硬件的CU上执行(在AMD 5xxx系列显卡上,CU就是simd,一个simd中有16个pe),OpenCL并不提供各个workgroup之间的一致性,如果我们需要在各个workgroup之间共享数据或

AMD OpenCL大学课程(7)

6.Nvdia GPU Femi架构 GTX480-Compute 2.0 capability: 有15个core或者说SM(Streaming Multiprocessors ). 每个SM,一般有32 cuda处理器. 共480个cuda处理器. 带ECC的global memory 每个SM内的线程按32个单位调度执行,称作warp.每个SM内有2个warp发射单元. 一个cuda核由一个ALU和一个FPU组成,FPU是浮点处理单元. SIMT和SIMD SIMT是指单指令.多线程. 硬

AMD OpenCL大学课程(11)

性能优化 1.线程映射    所谓线程映射是指某个线程访问哪一部分数据,其实就是线程id和访问数据之间的对应关系. 合适的线程映射可以充分利用硬件特性,从而提高程序的性能,反之,则会降低性能.    请参考Static Memory Access Pattern Analysis on a Massively Parallel GPU这篇paper,文中讲述线程如何在算法中充分利用线程映射.这是我在google中搜索到的下载地址:http://www.ece.neu.edu/~bjang/pat

AMD OpenCL大学课程(12) 性能优化案例NBody

    本节主要介绍NBody算法的OpenCL性能优化. 1.NBody     NBody系统主要用来通过粒子之间的物理作用力来模拟星系系统.每个粒子表示一个星星,多个粒子之间的相互作用,就呈现出星系的效果.      上图为一个粒子模拟星系的图片:Source: THE GALAXY-CLUSTER-SUPERCLUSTER CONNECTION,http://www.casca.ca/ecass/issues/1997-DS/West/west-bil.html    由于每个粒子之间都

AMD OpenCL大学课程(10)

GPU线程及调度      本节主要讲述OpenCL中的Workgroup如何在硬件设备中被调度执行.同时也会讲一下同一个Workgroup中的workitem,如果它们执行的指令发生diverage(就是执行指令不一致)对性能的影响.学习OpenCL并行编程,不仅仅是对OpenCL Spec本身了解,更重要的是了解OpenCL硬件设备的特性,现阶段来说,主要是了解GPU的的架构特性,这样才能针对硬件特性优化算法.现在OpenCL的Spec是1.1,随着硬件的发展,相信OpenCL会支持更多的并

AMD OpenCL大学课程(13) OpenCL扩展

1.OpenCL扩展      OpenCL扩展是指device支持某种特性,但这中特性并不是OpenCL标准的一部分.通过扩展,厂商可以给device增加一些新的功能,而不用考虑兼容性问题.现在各个厂商在OpenCL的实现中或多或少的使用了自己的扩展.      扩展的类型分为三种: Khronos OpenCL工作组批准的扩展,这种要经过一致性测试,可能会被增加到新版本的OpenCL规范中.这种扩展都以cl_khr作为扩展名. 外部扩展, 以cl_ext为扩展名.这种扩展是由2个或2个以上的

AMD OpenCL大学课程(4)

Kernel对象:     Kernel就是在程序代码中的一个函数,这个函数能在OpenCL设备上执行.一个Kernel对象就是kernel函数以及其相关的输入参数.   Kernel对象通过程序对象以及指定的函数名字创建.注意:函数必须是程序源代码中存在的函数. 运行时编译:     在运行时,编译程序和创建kernel对象是有时间开销的,但这样比较灵活,能够适应不同的OpenCL硬件平台.程序动态编译一般只需一次,而Kernel对象在创建后,可以反复调用.   创建Kernel后,运行Ker

AMD OpenCL大学课程(3)

OpenCL内存对象:       OpenCL内存对象就是一些OpenCL数据,这些数据一般在设备内存中,能够被拷入也能够被拷出.OpenCL内存对象包括buffer对象和image对象. buffer对象:连续的内存块----顺序存储,能够通过指针.行列式等直接访问. image对象:是2维或3维的内存对象,只能通过read_image() 或 write_image()来读取.image对象可以是可读或可写的,但不能同时既可读又可写.        该函数会在指定的context上创建一个