本文摘自 葛一鸣 老师的《实战java高并发程序设计》一书。因为觉得写得好就摘下来了
将串行程序改造成并发程序,一般来说可以提高程序的整体性能,但是究竟能提升多少,甚至说究竟是否真的可以提高,还是一个需要研究的问题。目前,主要有两个定律对这个问题进行解答,一个是Amdahl定律,另一个是Gustafson定律。
1.Amdahl定律
Amdahl定律是计算机科学中非常重要的定律。它定义了串行系统并行化后的加速比的计算公式和理论上线。
加速比定义:
加速比 = 优化前系统耗时 / 优化后系统耗时
所谓加速比就是优化前的耗时与优化后耗时的比值。加速比越高,表明优化效果越明显。图1-1 为Amdahl公式推导过程,其中 n 表示处理器个数,T 表示时间,T1 表示优化前耗时(也就是只有 1 个处理器时的耗时),Tn 表示使用 n 个处理器优化后的耗时。F 是程序中只能串行执行的比例。
![](https://i-blog.csdnimg.cn/blog_migrate/3768fc33f637ccae17ef01c7e03dbc25.png)
根据这个公式,如果 cpu 处理器数量趋于无穷,那么加速比与系统的串行化比例成反比,如果系统中必须有 50% 的代码串行执行,那么系统的最大加速比为 2。
假设有一个程序分为以下步骤执行,每个执行步骤花费 100 个单位时间。其中,只有步骤 2 和步骤 5 可以并行,步骤 1、3、4必须串行,如图1-2 所示。在全串行的情况下,系统合计耗时为500个单位时间。
![](https://i-blog.csdnimg.cn/blog_migrate/9e60fe894295f0badff8be272f9310ff.png)
若将步骤 2和步骤 5并行化,假设在双核处理器上,则有如图 1-3所示的处理流程。在这种情况下,步骤 2和步骤 5的耗时将为 50个单位时间。故系统整体耗时为400个单位时间。根据加速比定义有:
加速比 = 优化前系统耗时 / 优化后系统耗时 = 500 / 400 = 1.25
![](https://i-blog.csdnimg.cn/blog_migrate/621e90f4bd672dd191862ba845de97dc.png)
由于 5个步骤中,3个必须串行,因此串行化比例为 3/5 = 0.6,即 F=0.6,且双核处理器的处理器个数N为2.代入加速比公式得:
加速比 = 1/(0.6+(1-0.6) /2) = 1.25
在极端的情况下,假设并行处理器个数无限大,则如图 1-4所示处理过程。步骤 2和步骤 5的执行实现趋于0。即使这样整体系统耗时依然大于300个单位时间。使用加速比公式,N趋于无穷大,有加速比 = 1 / F,且F = 0.6,故有加速比 = 1.67。即加速比的极限为 500/300 = 1.67
![](https://i-blog.csdnimg.cn/blog_migrate/85350a954f831e45d286216d27a7c0c1.png)
由此可见,为了提高系统的速度,仅增加CPU处理器的数量并不一定能起到有效的作用。需要从根本上修改程序的串行行为,提高系统内可并行化的模块比重,在此基础上,合理增加并行处理器数量,才能以最小的投入,得到最大的加速比。
根据Amdahl 定律,使用多核CPU 对系统进行优化,优化的效果取决于CPU的数量,以及系统中串行化程序的比例。CPU 数量越多,串行化比例越低,则优化效果越好。仅提高CPU 数量而不降低程序的串行化比例,也无法提高系统性能。
2.Gustafson定律
Gustafson 定律也试图说明处理器个数、串行化比例和加速比之间的关系,如图2-1所示,但是Gustafson 定律和Amdahl 定律的角度不同。同样,加速比都被定义为优化前的系统耗时除以优化后的系统耗时。
![](https://i-blog.csdnimg.cn/blog_migrate/081c92f6901b6172159a9fb26bc19d75.png)
可以看到,由于切入角度的不同,Gustafson 定律的公式和Amdahl 定律的公式截然不同。从Gustafson 定律中,我们可以更容易的发现,如果串行化比例很小,并行化比例很大,那么加速比就是处理器的个数。只要不断地累加处理器,就能获得更快的速度。
3.是否相互矛盾
Amdahl 定律和Gustafson 定律的结论不同,这是不是说明这两个理论之间有一个是错误的呢?其实不然,两者的差异其实是因为这两个定律对同一个客观事实从不同的角度去审视的结果,他们的侧重点有所不同。
举一个生活中的例子,一辆汽车行驶在60km的路上,你花了一个小时,行驶了30km。无论接下来开多快,整个路程你都不可能达到90km/h的平均速度。图3-1很好的说明了原因。
![](https://i-blog.csdnimg.cn/blog_migrate/6d06a8d5a56eef7299a608c89df5d50a.png)
求解图3-1的方程,你会发现如果想要达到90km/h的时速,那么你从AB中点到达B点的时间会是一个负数,这显然不是一个合理的结论。实际上,如果前半程 30km你使用了一小时,那么即使你从中点到B点使用光速,也 只能把整体的平均时速维持在 60km/h。
也就是说Amdahl 强调:当串行化比例一定时,加速比是有上限的,不管你堆叠多少CPU参与计算,都不能突破上限!
而Gustafson定律的出发点与之不同,对Gustafson定律来说,不管你从A点出发的速度有多慢,只要给你足够的时间和距离,只要你后期的速度比期望快那么一点点,你总是可以把平均速度调整到非常接近那个期望值的。比如,你想要达到均速90km/h,即使在前30km 你的时速只有30km/h ,你只要在后面的速度达到91km/h,给你足够的时间和距离,总有一天可以把均速提高到非常接近90km/h。
因此,Gustafson 定律关心的是:如果可被串行化的代码所占比例足够大,那么加速比就能随着CPU的数量线性增长。
所以这两个定律并不矛盾。从极端的角度来说,如果系统中没有可被并行化的代码(即 F=1),那么对于这两个定律,其加速比都是1 。反之,如果系统中可被并行化代码的比例达到100%,那么这两个定律得到的加速比都是n (处理器个数)。