使用多線程的利弊

1. Amdahl定律

     一個很簡單的量化公式,用來計算一個程序中串行部分所佔多少對程序加速比的影響或者用來計算計算機硬件配置中某個設備的速度提高能夠將整個系統的速度提高多少。

     假設一個串行程序執行的總時間爲1,不能被並行化的部分佔的時間比例爲p,即串行化的部分爲p,可並行化的時間爲:1-p。如果用n個核用來加速的話,加速比爲:


李超

    如果一個程序中只有50%部分能夠被並行化,那麼即使使用100個核,能達到的最好的加速比爲1.98,即不會達到2.除非n無窮大。

     Amdahl就像克萊姆準則一樣不能用於實際中,因爲很難精確的使用這個公式。我們需要找到程序中所有的串行部分和並行部分。串行部分不僅僅存在於代碼中必需的依賴關係,可能還有底層庫函數中的串行,還有操作系統的串行部分,甚至還有硬件本身的串行部分。

 

2. 異步應用程序的實現方法

     常見的實現方式有:多線程+同步,異步I/O,非阻塞I/O,信號,事件。異步I/O和非阻塞I/O並不是一回事,當然在有些場合下也會混淆使用。一般來說,異步側重於表達並行,兩個執行流可以同時進行。非阻塞一般還包含一個查詢的過程,因爲要查詢所要進行的操作是否完成。

     異步I/O使用起來難度比多線程大,理解和維護起來的難度一般也比多線程麻煩。同樣使用信號也是這個缺點,因爲單個線程可以使用同步的方式,線程之間可以使用信號來通信。這樣就好像一個人同時做很多件事情和一個團隊來協作來完成這些事情的區別一樣。後者的執行邏輯會更加清晰,而且多線程+同步的方式能夠實現所有異步I/O帶來的優勢。

     使用UNIX信號的方式有嚴重的侷限性,因爲收到信號後所有的邏輯放在一個信號處理函數中執行,這並不是信號處理函數設計的初衷。而且,使用信號會顯得程序的組織結構比較混亂,維護起來比較麻煩。

     事件流也是實現異步應用程序的一種方式。一般系統底層會將應用程序收到的各種事件緩衝到一個隊列中,然後又底層負責將各種事件對應到一個回調函數上,串行的處理各個事件,即調用各個回調函數。這種方式的最大缺點就是有些事件的回調函數的執行事件比較長,會導致其他事件不能得到很好地相應。在Windows系統的.NET架構上,事件+回調函數是使用的比較多的一種方式。事件流的缺點在於其處理的順序性。當然事件流+回調函數+多線程是一種不錯的選擇。

 

3. 編程模型

     各個編程模型的計算能力是等價的,但是對問題抽象層次是不同的。彙編語言在表示程序的結構方面顯得比較笨拙,但是使用C語言就將程序的設計結構顯式的表現出來了。使用C語言進行數據封裝和多態處理顯得很笨拙,使用C++就能很好地處理這個問題。使用關係數據庫在解決大規模數據問題上顯得很笨拙,使用Map-Reduce就能很好的處理某些問題。非線程代碼不能顯式的表達操作的同步性,使用線程代碼就能很好的表達出這些同步性。線程源代碼讓獨立的模塊或者鬆耦合的模塊更加清楚的表現出來。

     不同的編程模型對應着不同的抽象層次,對於問題域的抽象恰到好處的抽象模型有助於我們解決更復雜的問題。

 

4. 什麼情況下使用線程

     使用線程是有代價的,如果程序是計算密集型且每一步都有依賴,那麼使用線程反而會導致效率下降,因爲多個線程之間需要切換,還要負責維護鎖,信號量等設施。對於可並行的計算密集型問題和I/O與計算可重疊的問題使用多線程一般會達到顯著的效果。程序中有多個可併發的模塊的時候,使用線程也能提高程序的響應速度。

原文:使用多線程的利弊

發佈了16 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章