OpenCL
- OpenCL(开放计算语言)是非盈利性技术联盟Khronos Group管理的异构编程框架
- OpenCL提供了各个设备的设备端语言和主机端控制层两方面的定义
- 设备端语言可以高效映射到众多的内存系统架构上
- 主机端语言的目标是以较低开销来高效管理复杂的并发程序
- OpenCL这种编程模型是
- 跨平台的
- 得到工业界广泛支持的
- 适合开发人员学习和使用的
并行思维
- 经典加速计算方法
- 分治法
- 问题迭代地划分为子问题
- 直到子问题可以在当前计算资源上高效求解
- 散列-收集法
- 输入数据的子集分配给每一个并行计算资源
- 收集计算结果
- 分治法
- 如何从一个应用程序中提取并行性的问题留给程序员解决
- 硬件厂商将GPU和CPU结合在一块硅片上,开启新一代异构计算
- 应用中数据密集型和计算密集型部分称为kernel,由GPU执行
- 主机端CPU可以执行其他任务
- 两个例子
- 两个数组元素相乘
- wordcount
并发模型与并行编程模型
虽然OpenCL支持许多模型,但在实际使用时具体用哪个模型可能受到底层硬件的限制。
-
并发性考虑的是同时发生的两个或两个以上的活动
-
任务可以是并发的,但不一定需要并行执行
-
并行性指的是以提高总体性能为明确目标,并行进行两个或多个任务。
-
并行程序必须具有并发性,但是并发程序并不一定需要具有并行性。
-
并发任务之间的相互依赖性会使一些任务不能并行。
线程和共享内存
一个正在运行中的程序可以由多个子程序组成,它们分别维护着自己独立的控制流,可以并发执行。这些子程序被定义为线程(thread)。
-
线程间的通信通过读写同一个地址空间的内存来完成!
-
每个线程有它们的局部内存池(变量),所有线程都能看到同样的局部变量集
-
内存一致性模型被用来管理内存读取和写入顺序
-
共享内存模型的一个主要特征是程序员不需要考虑数据移动。这使任务之间的数据通信变得容易,并行代码的开发因而也往往可以比较简单。
大部分多核CPU平台支持一种或多种形式的共享内存,OpenCL支持在共享内存的设备上运行。
消息传递通信
消息传递通信模型使我们能详细指定计算时可能会使用内存的一系列任务之间如何进行通信。
- 若干任务可以在同一物理设备上
- 任务通过发送和接受具体消息实现数据交换
- 数据传输需要各个进程执行协同性操作——一个发送操作匹配一个接收操作
消息传递往往由一个独立于硬件的通用库程序来实现发送和接收消息
- MPI是目前最流行的消息传递中间件,这些实现在本质上差别大,难以开发可移植应用程序
不同的并行颗粒
- 颗粒度为计算与通信之比
- 选择正确的并行颗粒度 称为“分块”(chunking)
- 细颗粒度并行
- 计算强度低
- 没有足够的任务来隐藏长时间的异步通信
- 容易通过提供大量可管理的(更小的)工作单元实现负载均衡
- 如果颗粒太细,任务之间通信和同步开销太大,影响算法执行速度
- 粗颗粒度并行
- 计算强度高
- 完整的应用可以作为并行的粒度
- 难以有效实现负载均衡
选择多大的并行颗粒度取决于算法本身和其运行的硬件环境
数据共享和同步
- 并发程序中需要数据共享的情况包括如下:
- 某个任务的输出依赖于另一个任务产生的结果(生产者/消费者或管道执行模型)
- 需要汇集中间计算结果(归约计算)