【轉】淺談多核CPU、多線程、多進程 淺談多核CPU、多線程、多進程

淺談多核CPU、多線程、多進程

1.CPU發展趨勢html

核心數目依舊會愈來愈多,依據摩爾定律,因爲單個核心性能提高有着嚴重的瓶頸問題,普通的桌面PC有望在2017年底2018年初達到24核心(或者16核32線程),咱們如何來面對這突如其來的核心數目的增長?編程也要與時俱進。筆者斗膽預測,CPU各個核心之間的片內總線將會採用4路組相連:),由於全相連太過複雜,單總線又不夠給力。並且應該是非對稱多核處理器,可能其中會混雜幾個DSP處理器或流處理器。程序員

 

2.多線程與並行計算的區別數據庫

(1)多線程的做用不僅是用做並行計算,他還有不少頗有益的做用。編程

還在單核時代,多線程就有很普遍的應用,這時候多線程大多用於下降阻塞(意思是相似於數組

while(1)網絡

{多線程

if(flag==1)架構

break;併發

sleep(1);負載均衡

}

這樣的代碼)帶來的CPU資源閒置,注意這裏沒有浪費CPU資源,去掉sleep(1)就是純浪費了。

阻塞在何時發生呢?通常是等待IO操做(磁盤,數據庫,網絡等等)。此時若是單線程,CPU會幹轉不幹實事(與本程序無關的事情都算不幹實事,由於執行其餘程序對我來講沒意義),效率低下(針對這個程序而言),例如一個IO操做要耗時10毫秒,CPU就會被阻塞接近10毫秒,這是何等的浪費啊!要知道CPU是數着納秒過日子的。

因此這種耗時的IO操做就用一個線程Thread去代爲執行,建立這個線程的函數(代碼)部分不會被IO操做阻塞,繼續幹這個程序中其餘的事情,而不是乾等待(或者去執行其餘程序)。

一樣在這個單核時代,多線程的這個消除阻塞的做用還能夠叫作「併發」,這和並行是有着本質的不一樣的。併發是「僞並行」,看似並行,而實際上仍是一個CPU在執行一切事物,只是切換的太快,咱們無法察覺罷了。例如基於UI的程序(俗話說就是圖形界面),若是你點一個按鈕觸發的事件須要執行10秒鐘,那麼這個程序就會假死,由於程序在忙着執行,沒空搭理用戶的其餘操做;而若是你把這個按鈕觸發的函數賦給一個線程,而後啓動線程去執行,那麼程序就不會假死,繼續相應用戶的其餘操做。可是,隨之而來的就是線程的互斥和同步、死鎖等問題,詳細見有關文獻。

如今是多核時代了,這種線程的互斥和同步問題是更加嚴峻的,單核時代大都算併發,多核時代真的就大爲不一樣,爲何呢?具體細節請參考有關文獻。我這裏簡單解釋一下,之前volatile型變量的使用能夠解決大部分問題,例如多個線程共同訪問一個Flag標誌位,若是是單核併發,基本不會出問題(P.S.在什麼狀況下會出問題呢?Flag有多個,或者是一個數組,這時候只能經過邏輯手段搞定這個問題了,多來幾回空轉無所謂,別出致命問題就行),由於CPU只有一個,同時訪問這個標誌位的只能有一個線程,而多核狀況下就不太同樣了,因此僅僅volatile不太能解決問題,這就要用到具體語言,具體環境中的「信號量」了,Mutex,Monitor,Lock等等,這些類都操做了硬件上的「關中斷」,達到「原語」效果,對臨界區的訪問不被打斷的效果,具體就不解釋了,讀者能夠看看《現代操做系統》。

(2)並行計算還能夠經過其餘手段來得到,而多線程只是其中之一。

其餘手段包括:多進程(這又包括共享存儲區的和分佈式多機,以及混合式的),指令級並行。

ILP(指令級並行),x86架構裏叫SMT(同時多線程),在MIPS架構裏與之對應的是super scalar(超標量)和亂序執行,兩者有區別,但共同點都是能夠達到指令級並行,這是用戶無法控制的,不屬於編程範圍,只能作些有限的優化,而這有限的優化可能只屬於編譯器管轄的範疇,用戶能作的甚少。

(3)典型的適於並行計算的語言

Erlang和MPI:這兩個前者是語言,後者是C++和Fortran的擴展庫,效果是同樣的,利用多進程實現並行計算,Erlang是共享存儲區的,MPI是混合型的。

C#.NET4.0:新版本4.0能夠用少許代碼實現並行For循環,以前版本須要用很繁瑣的代碼才能實現一樣功能。這是利用了多線程實現並行計算。Java和C#3.5都有線程池(ThreadPool),也是不錯的很好用的多線程管理類,能夠方便高效的使用多線程。

CUDA,仍是個初生牛犢,有很大的發展潛力,只不過就目前其應用領域頗有限。其目前只能使用C語言,並且還不是C99,比較低級,不能使用函數指針。我的感受這因爲硬件上天生的侷限性(平均每一個核心可用內存小,與系統內存通信時間長),只適用於作科學計算,靜態圖像處理,視頻編碼解碼,其餘領域,還不如高端CPU。等之後GPU有操做系統了,能充分調度GPU資源了,GPU就能夠當大神了。遊戲中的物理加速,實際上多核CPU也能很好的作到。

其餘語言。。。恩。。留做未來討論。

 

3.線程越多越好嗎?何時纔有必要用多線程?

線程必然不是越多越好,線程切換也是要開銷的,當你增長一個線程的時候,增長的額外開銷要小於該線程可以消除的阻塞時間,這才叫物有所值。

Linux自從2.6內核開始,就會把不一樣的線程交給不一樣的核心去處理。Windows也從NT.4.0開始支持這一特性。

何時該使用多線程呢?這要分四種狀況討論:

a.多核CPU——計算密集型任務。此時要儘可能使用多線程,能夠提升任務執行效率,例如加密解密,數據壓縮解壓縮(視頻、音頻、普通數據),不然只能使一個核心滿載,而其餘核心閒置。

b.單核CPU——計算密集型任務。此時的任務已經把CPU資源100%消耗了,就不必也不可能使用多線程來提升計算效率了;相反,若是要作人機交互,最好仍是要用多線程,避免用戶無法對計算機進行操做。

c.單核CPU——IO密集型任務,使用多線程仍是爲了人機交互方便,

d.多核CPU——IO密集型任務,這就更不用說了,跟單核時候緣由同樣。

 

4.程序員須要掌握的技巧/技術

(1)減小串行化的代碼用以提升效率。這是廢話。

(2)單一的共享數據分佈化:把一個數據複製不少份,讓不一樣線程能夠同時訪問。

(3)負載均衡,分爲靜態的和動態的兩種。具體的參見有關文獻。

相關文章
相關標籤/搜索