您現在的位置是:首頁 > 寵物首頁寵物

CPU 核數與執行緒數有什麼關係?

由 架構師之道 發表于 寵物2021-10-03
簡介總結執行緒數和CPU核心數可以沒有任何關聯,如果在使用執行緒時僅僅針對上述提到的幾個簡單場景,那麼你根本不需要關心CPU是單核還是多核

電腦多核是什麼意思

大廚與菜譜

你沒猜錯,做菜之前先去下一份菜譜,照著菜譜一步步來:起鍋燒油、蔥薑蒜末下鍋爆香、倒入切好的食材、大火翻炒、加入適量醬油、加入適量鹽、繼續翻炒、出鍋嘍!

CPU 核數與執行緒數有什麼關係?

這樣一道色香味俱佳的小炒大功告成,裝盤端出來拿起筷子一嘗,難吃死了

CPU 核數與執行緒數有什麼關係?

火候有點過,醬油加的有點少,鹽加多了,中餐裡的“火候”以及“適量”是最為神秘的存在,可以意會不可言傳。因此相對肯德基麥當勞之類的標準工業品,中餐更像是藝術。每個人炒出來的菜味道都不一樣,顯然嘛,每個人對火候以及適量的理解是不一樣的。

對不起,跑題了

CPU 核數與執行緒數有什麼關係?

雖然小風哥我廚藝不怎麼樣,但輸廚藝不能輸氣場,有時我會幾樣一起來,這邊炒著A菜,那邊炒著B菜。

也就是說,我可以同時按照兩份菜譜去做飯,如果小風哥足夠快,那麼我可以同時炒 N 樣菜。

炒菜與執行緒

實際上CPU和廚師一樣,都是按照菜譜(機器指令)去執行某個動作,

從作業系統的角度講當CPU切換回使用者態後,CPU執行的一段指令就是執行緒,或者說屬於某個執行緒

CPU 核數與執行緒數有什麼關係?

這和炒菜一樣,我可以按照菜譜抄魚香肉絲,那麼炒菜時這就是魚香肉絲線程;我可以按照菜譜抄宮保雞丁,那麼炒菜時這就是宮保雞丁執行緒。

廚師個數就好比CPU核心數,炒菜的樣數就好比執行緒數,這時我問你,你覺得廚師的個數和可以同時抄幾樣菜有關係嗎?

答案當然是沒有。

CPU的核心數和執行緒個數沒有什麼必然的關係

單個核心上可以跑任意多個執行緒,只要你的記憶體夠就行;計算機系統內也可以有任意多核數,只要你有錢就行。

看到這個答案你是不是覺得有點疑惑、有點疑問、有點不明所以,這好像和其它人說的不一樣啊!

彆著急,我們慢慢講。

傻傻的CPU

CPU根本不理解自己執行的指令屬於哪個執行緒,CPU也不需要理解這些,

CPU需要做的事情就是根據PC暫存器中的地址從記憶體中取出後執行,其它沒了

CPU 核數與執行緒數有什麼關係?

你看CPU才不管你係統內有多少執行緒。

有多少執行緒是誰需要來關心的呢?是作業系統。

執行緒是作業系統的把戲。

作業系統與多工

很久很久以前,計算機一次只能執行一個任務,你不能像現在這樣在計算機上一邊看電影一邊在下小電影,哦,不對,一邊寫程式碼,一邊下載資料。

要麼你先寫程式碼,寫完程式碼後再去下資料,要麼你先下資料然後再寫程式碼,總之,

這兩個任務不能同時進行

這顯然很不方便,就這樣,多工——Multi-Tasking,誕生了。

CPU 核數與執行緒數有什麼關係?

你CPU不是隻知道執行機器指令嗎?很好,那我作業系統就透過修改你的PC暫存器,讓你CPU執行A任務的機器指令一段時間,然後下一段時間再去執行B任務的機器指令,再然後下一個時間段去執行C任務的機器指令

,由於每一段時間非常少,通常在毫秒級別,那麼在人類看來A、B、C三個任務在“同時”執行。

這就是多工的本質。

程序與執行緒

CPU不知道執行的某一段機器指令屬於A任務還是B任務,只有作業系統知道,同時作業系統還能知道任務A和B任務是否屬於同一個

地址空間

如果屬於同一個地址空間,那麼任務A和任務B就是我們熟悉的“多執行緒”;如果不屬於同一個地址空間,那麼任務A和任務B就是我們熟悉的“多程序”,現在你應該明白這兩個概念了吧。

CPU 核數與執行緒數有什麼關係?

