阿姆达尔定律

原文地址 作者:Jakob Jenkov  译者:张坤

阿姆达尔定律可以用来计算处理器平行运算之后效率提升的能力。阿姆达尔定律因Gene Amdal 在1967年提出这个定律而得名。绝大多数使用并行或并发系统的开发者有一种并发或并行可能会带来提速的感觉,甚至不知道阿姆达尔定律。不管怎样,了解阿姆达尔定律还是有用的。

我会首先以算术的方式介绍阿姆达尔定律定律,然后再用图表演示一下。

阿姆达尔定律定义

一个程序(或者一个算法)可以按照是否可以被并行化分为下面两个部分:

  • 可以被并行化的部分
  • 不可以被并行化的部分

假设一个程序处理磁盘上的文件。这个程序的一小部分用来扫描路径和在内存中创建文件目录。做完这些后,每个文件交个一个单独的线程去处理。扫描路径和创建文件目录的部分不可以被并行化,不过处理文件的过程可以。

程序串行(非并行)执行的总时间我们记为T。时间T包括不可以被并行和可以被并行部分的时间。不可以被并行的部分我们记为B。那么可以被并行的部分就是T-B。下面的列表总结了这些定义:

  • T = 串行执行的总时间
  • B = 不可以并行的总时间
  • T- B = 并行部分的总时间

从上面可以得出:

T = B + (T – B)

首先,这个看起来可能有一点奇怪,程序的可并行部分在上面这个公式中并没有自己的标识。然而,由于这个公式中可并行可以用总时间T 和 B(不可并行部分)表示出来,这个公式实际上已经从概念上得到了简化,也即是指以这种方式减少了变量的个数。

T- B 是可并行化的部分,以并行的方式执行可以提高程序的运行速度。可以提速多少取决于有多少线程或者多少个CPU来执行。线程或者CPU的个数我们记为N。可并行化部分被执行的最快时间可以通过下面的公式计算出来:

(T – B ) / N

或者通过这种方式

(1 / N) * (T – B)

维基中使用的是第二种方式。

根据阿姆达尔定律,当一个程序的可并行部分使用N个线程或CPU执行时,执行的总时间为:

T(N) = B + ( T – B ) / N

T(N)指的是在并行因子为N时的总执行时间。因此,T(1)就执行在并行因子为1时程序的总执行时间。使用T(1)代替T,阿姆达尔定律定律看起来像这样:

T(N) = B + (T(1) – B) / N

表达的意思都是是一样的。

一个计算例子

为了更好的理解阿姆达尔定律,让我们来看一个计算的例子。执行一个程序的总时间设为1.程序的不可并行化占40%,按总时间1计算,就是0.4.可并行部分就是1 – 0.4 = 0.6.

在并行因子为2的情况下,程序的执行时间将会是:

T(2) = 0.4 + ( 1 - 0.4 ) / 2
 = 0.4 + 0.6 / 2
 = 0.4 + 0.3
 = 0.7

在并行因子为5的情况下,程序的执行时间将会是:

T(5) = 0.4 + ( 1 - 0.4 ) / 5
 = 0.4 + 0.6 / 6
 = 0.4 + 0.12
 = 0.52


优化算法

从阿姆达尔定律可以看出,程序的可并行化部分可以通过使用更多的硬件(更多的线程或CPU)运行更快。对于不可并行化的部分,只能通过优化代码来达到提速的目的。因此,你可以通过优化不可并行化部分来提高你的程序的运行速度和并行能力。你可以对不可并行化在算法上做一点改动,如果有可能,你也可以把一些移到可并行化放的部分。

优化串行分量

如果你优化一个程序的串行化部分,你也可以使用阿姆达尔定律来计算程序优化后的执行时间。如果不可并行部分通过一个因子O来优化,那么阿姆达尔定律看起来就像这样:

T(O, N) = B / O + (1 - B / O) / N

记住,现在程序的不可并行化部分占了B / O的时间,所以,可并行化部分就占了1 - B / O的时间.

如果B为0.1,O为2,N为5,计算看起来就像这样:

T(2,5) = 0.4 / 2 + (1 - 0.4 / 2) / 5
   = 0.2 + (1 - 0.4 / 2) / 5
   = 0.2 + (1 - 0.2) / 5
   = 0.2 + 0.8 / 5
   = 0.2 + 0.16
   = 0.36

