并行计算中需要解决的问题
- 资源共享
多个线程与多个进程经常使用到同一个资源,产生临界资源,操作系统需要使用信号量来解决,这里不再赘述。 - 并发性
在面临的任务中,有一部分属于“易并行”,例如矩阵乘法,每个计算单元的输出相互独立,这类问题在GPU上可以得到很好的解决并且编程非常简单。对于“不易并行”的任务,各个计算单元之间存在依赖性。CUDA中,涉及块内的通信通过共享内存实现,块间通信需则要全局内存来实现。 - 局部性
程序局部性对于GPU编程也同样重要,由于GPU擅长进行大量重复性工作,这样的话在多次迭代过程中能够大量减少数据在内存和显存之间的传输。对于GPU编程来说,需要编程者自己去管理局部性。
两种并行处理类型
- 基于任务的并行处理
这种并行模式思想是将计算按照任务种类进行拆分,即操作系统的流水线技术,每一个计算的输出是下一个计算的输入,但每一个计算都在一个专有硬件上独立执行。 - 基于数据的并行处理
这种并行模式思想是将数据分割成多个块,让多个计算单元分别执行每个块上的数据,最后再汇总起来。这种并行模式思想是将数据分割成多个块,让多个计算单元分别执行每个块上的数据,最后再汇总起来。
但一般来说,CPU擅长第一种并行处理模式,GPU擅长第二种模式
几个并行处理策略
- 对于循环的处理
首先尝试消除循环每次迭代之间的依赖,如果消除不了,则通常将循环分解成若干个块,在每个块内尝试迭代并行执行。 - 派生/汇集模型
该模式通常针对一种串行代码,但是代码中的某一部分是可以并行的。在可以并行的阶段,派生出额外的计算单元并列执行,最后再将其汇总。这种模式通常用于并发事件事先不确定的情况。 - 分条/分块模式
对于特别庞大的数据任务,可以将数据分为几个块来进行并行计算。 - 分而治之
绝大多数的递归算法,比如快排,都可以转换为迭代模型,而迭代模型能够映射到CPU编程绝大多数的递归算法,比如快排,都可以转换为迭代模型,而迭代模型能够映射到CPU编程
ShaneCook, 库克, 苏统华,等. CUDA并行程序设计:GPU编程指南[M]. 机械工业出版社, 2014.