这门课程是由斯坦福大学在今年 4 月份推出的线上课程,主讲人是Reza Zadeh,总体来说主讲人讲解比较幽默,内容也是容易让人听得下去,不是那么晦涩难懂。课程内容分为两个部分:并行计算(parallel computing),分布式计算(distributed computing)。并行计算与分布式计算有啥区别呢?主要的区别在于:并行计算主要是在共享内存情况下的同时计算;而分布式计算则是更多需要考虑网路通信。
并行计算简介
为什么我们要研究并行计算呢?现在 CPU 性能这么强劲,为啥还要费力研究用多个核一起计算呢?主要原因在于 CPU 的性能优化受到以下限制:CPU 的运算会有上限,3 Gigahertz;并且 CPU 的散热也是有限的。但是与之相对的是:RAM,硬盘空间却是处于不断增长的情况。因为硬件制造商开始从开发更快的处理器,转为开发多核处理的系统。由于计算从连续计算变为了并行计算,我们也就需要开始研究并行计算算法。
要研究并行算法,我们首先要明确的一个问题就是我们如何来评估并行算法的效率。通常来说,一个算法的效率可以用完成该算法所需要的操作数目(operation)来评估。但是当我们研究并行算法的时候,情况可就大不一样了。一个高效的并行算法在单个处理器上可能并不高效,反之亦然。所以,为了评估并行算法是否高效,Reza 引入了work-depth,并且介绍了算法如何设计来优化该目标。
Parallel RAM 模型
第一个要介绍的并行算法是:Parallel RAM(PRAM)。RAM(Random Access Memory) 模型是典型的连续模型, 在 RAM 中,对于一个特定的内存单元
,有处理器 。处理器 可以在常数时间内,读取或写入内存中的任意位置。当我们研究 PRAM,它可能有多种不同的变化了。PRAM 与 RAM 的不同在于,处理器变为多个,内存还是那一块,那么这会有什么变化呢?我们可能面临多个处理器同时访问一块内存的情况,这可以分为以下几种情况:
一般来说,这些情况中最常用的是同时读取,独占写入的情况。当然也会有同时写入的情况。
在处理同时写入情况时,需要仔细考虑多个处理器同时向同一内存的同一区域写入有冲突的情况,一般有以下方式来解决同时写入:
Undefined/Garbage: 机器可能会挂掉或者写入的结果被当成垃圾处理Arbitrary: 没有事先定义好的确定处理器写入优先级的规则,每次都随机选取处理器进行写入Priority: 事先确定好各处理器写入的顺序Combination: 根据写入值来确定写入的顺序(比如最大值,负数等优先写入),与 Priority 方式不同点在于,这个利用了写入值来确定写入顺序,而前者则是根据处理器来决定顺序
通用 Parallel RAM 模型
Parallel RAM 模型主要有以下两类:
在实际使用的过程中,处理器与内存之间可能还存在额外的 cache 层。
work 与 depth 的实际意义
work :算法的 work 是指完成算法消耗的时间乘以完成算法消耗的处理器的数目
depth:在并行算法中,我们需要等待计算最缓慢的处理器完成计算,整个计算过程才算真正完成,这个时间就是算法的 depth
对于同样一个算法,如果该算法在单个处理器上进行处理,其耗时定义为:
;如果在 个处理器上进行处理,其耗时定义为: 。理想情况下,如果总任务被均分为 部分,并且各个部分速度都相同,所以 满足以下条件:,
这也是分布式算法希望达到的下界。
算法的 DAG 表示
我们可以使用一个有向无环图来表示算法中不同操作之间的依赖关系。可以这样来将算法构建为 DAG: 当节点
是节点 的输入时,用一个从 出发到 的边来表示。最终构成的图不保证一定是完全连接的,因为有一些计算可能与其它部分完全独立。
我们可以把 DAG 看成是一棵树,它的 root 的 depth 是 0,root 的 children 的 depth 是 1,以此类推。将
定义为树的第 层所含有的操作的数目,同一层的操作之间没有依赖关系因此它们可以同时计算。不同层之间的操作不能同时计算。如果要计算当前层的操作,需要等待它所有的 children 操作都计算完成才可以进行。对于连续算法来讲,完成算法所需花费的时间就是树中所有节点的总和,所以我们可以把work定义为:
那么当我们拥有无限的处理器的时候,执行算法的耗时是多少呢?耗时就是算法的depth。定义如下:
Brent's 定理
定义:假设算法的各过程是最优调度的