在计算密集型或者数据密集型的应用场景,多机并行处理是提升性能的常用方法。并行编程不仅仅是一个编程问题,它涉及到数据访问、多机通信和资源调度,应用开发人员不可能从头造轮子解决所有问题,借助于编程框架是不可避免的趋势。究竟框架如何提升并行处理的效能呢?本篇我们聊聊这个话题。
01 并行如何提升计算效率?
1.1 分而治之是王道
计算机算法中常常将一个大问题分解成若干个小问题来解决,这就是所谓的分治法(Divide-Conquer
)。如果不同的小问题可以交由单台机器的N个CPU(泛指逻辑CPU,包括CPU、核或者超线程
),或者更进一步交给多台机器的N个CPU,理想情况下期望的运行时间可能缩短到1/N
。之所以说是理想,是因为实际运行时间由下面几个因素决定:
-
程序的串并行部分比率:程序不可能所有部分都能够并行执行,如果程序的必须串行部分的比例一定时,加速比是有上限的,即不管你堆叠多少CPU参与计算,都不能突破上限。这就是下面的
Amdahl
定律:
由上述公式可知,如果系统中必须有50%的代码串行执行,那么系统的最大加速比为2。
-
交互代价:既然是分治,有分解(
Divide
),必然有合并(Conquer
)。合并意味着多个并行的子任务结束后需要交互,可能是汇总结果,也可能是重新分割数据。这中间有可能产生一部分串行,也有可能串行时间很短,但是通信代价很大,例如消息延迟或者大数据量传输。交互是严重影响性能的因素。很多类型的计算,规模增加到一定程度,性能不增反降,就是因为交互代价占了上风。
1.2 计算机体系提升并行的方式
分布式计算是从并行计算机的时代演化来的。我们花点时间介绍一下传统并行计算机的实现模式,以此为基础理解分布式并行计算会有帮助。笔者认为并行的基础是数据并行。这个数据指文件,也可以是内存或者寄存器的数据。如果没有数据并行,那意味着操作之间或者毫无关系(从而直接分解),或者必须严格串行。如果是后者,就不可能有并行可言。
在传统的计算机体系中,数据并行有两种实现路径: