并行与分布式计算:基本模型与算法设计(一)
介绍
写给P大学子: 由于罗老师的英语太塑料了,我的学术英语也太差了,并分导的课堂上我总是处于游离边缘。因此我特别在学习之余总结了并分导授课的主要内容(内容来自PPT和教材的阅读),以供后人使用。阅读本系列你将获得:
- 罗老师并分导的全部知识点(还有分支去梳理考点噢)
- 所有作业及其详解
- 用半小时完成两小时塑料英语课堂的学习(ppt reader已经很过分了,用的还是塑料英语)
特别说明,由于Lecture1除了speedup怎么算什么solid的东西都没有,在这里就不着重写了
写给其他学习者: 本文及其后续系列是一套详尽的并行计算与分布式计算,openMP及MPI的入门教程
为了方便,下文将MPI与OpenMP并行程序设计:C语言版(By Michael J. Quinn)简称为教材
特别的,对于P大学子,推荐阅读完第三章之后直接跳到第十七章去学OpenMP
Lecture 1 回顾
知识上会这个就够了,第一节课主要讲并分导的motivation,真想了解那些故事就去看书吧
-
其中,是程序可并行的部分(),是程序仅串行的部分()
Lecture 2 编程模型与算法设计的基本原则
并行模型与结构
System Layers
- 并行程序
- 编译器、运行环境
- 操作系统
- 微结构(硬件设备)
三种并行编程模型
三种模型在展示给程序员的程序通讯的抽象结构上有所不同
不同的编程模型会影响程序员编程时的思路
Shared address space(SAS Model)
- 各个线程通过读写共享的变量来实现通讯
- 共享变量就像一个大的公告板
- 几个例子
- Non-uniform Memory Access
Message passing
- 各线程在自己的私有地址空间里运作
- 线程间通过收发消息交互
常用的库:MPI
硬件不需要在整个系统范围内装载和存储跨程序信息,只需要能够交换信息即可
- 注意,既可以在硬件执行共享地址空间的机器上搞message passing的抽象,也可以在不支持共享地址空间的机器上执行SAS
- 程序模型和机器类别的相关性是模糊的,只需要记住什么是编程模型,什么是硬件实现就行
Data parallel
- 历史上的DP是对一个array进行同一操作(例如克雷超级计算机就是一个向量处理器)
- 例如matlab的操作C=A+B,其中A,B,C都是向量
- 现在一般采取SPMD的编程形式
- map(function,collection)
- function独立的处理每一个元素,function可能是一个复杂的逻辑序列(从而用一个统一的function区分处理不同元素)
- 在map结束时,同步是隐含其中的
- 当function已经作用于集合的所有元素,map就返回了
- map(function,collection)
编程模型强加在程序上的结构
SAS:对结构的强制性要求很少
MP:高度结构化的通讯
DP:非常死板的计算结构
- DP程序对同一个集合的不同数据元素都执行相同的功能
现代实践(混合编程模型)
- 比较常见的实例
- 在同一个节点的内部多核之间使用共享地址空间
- 在节点层面使用massage passing
三种机器结构(关于硬件的部分仅需有所了解即可)
机器结构通常反映了硬件设备的能力
机器结构是一种硬件向软件呈现的抽象形式
(我不是很理解,原句为"Abstraction presented by the hardware to low-level software")
下面的东西比较ICS,我反正是不懂
Flynn分类法
- XIYD 即X instruction Y Data,其中X、Y为single或multiple
- 从而有SISD MISD SIMD MIMD四种
SISD
实例:单核计算机——一个数据池,一个指令池,线性的处理任务
SIMD
MISD
MIMD
-
MIMD的进一步细分
- 共享内存的结构
- 分布式内存结构
- 混合型结构
- 格点结构
- 有局域网和/或广域网联接的分布式异构资源
设计原则
增量并行化
- 研究一个串行程序
- 寻找瓶颈和并行化机会
- 尝试使所有处理器开始干活
Foster的设计理念(四步法)
接下来的部分PPT完全照抄了教材
划分
- 将计算和数据分成小模块
- 考虑如何最大化利用数据并行
- 将数据分成小块
- 决定如何将计算与数据结合
- 考虑如何最大化利用任务并行
- 将计算分成小块
- 决定如何将数据与计算结合
- 利用流水线并行性
- 如最大化利用每一个循环
数据划分
- 决定数据应该如何在处理器间分配
- 决定每一个处理器的计算任务
例子:寻找一个数组中的最大值,数组被均分给n-1个处理器,每个处理器找到最大值,将其汇总到最后一个处理器,这个处理器给出最大值
任务划分
- 将计算任务分配给不同处理器
- 决定哪些数据元素应该被哪些处理器读写
例子:GUI的事件处理器
Pipelining(生产线)
- 装配流水线式并行
- 每一个“工人”只干一件事
- 可以想象,每一个人干完自己的加工部分就把东西传给下一个人,然后从上一个人那里拿到材料重复这个过程
例子:3D渲染
在这个例子里,处理N个data sets,需要N+3步(一个处理器只能同时搞一个数据集,故而每个数据集要排队顺次进入生产线)
注意 生产线只能提高产量,不能解决线程间或处理器间交互延迟(这是显然的)
- Initial Interval(II)的限制
-
在上述举例中,四个逻辑单元要流水线式的完成两个数据集的任务,必须让第二个数据集额外等待1 step
-
很显然,当II=1时,总产量将达到最大,但这并不总是可能的
- 在这个例子中,使用1间隔将引发错误(在r*v2和r+v1同时进行了,这就可能引发错误——先加的话结果就错了)
- 第三个处理器加完v1[i-1]第四个处理器开始给r乘v2[i-1],此时第三个处理器也回过头去给r加v1[i]
- 在这个例子中,使用1间隔将引发错误(在r*v2和r+v1同时进行了,这就可能引发错误——先加的话结果就错了)
-
通讯、聚集、映射见第二部分