以下内容转自http://ifeve.com/amdahls-law/

阿姆达尔定律可以用来计算处理器平行运算之后效率提升的能力。阿姆达尔定律因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 / 5
= 0.4 + 0.12
= 0.52

阿姆达尔定律图示

为了更好地理解阿姆达尔定律,我会尝试演示这个定定律是如何诞生的。

首先,一个程序可以被分割为两部分,一部分为不可并行部分B,一部分为可并行部分1 – B。如下图:

在顶部被带有分割线的那条直线代表总时间T(1)。

下面你可以看到在并行因子为2的情况下的执行时间:

并行因子为3的情况:

优化算法

从阿姆达尔定律可以看出,程序的可并行化部分可以通过使用更多的硬件(更多的线程或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缓存等)上的一致性可能更好。

30、Java并发性和多线程-阿姆达尔定律的更多相关文章

  1. java 并发性和多线程 -- 读感 (一 线程的基本概念部分)

    1.目录略览      线程的基本概念:介绍线程的优点,代价,并发编程的模型.如何创建运行java 线程.      线程间通讯的机制:竞态条件与临界区,线程安全和共享资源与不可变性.java内存模型 ...

  2. Java 并发和多线程(一) Java并发性和多线程介绍[转]

    作者:Jakob Jenkov 译者:Simon-SZ  校对:方腾飞 http://tutorials.jenkov.com/java-concurrency/index.html 在过去单CPU时 ...

  3. Java并发性和多线程

    Java并发性和多线程介绍   java并发性和多线程介绍: 单个程序内运行多个线程,多任务并发运行 多线程优点: 高效运行,多组件并行.读->操作->写: 程序设计的简单性,遇到多问题, ...

  4. Java并发性和多线程介绍

    java并发性和多线程介绍: 单个程序内运行多个线程,多任务并发运行 多线程优点: 高效运行,多组件并行.读->操作->写: 程序设计的简单性,遇到多问题,多开线程就好: 快速响应,异步式 ...

  5. Java高级教程:Java并发性和多线程

    Java并发性和多线程: (中文,属于人工翻译,高质量):http://ifeve.com/java-concurrency-thread-directory/ (英文):http://tutoria ...

  6. java 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    参考文章:http://ifeve.com/java-concurrency-thread-directory/ 其中的竞态,线程安全,内存模型,线程间的通信,java ThreadLocal类小节部 ...

  7. 【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    原文地址:https://www.cnblogs.com/edenpans/p/6020113.html 参考文章:http://ifeve.com/java-concurrency-thread-d ...

  8. Java 并发性和多线程

    一.介绍 在过去单 CPU 时代,单任务在一个时间点只能执行单一程序.之后发展到多任务阶段,计算机能在同一时间点并行执行多任务或多进程.虽然并不是真正意义上的“同一时间点”,而是多个任务或进程共享一个 ...

  9. 1、Java并发性和多线程-并发性和多线程介绍

    以下内容转自http://ifeve.com/java-concurrency-thread/: 在过去单CPU时代,单任务在一个时间点只能执行单一程序.之后发展到多任务阶段,计算机能在同一时间点并行 ...

随机推荐

  1. ACM_三角形的周长

    三角形的周长 Time Limit: 2000/1000ms (Java/Others) Problem Description: 有n根棍子,棍子i的长度为ai,想要从中选出3根棍子组成周长尽可能长 ...

  2. 所有版本chrome、chromedriver、firefox下载链接

    1. 所有版本chrome下载 是不是很难找到老版本的chrome?博主收集了几个下载chrome老版本的网站,其中哪个下载的是原版的就不得而知了. http://www.slimjet.com/ch ...

  3. RecylerView为item添加点击事件

    RecyclerView侧重的是布局的灵活性,虽说可以替代ListView但是连基本的点击事件都没有,这篇文章就来详细讲解如何为RecyclerView的item添加点击事件. 1 原理: 为Recy ...

  4. windows服务器监控多个tomcat运行状态

     第一步,修改tomcat默认的进程名 因为所有的tomcat项目的进程名默认都叫java.exe,所以需要修改tomcat容器bin目录下的setclasspath.bat.注释掉:(在set前加上 ...

  5. 【Linux】Ubuntu下C语言访问MySQL数据库入门

    使用的系统是Ubuntu 11.10.数据库是MySQL. MySQL数据库环境配置 首先需要安装MySQL客户端和服务器,命令行安装方式为: sudo apt-get install mysql-s ...

  6. python学习小结-字典key,val互换

    第一种,使用压缩器: >>> m = {'a': 1, 'b': 2, 'c': 3, 'd': 4} >>> zip(m.values(), m.keys()) ...

  7. HDU_1227_Fast Food_动态规划

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1227 Fast Food Time Limit: 2000/1000 MS (Java/Others)   ...

  8. JavaScript 中实现 sleep

    来自推特上 Windows 故障分析的笑话 图片来源:me.me 推上看到的笑话,Windows 故障分析的实现. 然后想起来 JavaScript 中如何实现这个 sleep() 函数让代码暂停指定 ...

  9. ThinkPHP---案例2--职员管理功能

    [一]准备工作 (1)创建菜单,修改跳转路径 <li> <a href="javascript:;" class="workerManage" ...

  10. 10Java Server Pages 隐式对象

    Java Server Pages 隐式对象 JSP隐式对象是Web容器加载的一组类的实例,它不像一般的Java对象那样用“new”去获取实例,而是可以直接在JSP页面使用的对象.JSP提供的隐式对象 ...