java架構師成長路線-Java阿姆達爾定律

魯班學院 java架構師成長路線-Java阿姆達爾定律java

阿姆達爾定律能夠用來計算處理器平行運算以後效率提高的能力。阿姆達爾定律因Gene Amdal 在1967年提出這個定律而得名。絕大多數使用並行或併發系統的開發者有一種併發或並行可能會帶來提速的感受,甚至不知道阿姆達爾定律。無論怎樣,瞭解阿姆達爾定律仍是有用的。算法

我會首先以算術的方式介紹阿姆達爾定律定律,而後再用圖表演示一下。緩存

阿姆達爾定律定義網絡

一個程序(或者一個算法)能夠按照是否能夠被並行化分爲下面兩個部分:架構

能夠被並行化的部分併發

不能夠被並行化的部分ide

假設一個程序處理磁盤上的文件。這個程序的一小部分用來掃描路徑和在內存中建立文件目錄。作完這些後,每一個文件交個一個單獨的線程去處理。掃描路徑和建立文件目錄的部分不能夠被並行化,不過處理文件的過程能夠。優化

程序串行(非並行)執行的總時間咱們記爲T。時間T包括不能夠被並行和能夠被並行部分的時間。不能夠被並行的部分咱們記爲B。那麼能夠被並行的部分就是T-B。下面的列表總結了這些定義:線程

T = 串行執行的總時間code

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

阿姆達爾定律圖示

爲了更好地理解阿姆達爾定律,我會嘗試演示這個定定律是如何誕生的。

首先,一個程序能夠被分割爲兩部分,一部分爲不可並行部分B,一部分爲可並行部分1 – B。以下圖:

java架構師成長路線-Java阿姆達爾定律

在頂部被帶有分割線的那條直線表明總時間 T(1)。

下面你能夠看到在並行因子爲2的狀況下的執行時間:

java架構師成長路線-Java阿姆達爾定律

並行因子爲3的狀況:

java架構師成長路線-Java阿姆達爾定律

優化算法

從阿姆達爾定律能夠看出,程序的可並行化部分能夠經過使用更多的硬件(更多的線程或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緩存等)上的一致性可能更好。

相關文章
相關標籤/搜索