运行时间 vs. 加速

到目前为止,我们只用阿姆达尔定律计算了一个程序或算法在优化后或者并行化后的执行时间。我们也可以使用阿姆达尔定律计算加速比(speedup),也就是经过优化后或者串行化后的程序或算法比原来快了多少。

如果旧版本的程序或算法的执行时间为T,那么增速比就是:

Speedup = T / T(O , N);

为了计算执行时间,我们常常把T设为1,加速比为原来时间的一个分数。公式大致像下面这样:

Speedup = 1 / T(O,N)




如果我们使用阿姆达尔定律来代替T(O,N),我们可以得到下面的公式:

Speedup = 1 / ( B / O + (1 - B / O) / N)




如果B = 0.4, O = 2, N = 5, 计算变成下面这样:

Speedup = 1 / ( 0.4 / 2 + (1 - 0.4 / 2) / 5)
    = 1 / ( 0.2 + (1 - 0.4 / 2) / 5)
    = 1 / ( 0.2 + (1 - 0.2) / 5 )
    = 1 / ( 0.2 + 0.8 / 5 )
    = 1 / ( 0.2 + 0.16 )
    = 1 / 0.36
    = 2.77777 ...




上面的计算结果可以看出,如果你通过一个因子2来优化不可并行化部分,一个因子5来并行化可并行化部分,这个程序或算法的最新优化版本最多可以比原来的版本快2.77777倍。

测量,不要仅是计算

虽然阿姆达尔定律允许你并行化一个算法的理论加速比,但是不要过度依赖这样的计算。在实际场景中,当你优化或并行化一个算法时,可以有很多的因子可以被考虑进来。

内存的速度,CPU缓存,磁盘,网卡等可能都是一个限制因子。如果一个算法的最新版本是并行化的,但是导致了大量的CPU缓存浪费,你可能不会再使用x N个CPU来获得x N的期望加速。如果你的内存总线(memory bus),磁盘,网卡或者网络连接都处于高负载状态,也是一样的情况。

我们的建议是,使用阿姆达尔定律定律来指导我们优化程序,而不是用来测量优化带来的实际加速比。记住,有时候一个高度串行化的算法胜过一个并行化的算法,因为串行化版本不需要进行协调管理(上下文切换),而且一个单个的CPU在底层硬件工作(CPU管道、CPU缓存等)上的一致性可能更好。

时间: 2024-10-23 15:46:42

阿姆达尔定律的相关文章

Michael I. Jordan联合UC伯克利13位重量级学者:下一代人工智能系统的4大趋势和9大研究课题

Michael I. Jordan 简介: LDA作者,机器学习泰斗,美国科学院/工程院/艺术科学院三院院士,ACM/AAAI Fellow,认知科学最高奖Rumelhart Prize得主,美国人工智能协会的艾伦奖得主,2016年入选最有影响力的计算机科学家. 论文:A Berkeley View of Systems Challenges for AI 论文链接:https://www2.eecs.berkeley.edu/Pubs/TechRpts/2017/EECS-2017-159.p

《C++ AMP:用Visual C++加速大规模并行计算》——1.1 为什么选择GPGPU?什么是异构计算?

1.1 为什么选择GPGPU?什么是异构计算? C++ AMP:用Visual C++加速大规模并行计算 作为开发者,面对周围不断变化的世界,努力调整自己,这种生活我们早已习以为常.IT行业对世界的影响自成体系.我们学习新的语言,使用新的方法,考虑采用新的用户界面,并理所当然地认为它们都能让我们的程序变得更好.为了让下一版比上一版更完善,如果认为采用某种方法会碰壁,我们就会转而换用另外一种方法.而有些开发者现在要使用的最新方法就是异构计算. 本章将回顾计算性能提升的历史,让读者们看看开发者们都碰

为什么响应式编程并非一时之势?

