第一章 Opencl介绍
1、什么是opencl
OpenCL是面向由CPU、GPU和其他处理器组合构成的计算机进行编程的行业标准框架.
2、多核的未来,异构平台
cpu中门切换消耗的能量为电容©乘以电压(V)的平方.这些门在1秒内切换的次数等于频率.一个微处理器的功耗计算为P=C V^2 f.
在执行指令一样的情况下,双核处理器中的功耗是单核处理器的0.396倍.
低频率运行的多核在功耗效能上会显著提高.
移动设备非常依赖多核,前面说过,多核设备比较省电,移动设备中电量的节省至关重要.
3、多核世界中的软件
我们将要考虑两个并行程序设计模型:任务并行和数据并行.
OpenCL必须同时支持任务并行和数据并行.
4、OpenCL的概念基础
1、面向异构平台的应用都必须完成一下步骤
1、发现构成异构系统的组件
2、探查这些组件的特性,使软件能够适应不同硬件单元的特定特性.
3、创建将在平台上运行的指令快(内核)
4、建立并管理计算中涉及的内存对象
5、在系统中正确的组件上按正确的顺序执行内核.
6、收集最终结果
2、opencl四大模型
- 平台模型 :异构系统的高层描述.
- 执行模型 :指令流在异构平台上执行的抽象表示.
- 内存模型 :OpenCL中内存区域集合以及一个OpenCL计算期间这些内存区域如何交互.
- 编程模型 :程序员设计算法来实现一个应用时使用的高层抽象.
1、平台模型
OpenCL平台总是包括一个宿主机(host).
宿主机与OpenCL程序外部的环境交互,包括I/O或与程序用户的交互.
宿主机与一个或者多个OpenCL设备连接.
设备就是执行指令流(内核)的地方,因OpenCL设备通常称为计算设备.
设备可以是CPU、GPU、DSP或硬件提供以及OpenCL开发商支持的任何其他处理器.
DSP:是一种独特的微处理器,是以数字信号来处理大量信息的器件.
其工作原理是接受模拟信号,转换为0或1的数字信号,再对数字信号进行修改、删除、强化,并在其他系统芯片中把数字数据编译回模拟数据或实际环境格式.
它不仅具有可编程性,而且其实时运行速度可以达到每秒数以千万条复杂指令程序,远远超过通用微处理器,是数字化电子世界中日益重要的电脑芯片.
它的两大特色是:强大数据处理能力和高运行速度.
总结:OpenCL平台模型包括一个宿主机以及一个或者多个OpenCL设备.各个OpenCL设备有一个或者多个计算单元,其中哥哥计算单元包括一个或者多个处理单元.
2、执行模型
OpenCL应用由两个不同的部分组成:一个宿主机程序以及一个或者多个内核组成的集合.
宿主机程序在宿主机上运行.
内核在OpenCL设备上执行.
(1)、OpenCL定义了两类内核:
- OpenCL内核 :用OpenCL C编程语言编写并用OpenCL编译器编译的函数.所有OpenCL实现都必须支持OpenCL内核.
- 原生内核 :OpenCL之外创建的函数,在OpenCL中可以通过一个函数指针来访问.这些函数可以是宿主机源码代码中定义的函数,或者是从专用库导出的函数.执行原生内核的能力是OpenCL的一个可选的功能,原生内核的语义依赖于具体实现.
OpenCL执行模型定义了内核如何执行.
(2)、内核如何在OpenCL设备上执行
内核在宿主机上定义.
执行内核的各个实例称为一个工作项(work-item),工作项由它在索引空间中的坐标来标识,这些坐标就是工作工作项的全局ID.
工作项组织成为工作组(work-group).
工作组提供了对索引空间更粗粒度的分解,跨越整个全局索引空间.
为工作组指定一个唯一的ID,这个ID与工作项使用的索引空间有相同的维度.
为工作项指定一个局部ID,这个局部ID在工作组中是唯一的,这样就能由其全部ID或者有其局部ID和工作组唯一地表示一个工作项.
给定工作组中的工作项会在一个计算单元的处理单元上并发执行.
索引空间是一个N维的值网络,也称之为NDRang.N维索引空间中的N可以是1、2或3.
载一个OpenCL程序中,NDRang由一个长度为N的整数数组定义,N指定索引空间各维度的大小.
3、上下文
宿主机的第一个任务是为OpenCL应用定义上下文.
上下文定义了一个环境,内核就在这个环境中定义和执行.
有以下资源定义上下文:
- 设备(decive):宿主机使用的OpenCL设备集合.
- 内核(kernel):在OpenCL设备上运行的OpenCL函数.
- 程序对象(program object):实现内核的程序源代码和可执行文件.
- 内存对象(memory object):内存中对OpenCL设备可见的一组对象,包含可以由内核实例处理的值.
上下文由宿主机使用OpenCL API函数创建和管理.
上下文包括一个或者多个程序对象(program object),程序对象包含内核的代码.
可以把程序对象想象成一个动态库,可以从中取出内核使用的函数.
程序对象会在运行时由宿主机程序构建.
总结:上写文就是OpenCL设备、程序对象、内核以及内核在执行时使用的内存对象.
4、命令队列
宿主机与OpenCL设备之间的交互是通过命令完成的,这些命令有宿主机提交给命令队列(command-queue).
这些命令会在命令队列中等待,直到在OpenCL设备上执行.
OpenCL支持三种类型的命令:
- 内核执行命令
- 内存命令
- 同步命令
命令总是与宿主机程序异步执行.
宿主机程序向命令队列提交命令,然后继续工作,而不必等待命令完成.
如果有必要让宿主机等待一个命令,可以利用一个同步命令闲式地建立这个约束.
一个队列中命令执行时可以有一下两种模式:
- 有序执行:命令按顺序发出,一个执行完后在执行下一个.
- 乱序执行:命令按顺序发出,但是下一个命令执行之前不会等待前一个命令完成.
3、内存模型
OpenCL定义了两种类型的内存对象:缓冲区对象(buffer object)和图像对象(image object).
缓冲区对象就是内核可用的一个连续的内存区.
图像对象仅限于存储对象.
OpenCL内存模型定义了5种不同的内存区域:
- 宿主机内存(host memory):这个内存区域只对宿主机可见.
- 全局内存(global memory):这个存储区域允许读、写所有工作组中的所有工作项.
- 常量内存(constant memory):全局内存的这个内存区域在执行一个内核期间保持不变.
- 局部内存(local memory):这个内存区域对工作组是局部的.
- 私有内存(private memory):这个内存区域是一个工作项私有的区域.
工作项在处理单元上运行,有其自己的私有空间.工作组在一个计算单元上运行,与该组中的工作项共享一个局部内存区域.OpenCL设备利用宿主机来支持全局内存.
在大多数情况下,宿主机和OpenCL设备内存模型是独立的,它们之间交互有两种方式:显示地复制数据,或者映射和解映射内存对象的内存区域.
Opencl没有在宿主机上规定内存一致性模型.
4、编程模型
OpenCL定义了两种不同的编程模型:任务并行和数据并行.
1、数据并行编程模型
OpenCL提供了层次结构的数据并行性:工作组中工作项的数据并行再加上工作组层次的数据并行OpenCL规范讨论了这种数据并行形式的两个变种.在显示模式中,程序员负责显示地定义工作组的大小.利用第二个模型,隐式模型,程序员只需要定义NDRang空间,由系统选择工作组.
如果内核不包含任何分支语句,那么各个工作项会执行相同的操作,但是会吹丽其全局ID选择的数据项的一个子集.
这种清情况下定义了数据并行模型的一个重要子集,成为单指令多数据(SIMD).
单程序多数据模型,内核中的分支语句可能让各个工作项执行完全不同的操作,尽管各个工作项使用相同的"程序"(内核),但它完成的具体工作可能完全不同.
OpenCL同时支持SIMD和SPMD模型.
2、任务并行编程模型
OpenCL
执行模型被设计为以数据并行作为主要目标.
这个模型还支持大量任务并行算法.
任务并行的三个版本
1、OpenCL将任务定义为单个工作项执行的内核,而不考虑OpenCL应用中其他内核使用的NDRang.当我们希望的并发性来自于任务,就会使用这个任务.
2、内核作为任务提交,利用一个乱序队列同时执行这些任务.
在一个四核CPU上,一个核可能是宿主机,另外三个核配置为一个OpenCL设备中的计算单元.
3、任务使用OpenCL的事件模型连接到一个任务图.
并行算法的限制
OpenCL表述并行性的这些约束进一步限制了工作组之间和内核之间共享数据的方式.
1、前面的内核如果等待来自后面内核的事件,就可能死锁.
2、与一个算法关联的任务图只能有单向边,从任务队列中先入队的节点指向命令队列中后入队的内核.