這裡出現了一個有點拗口的名詞,地址空間,Address Space,關於地址空間的概念以及程序執行緒這一部分更加詳細的講解,請參考小風哥的《深入理解作業系統》第7章,關注公眾號“碼農的荒島求生”並回復”作業系統“即可。

值得注意的是,計算機系統還在單核時代就已經有多執行緒的概念了,我們之前說過,即使是單核也可以執行多個執行緒,那麼有的同學可能會有疑問,在單核的系統中開啟多個執行緒有什麼意義嗎?

單核與多執行緒

假設現在有兩個任務,任務A和任務B,每個任務需要的計算時間都是5分鐘,那麼無論是任務A和任務B序列執行還是放到兩個執行緒中並行執行,在單核環境下執行完這兩個任務總需要10分鐘,因此有的同學覺得單核下多執行緒沒什麼用。

實際上,

執行緒這個概念為程式設計師提供了一種程式設計抽象

,我們可以把一項任務進行劃分,然後把每一個子任務放到一個個執行緒中去執行。

CPU 核數與執行緒數有什麼關係?

假如你的程式帶有圖形介面,某個UI元素背後需要的大量運算,這時為了防止執行該運算時UI產生卡頓,那麼可以把這個運算任務放到一個單獨的執行緒中去。

因此如果你的目的是防止當前執行緒因執行某項操作而不得不等待,那麼在這樣的應用場景下,你根本就不需要關心繫統內是單核還是多核以及有多少個核。

阻塞式I/O

這也是使用執行緒的經典場景。

如果沒有執行緒,那麼執行阻塞式I/O時整個程序會被作業系統暫停,但如果你開啟兩個執行緒,其中一個執行緒被阻塞時另一個執行緒依然可以繼續向前推進。

這樣的話你就不需要去使用反人類的非同步IO了。

當然,

這一切的前提是你的場景不涉及高效能以及高併發

,如果涉及的話那這就是另一個話題了,如果你想了解這一話題,關注公眾號“碼農的荒島求生”並回復“高併發”即可。

在這種簡單的場景下,你建立執行緒時也不需要關心繫統中是單核還是多核。

多核時代

實際上,執行緒這個概念是從2003年左右才開始流行的,為什麼?因為這一時期,多核時代到來了。

CPU 核數與執行緒數有什麼關係?

之所以產生多核,是因為單核的效能提升越來越困難了。

儘管採用多程序也可以充分利用多核,但畢竟多程序程式設計是很繁瑣的,這涉及複雜的程序間通訊機制、程序間切換的較高效能損耗、程序間記憶體相互隔離帶來的對記憶體消耗等。

執行緒這個概念很好的解決了上述問題,開始成為多核時代的主角,要想充分利用多核資源,執行緒是程式設計師的首選工具。

真正的並行

有了多核後,執行在兩個執行緒中的任務A和任務B實現了真正的並行。

此前這樣一句話廣為引用,這句話是這麼說的:

threads are for people who can‘t program state machines

“執行緒是為那些不懂狀態機的人準備的”,這句話在單核時代有它的道理,因為在單核時代,所有的任務都不是在同時向前推進,而是“交錯”前進,A前進一點,然後B前進一點,執行緒並不是實現這種“偽並行”唯一的方法,狀態機也可以。

CPU 核數與執行緒數有什麼關係?

但在多核時代,這句話就不再適用了,對於大多數程式設計師來說多程序多執行緒幾乎是充分利用多核資源的唯一方法。

如果你的場景是想充分利用多核,那麼這時你的確需要知道系統內有多少核數,

一般來說你建立的執行緒數需要與核數保持線性關係。

也就是說,如果你的核數翻倍,那麼建立的執行緒數也要翻倍。

需要多少執行緒?

值得注意的是,執行緒不是越多越好。

如果你的執行緒是不涉及任何I/O、沒有任何同步互斥之類的純計算型別,那麼每個核心一個執行緒通常是最佳選擇。但通常來說,執行緒都需要一定的I/O,可能需要一定的同步互斥,那麼這時

適當

增加執行緒可能會提高效能,但當執行緒數量到達一個臨界值後效能開始下降,這時執行緒間切換的開銷將顯著增加。

這裡之所以用適當這個詞,是因為這很難去量化,

只能用你實際的程式根據真正的場景進行測試才能得到這個值

總結

執行緒數和CPU核心數可以沒有任何關聯,如果在使用執行緒時僅僅針對上述提到的幾個簡單場景,那麼你根本不需要關心CPU是單核還是多核。

但當你需要利用執行緒充分發揮多核威力時,通常情況下你建立的執行緒數與核數要保持一種線性關係,最佳係數通常需要測試才能得到。

原文連結:https://mp。weixin。qq。com/s/Tp680dfOB7Zb6xlXSay7XA