討論多線程與多核的關係

1.在多核CPU下,同一進程下的多個線程可不可以並行運行,是不是一個進程下的所有線程都在同一個cpu上運行?

http://bbs.csdn.net/topics/270083226

如果是內核線程(就是fork出來的,pthread_create在2.4後最終也用fork,具體參看其實現),那麼可以調度到多cpu,內核支持線程的誘導因素之一就是可以利用多cpu資源進行並行計算;如果是用戶線程,那麼就不能在多cpu上並行計算了,用戶庫線程的弊端之一就是不能利用多cpu資源;具體到調度,就是當內核發現本cpu沒有任何可運行線程時,就會去別的忙cpu上拽幾個下來,當然這是內核自發進行的多cpu調度,作爲用戶也可以自覺地將線程邦定到具體cpu,更加確定的利用多cpu,當然什麼都不是任其發展的,內核不能隨便從哪個忙cpu上拽線程,還要看線程願不願意(參見linux內核函數cpuset_cpus_allowed),另外還要考慮smt(在intel平臺即超線程)的兄弟cpu,還要考慮numa,你總不能讓本地cpu的線程跑到遙遠的cpu上運行吧…..(還有很多好玩的,自己看代碼吧)

以上扯的都是linux的實現,是我對代碼的總結,感興趣可自行閱讀。至於windows平臺,道道就更多了(windows的道道總是能把你搞暈,不過玩玩挺好,挺有趣,比如動態優先級提升之類的),它甚至可以讓內核線程運行在一個專門cpu上,別的用戶線程分享別的cpu(linux也可以做到,但是有意思嗎?)…..

對於運行在多CPU上的LINUX來說,每個CPU有一個自己的調度隊列。當多個調度隊列中的進程數相差超過一定的數值時,內核會自動進行調整,從而使得各CPU上的進程數保持均衡。

另外需要說明的是,Linux下的線程,相當於進程,因爲它在內核中有自己的task_struct。其實線程與進程的唯一差別是,線程沒有自己獨立的虛存空間。也就是說,如果一個進程創建了一個線程,那麼新線程與老的主線程,就相當於兩個共享虛存空間的進程。內核的調度程序是以task_struct爲單位進行調度的。

一個進程中的多個線程可以在多核處理器上的 不同核上運行嗎?

未必,得看操作系統的支持和調度算法

這得看操作系統怎麼管理CPU資源,運行在操作系統上的進程不止一個,每個進程的線程也可能多個。所以操作系統對於是把同一進程的線程分配到不同的CPU,還是在同一個CPU上使用輪訓和調度權限改變來調度,這一切都是由操作系統的調度算法決定的

線程應該是一個併發的概念,不是並行的概念吧,併發是指每一時刻僅有一個線程投入運行,並行就不同了每一刻都有N多的線程在同時運行,共享系統資源,如果線程可以在多處理器上運行的話那就是並行了,如果是這樣的話,應該是硬件CPU的研製跟不上軟件的發展纔對(多加線程提升軟件的性能),但事實並非如此,

2.進程與線程的一個簡單解釋引發的討論

http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html

herodot 說:

進程和線程簡單而基本靠譜的定義如下:
1. 進程:程序的一次執行
2. 線程:CPU的基本調度單位
這兩個概念雖然過於簡單,但是完全可以爲理解OS/線程/進程打下堅實的基礎,我認爲關於進程/線程的探討,無論採用何種方式,都必須以這兩句話爲落腳點,纔算靠譜。
你寫的大多數文章相當出色。在以通俗的方式解釋複雜的概念這方面,尤其出色。但是,我個人的經驗,這種方式比較適合用來解釋一個複雜概念的一個方面,或者從某個角度的理解。想面面俱到的說明白一個複雜的系統,繁瑣枯燥的概念,以及這些概念間的推演幾乎不可避免。坦白說,在實際項目中大量用到線程/進程之前,我看過很多遍相關的概念,也寫過小的示例程序,但真到了用的時候,還是發現之前沒搞明白。
我對進程/線程的理解也很粗淺。個人見解,僅供參考。

viho_he 說

拋開各種技術細節,從應用程序角度講:
1、在單核計算機裏,有一個資源是無法被多個程序並行使用的:cpu。
沒有操作系統的情況下,一個程序一直獨佔着全都cpu。
如果要有兩個任務來共享同一個CPU,程序員就需要仔細地爲程序安排好運行計劃–某時刻cpu和由程序A來獨享,下一時刻cpu由程序B來獨享
而這種安排計劃後來成爲OS的核心組件,被單獨名命爲“scheduler”,即“調度器”,它關心的只是怎樣把單個cpu的運行拆分成一段一段的“運行片”,輪流分給不同的程序去使用,而在宏觀上,因爲分配切換的速度極快,就製造出多程序並行在一個cpu上的假象。
2、在單核計算機裏,有一個資源可以被多個程序共用,然而會引出麻煩:內存。
在一個只有調度器,沒有內存管理組件的操作系統上,程序員需要手工爲每個程序安排運行的空間 – 程序A使用物理地址0x00-0xff,程序B使用物理地址0x100-0x1ff,等等。
然而這樣做有個很大的問題:每個程序都要協調商量好怎樣使用同一個內存上的不同空間,軟件系統和硬件系統千差萬別,使這種定製的方案沒有可行性。
爲了解決這個麻煩,計算機系統引入了“虛擬地址”的概念,從三方面入手來做:
2.1、硬件上,CPU增加了一個專門的模塊叫MMU,負責轉換虛擬地址和物理地址。
2.2、操作系統上,操作系統增加了另一個核心組件:memory management,即內存管理模塊,它管理物理內存、虛擬內存相關的一系列事務。
2.3、應用程序上,發明了一個叫做【進程】的模型,(注意)每個進程都用【完全一樣的】虛擬地址空間,然而經由操作系統和硬件MMU協作,映射到不同的物理地址空間上。不同的【進程】,都有各自獨立的物理內存空間,不用一些特殊手段,是無法訪問別的進程的物理內存的。
3、現在,不同的應用程序,可以不關心底層的物理內存分配,也不關心CPU的協調共享了。然而還有一個問題存在:有一些程序,想要共享CPU,【並且還要共享同樣的物理內存】,這時候,一個叫【線程】的模型就出現了,它們被包裹在進程裏面,在調度器的管理下共享CPu,擁有同樣的虛擬地址空間,同時也共享同一個物理地址空間,然而,它們無法越過包裹自己的進程,去訪問別一個進程的物理地址空間。
4、進程之間怎樣共享同一個物理地址空間呢?不同的系統方法各異,符合posix規範的操作系統都提供了一個接口,叫mmap,可以把一個物理地址空間映射到不同的進程中,由不同的進程來共享。
5、PS:在有的操作系統裏,進程不是調度單位(即不能被調度器使用),線程是最基本的調度單位,調度器只調度線程,不調度進程,比如VxWorks

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