[编者按]本文作者为 David Buschman,文章从程序架构与系统的发展历程出发,逐步论证了为什么响应式编程并非一时之势,而是能带来更快处理速度,更高硬件利用率的未来选择.文章系国内 ITOM 管理平台 OneAPM 编译呈现. 这些年来,程序架构和系统发生了不少变化.大部分情况下,这些变化都跟它们依托的硬件密切相关.软件架构到底是从何处起源,众说纷纭,而且对构架的实际构成部分也有各种定义.本文将从整体化应用的兴起来展开讨论. 摩尔定律 当你的所有资源都在单机上时,把所有的代码存在一个地方

《C++ Concurrency in Action》中文版

2014年马上就到了,借此文感谢各位同学一直以来对并发编程网的支持和厚爱,祝大家新年快乐,并在新的一年里事事马到成功!在新的一年里如果您对并发编程网有什么要求,请只管在本文的回复里告诉我们. 至此新春之际,并发网和人民邮电出版社将在2014年向大家推送<C++ Concurrency in Action>中文版的样章,该书即将登场,而并发编程网让大家先睹为快!本文是第一篇,主要是包含本书的内容介绍,目录和译者介绍.喜欢的话请猛点赞. 内容介绍 本书是一本基于C++11新标准的并发和多线程编程深

Java并发性和多线程介绍目录

Java并发性和多线程介绍 多线程的优点 多线程的代价 并发编程模型 如何创建并运行java线程 竞态条件与临界区 线程安全与共享资源 线程安全及不可变性 Java内存模型 JAVA同步块 线程通信 Java ThreadLocal Thread Signaling (未翻译) 死锁 避免死锁 饥饿和公平 嵌套管程锁死 Slipped Conditions Java中的锁 Java中的读/写锁 重入锁死 信号量 阻塞队列 线程池 CAS 剖析同步器 无阻塞算法 阿姆达尔定律 文章转自 并发编程网

《架构真经:互联网技术架构的设计》水平扩展

本节书摘来自华章出版社<架构真经:互联网技术架构的设计>一书中的第1章,第3节,作者 小象学院 杨 磊,更多章节内容可以访问"华章计算机"公众号查看. 水平扩展 在实践中,我们经常告诉客户,"向上扩展注定会失败".这是因为在超高速增长的环境里,公司计划以水平方式扩展(又称之为向外扩展)至关重要.大多数情况下,这是通过对跨越多个系统工作负荷的拆分或者复制完成的.数据拆分的实施,类似我们在第2章中描述的众多方法中的一种,当超高速增长的公司无法扩展时,他们唯一

JVM堆内存监测的一种方式,性能调优依旧任重道远

上月,由极客邦.InfoQ和听云联合主办2016 APMCon中国应用性能管理大会圆满落下帷幕.会上,Java冠军Martijn Verburg进行了一场Java and the Machine的分享,讨论了为什么数据分析至关重要.他有着十多年Java经验,目前是创业公司jClarity的CEO,jClarity是一款采用统计和机器学习来探究性能问题根源的方案.会后,InfoQ还专访Martijn以进一步了解沟通. JVM堆内存及一种监测方式 在讨论Martijn的团队如何进行堆内存监测之前,我

深入解析SQL Server并行执行原理及实践(下)

谈完并行执行的原理,咱们再来谈谈优化,到底并行执行能给我们带来哪些好处,我们又应该注意什么呢,下面展开.   Amdahl's  Law    再谈并行优化前我想有必要谈谈阿姆达尔定律,可惜老爷子去年已经驾鹤先去了.     其中  P:可以并行的百分比 N:算法并行计算使用的"CPU"    这里我们举个简单的例子,我们来做一份大餐,如图1-1所示:   图1-1   土豆泥,荷兰豆,鸡排还有整体组合各需十分钟.在这里前三个食材是可以共同执行的,也就是说4个步骤中3步可并行 P=3/

谷歌披露了TensorFlow处理器单元架构的细节

本月早些时间谷歌进一步披露了更多关于一年前发布的TPU的细节.TPU项目和团队的高级架构师Norm Jouppi表示,与Nvidia K80和Haswell E5-2699 V3等主流高性能处理器相比,使用TPU执行神经网络计算可以获得成数量级的性能增益.Jouppi说: "据估计TPU会比K80 GPU和Haswell CPU快大概15倍到30倍--在6个神经网络用例中,有4个在TPU上是内存或带宽受限的,假如让TPU使用和K80 GPU一样的内存系统,那它就可以比GPU和CPU快30到50倍