1. 程式人生 > >執行緒池大小設定,CPU的核心數、執行緒數的關係和區別,同步與堵塞完全是兩碼事

執行緒池大小設定,CPU的核心數、執行緒數的關係和區別,同步與堵塞完全是兩碼事

執行緒池應該設定多少執行緒合適,怎麼樣估算出來。最近接觸到一些相關資料,現作如下總結。

最開始接觸執行緒池的時候,沒有想到就僅僅是設定一個執行緒池的大小居然還有這麼多的學問,汗顏啊。

首先,需要考慮到執行緒池所進行的工作的性質:

  • IO密集型
  • CPU密集型

簡單的分析來看,如果是CPU密集型的任務,我們應該設定數目較小的執行緒數,比如CPU數目加1。如果是IO密集型的任務,則應該設定可能多的執行緒數,由於IO操作不佔用CPU,所以,不能讓CPU閒下來。當然,如果執行緒數目太多,那麼執行緒切換所帶來的開銷又會對系統的響應時間帶來影響。

《linux多執行緒伺服器端程式設計》

中有一個思路,CPU計算和IO的阻抗匹配原則。

如果執行緒池中的執行緒在執行任務時,密集計算所佔的時間比重為P(0<P<=1),而系統一共有C個CPU,為了讓CPU跑滿而又不過載,執行緒池的大小經驗公式 T = C / P。在此,T只是一個參考,考慮到P的估計並不是很準確,T的最佳估值可以上下浮動50%。

這個經驗公式的原理很簡單,T個執行緒,每個執行緒佔用P的CPU時間,如果剛好佔滿C個CPU,那麼必有 T * P = C。

下面驗證一下邊界條件的正確性:

假設C = 8,P = 1.0,執行緒池的任務完全是密集計算,那麼T = 8。只要8個活動執行緒就能讓8個CPU飽和,再多也沒用了,因為CPU資源已經耗光了。

假設C = 8,P = 0.5,執行緒池的任務有一半是計算,有一半在等IO上,那麼T = 16.考慮作業系統能靈活,合理排程sleeping/writing/running執行緒,那麼大概16個“50%繁忙的執行緒”能讓8個CPU忙個不停。啟動更多的執行緒並不能提高吞吐量,反而因為增加上下文切換的開銷而降低效能。

如果P < 0.2,這個公式就不適用了,T可以取一個固定值,比如 5*C。另外公式裡的C不一定是CPU總數,可以是“分配給這項任務的CPU數目”,比如在8核機器上分出4個核來做一項任務,那麼C=4

文章如何合理設定執行緒池大小裡面提到了一個公式:

最佳執行緒數目 = ((執行緒等待時間+執行緒CPU時間)/執行緒CPU時間 )* CPU數目

比如平均每個執行緒CPU執行時間為0.5s,而執行緒等待時間(非CPU執行時間,比如IO)為1.5s,CPU核心數為8,那麼根據上面這個公式估算得到:((0.5+1.5)/0.5)*8=32。這個公式進一步轉化為:

最佳執行緒數目 = (執行緒等待時間與執行緒CPU時間之比 + 1)* CPU數目

可以得出一個結論:
執行緒等待時間所佔比例越高,需要越多執行緒。執行緒CPU時間所佔比例越高,需要越少執行緒。

 

 

 

workQueue:儲存任務的阻塞佇列,與執行緒池的大小有關:

  當執行的執行緒數少於corePoolSize時,在有新任務時直接建立新執行緒來執行任務而無需再進佇列   當執行的執行緒數等於或多於corePoolSize,在有新任務新增時則選加入佇列,不直接建立執行緒   當佇列滿時,在有新任務時就建立新執行緒