量化模型
量化模型
多线程不意味着并发,但并发肯定是多线程或者多进程;多线程存在的优势是能够更好的利用资源,有更快的请求响应。但是我们也深知一旦进入多线程,附带而来的是更高的编码复杂度,线程设计不当反而会带来更高的切换成本和资源开销。如何衡量多线程带来的效率提升呢,我们需要借助两个定律来衡量。
Amdahl 定律
Amdahl 定律可以用来计算处理器平行运算之后效率提升的能力,其由 Gene Amdal 在 1967 年提出;它描述了在一个系统中,基于可并行化和串行化的组件各自所占的比重,程序通过获得额外的计算资源,理论上能够加速多少。任何程序或算法可以按照是否可以被并行化分为可以被并行化的部分 1 - B
与不可以被并行化的部分 B,那么根据 Amdahl 定律,不同的并行因子的情况下程序的总执行时间的变化如下所示:
如果 F 是必须串行化执行的比重,那么 Amdahl 定律告诉我们,在一个 N 处理器的机器中,我们最多可以加速:
当 N 无限增大趋近无穷时,speedup 的最大值无限趋近 1/F
,这意味着一个程序中如果 50% 的处理都需要串行进行的话,speedup 只能提升 2 倍(不考虑事实上有多少线程可用);如果程序的 10% 需要串行进行,speedup 最多能够提高近 10 倍。
Amdahl 定律同样量化了串行化的效率开销。在拥有 10 个处理器的系统中,程序如果有 10% 是串行化的,那么最多可以加速 5.3 倍(53 %的使用率),在拥有 100 个处理器的系统中,这个数字可以达到 9.2(9 %的使用率)。这使得无效的 CPU 利用永远不可能到达 10 倍。下图展示了随着串行执行和处理器数量变化,处理器最大限度的利用率的曲线。随着处理器数量的增加,我们很明显地看到,即使串行化执行的程度发 生细微的百分比变化,都会大大限制吞吐量随计算资源增加。
Amdahl 定律旨在说明,多核 CPU 对系统进行优化时,优化的效果取决于 CPU 的数量以及系统中的串行化程序的比重;如果仅关注于提高 CPU 数量而不降低程序的串行化比重,也无法提高系统性能。
Gustafson
系统优化某部件所获得的系统性能的改善程度,取决于该部件被使用的频率,或所占总执行时间的比例。
摩尔定律,可伸缩网络和我们所处的困境
1965 年,美国科学家,企业家,英特尔公司创始人之一的戈登·摩尔撰写了一篇长达三页的论文,阐述了电子产品市场对集成电路的整合影响,并预测集成电路中元件数量每年至少增加一倍,而这个过程将持续至少十年。1975 年,他修正了这一预测,指出集成电路中的元件数量每两年翻一番。并持续到 2012 年左右。
一些公司预见摩尔定律预测的速度会放缓,开始研究增加计算能力的替代方法。俗话说,必要性是创新之母,所以多核处理器就是这样诞生了。这看起来像是解决摩尔定律边界问题的一种聪明方式,但是计算机科学家很快就发现自己面临着另一个定律的局限:以 IBM360 系列机的主要设计者阿姆达尔命名的阿姆达尔定律。
阿姆达尔定律指出,系统中对某一部件采用更快执行方式所能获得的系统性能改进程度,取决于这种执行方式被使用的频率,或所占总执行时间的比例。于是阿姆达尔致力于并行处理系统的研究。例如,假设你正在编写一个基于 GUI 的程序:用户将看到一个界面,点击某些按钮,并发生一些事情。这种类型的程序受到管道中一个非常大的连续部分的限制:人员交互。无论为此程序提供多少内核,它总是受限于用户与界面进行交互的速度。
现在考虑一个不同的例子,计算 pi 的数字。多亏了 spigot 算法,我们可以很容易地将其划分为并行任务。在这种情况下,通过为程序提供更多的内核可以获得显著的收益,并且新问题变成了如何组合和存储结果。阿姆达尔定律帮助我们理解这两个问题之间的差异,并帮助我们确定并行化是否是解决系统性能问题的正确方法。对于这种类型的并行问题,建议编写可以水平扩展的应用程序。这意味着可以使用程序的实例,在更多的 CPU 或机器上运行它,虽然这会导致系统的运行时间提高。以这种方式构建程序非常简单,你可以将大块问题发送给应用程序的不同实例。
在 21 世纪初,当一种新的范式开始出现后,横向扩展变得容易得多:云计算。尽管有迹象表明这个词早在 20 世纪 70 年代就已经被使用过了,但是 21 世纪初,这个概念真正在时代精神中扎根。云计算意味着一种新的应用程序部署及扩展的规模和方法。云计算替你配置物理设备,替你安装软件,替你进行维护,这意味着你可以访问庞大的资源池,这些资源池将按需提供到机器中供工作负载使用。物理设备对使用者变得可有可无,并且配备了特别适合他们将要运行的程序的特性。通常(但不总是)这些资源池被托管在其他公司拥有的数据中心中。
这种改变引发了一种新的思考。突然之间,开发人员相对低成本的具备了大规模的计算能力,他们可以用它来解决大型问题。解决方案现在可以轻松跨越许多机器甚至访问到全球。云计算为以前那些只有技术巨头才有资格解决的问题提供了一套全新的低成本解决方案。但云计算也带来了许多新的挑战。调配资源,在设备之间进行通信以及汇总和存储结果都成为需要解决的问题。但其中最困难的是弄清楚如何同时对代码进行建模。部分解决方案可能在不同的机器上运行,这一情况加剧了建模问题时常见的一些问题。这些问题很快就造就了新的解决方案,可伸缩网络。
网络通常希望能够通过添加更多应用程序实例来处理数十万(或更多)的同步工作负载,这使得滚动升级,弹性水平可伸缩体系结构和地理描述等成为必备属性,与此同时,这种解决方案还在编译和容错两方面引入了新的复杂度。因此,我们发现,现代开发人员可能有点不知所措。2005 年,ISO C++标准委员会主席,C++/CLI 首席架构师 Herb Sutter 为 Dobb 博士撰写了一篇文章,标题为“免费午餐结束:软件并发的根本转向”。标题贴切,文章有先见之明。Sutter 最后表示,“我们迫切需要一种更高层次的并发性编程模型,而非当前语言所能提供给我们的。”
如果想明白为什么 Sutter 有如此的“迫切感”,我们必须研究为什么并发很难得到正确的结果。