為什么說線程太多,cpu切換線程會浪費很多時間?


更正:

線程越多,會耗費越多的內存,在線程切換上,為什么線程越多消耗的時間越長呢?其實單個線程的上下文占用的內存其實是不會隨着線程數量的增多而增多的,線程越多切換越慢是和操作系統的CPU調度器的調度策略有關,目前大部分服務器操作系統的cpu調度器使用的調度策略是“CFS”(CFS是Completely Fair Scheduler簡稱,即完全公平調度器)。該調度器對READY的線程使用紅黑樹組織起來,在CPU調度的時候,會從這個紅黑樹里面根據每個線程的虛擬時鍾-virtual runtime(vruntime)來選擇一個線程執行。所以如果線程越多的話,紅黑樹就越大,樹節點越多,查詢就越慢,類似mysql索引的b+樹,數量越大,查詢速度越慢。

 

問題1:

假如有一個計算任務,計算1-100的和,每10個數相加,需要占用一個cpu時間片(1s)。如果起一個線程(模擬沒有線程切換),完成任務需要多長時間?如果起5個線程,完成任務需要消耗多久時間?如果起20個線程,完成任務需要多長時間?如果起20個線程呢?20個線程呢?50個線程呢?
假設1:cpu是單核cpu
假設2:每個線程的優先級一樣。
假設3:cpu在兩個線程之間切換的時間消耗是0.1s。
 
答:
1.如果起1個線程(模擬沒有線程切換)就要消耗10s的cpu時間能完成任務。
2.如果起5個線程,每個線程處理20個數相加,所以要占用2個cpu時間片,即10s,cpu要切換9次,即0.9s,總耗時10s+0.9s=10.9s;
3.如果起10個線程,每個線程處理10個數相加,要消耗1個cpu時間,即10s,cpu要切換9次,即0.9s,總耗時10s+0.9s=10.9s。
4.如果起20個線程,每個線程處理5個數相加,占用0.5個時間片,即消耗10s,cpu要切換19次,即1.9s,總耗時10s+1.9s=11.9s。
5.如果起50個線程,每個線程處理2個數相加,占用0.2個時間片,即消耗10s,cpu要切換50次,即5s,總耗時10s+5s=15s。
 
總結:1個線程最快,起5個線程和10個線程的耗時是一樣的,20個線程會更慢,所以線程數不是越多越好。
 
問題2:
 
假如有一個計算任務,計算1-100的和,每10個數相加,需要占用一個cpu時間片(1s),同時要在本地文件(模擬io阻塞)記一次數,會阻塞2s。如果起1個線程,完成任務需要耗時多少?如果起5個線程,完成任務需要消耗多久時間?如果起10個線程,完成任務需要多長時間?如果起20個線程呢?50個線程呢?
假設1:cpu是單核cpu
假設2:每個線程的優先級一樣。
假設3:cpu在兩個線程之間切換的時間消耗是0.1s。
 
答:
1.如果起1個線程(模擬沒有線程切換)處理數字相加需要消耗10s,寫文件(阻塞)要消耗20s,總共需要消耗10s+20s=30s。
2.如果起5個線程,每個線程處理20個數相加,每個線程處理數字相加要2s,阻塞要4s。第一輪cpu時間片輪轉導致線程切換,每個線程都計算完各自的10個數字,五個線程計算數字要5s,並且cpu切換了4次,切換要用0.4s,所以第一輪耗時5s+0.4s+=5.4s;然后開始第二輪,因為第二輪每個線程都是處理寫文件的事情,那是dma的事情,線程會阻塞出讓cpu,所以cpu直接切換,連續切換四次,加上第一輪到第二輪的切換,一共5次切換,切換占用0.5s,所以第二輪cpu都是耗在線程切換上,第二輪耗時0.5s。然后開始第三輪,這時候第一個線程還要阻塞1.5s(2-0.5=1.5)才能開始執行三輪,所以這1.5s范圍內,cpu是空閑的。過了1.5秒之后,開始第三輪和第四輪,分別和前面的第一輪和第二輪一樣,分別是,第三輪耗時5.4s,第四輪耗時0.5s。但是第四輪第5個線程切換之后,還要等待2s,第五個線程才完成文件io。所以起五個線程,cpu要切換四輪,總消耗5.4s(第一輪)+0.5s(第二輪)+1.5s(等待io)+5.4s(第三輪)+0.5s(第四輪)+2s(io等待)=15.3s。
3.如果起10個線程,每個線程處理10個數相加,要消耗1個cpu時間,即10s,cpu要切換9次,即0.9s,第一輪耗時10s+9s=10.9s;第二輪因為是io阻塞,直接切換,要切換10次,切換耗時1s,然后繼續等待第五個線程的io完成,等待1s(io要2s,切換線程過了1s,2-1=1)即可;所以總耗時是10.9s+1s+1s=12.9s。
4.如果起20個線程,每個線程處理5個數相加,第一輪切換29次線程,切換占用2.9s,計算數字需要10s,每切換兩個線程,就io阻塞一次,ios阻塞10次,最后一次切換線程之后,還要等待最后一個線程的io,要等待2s。所以一共耗時2.9s+10s+2s=14.9s。
5.如果起50個線程,每個線程處理2個數相加,第一輪切換49次線程,切換占用4.9s,每切換5次線程,就io阻塞一次,計算數字要10s,,最后一次切換線程之后,還要等待最后一個線程的io,要等待2s。所以總耗時是:4.9s+10s+2s=16.9s。
 
總結:1個線程最快,起5個線程和10個線程的耗時是一樣的,20個線程會更慢,所以線程數不是越多越好。
 
以下附上兩個自己畫的圖,便於理解:
 

 

 

                    歡迎關注微信公眾號“ismallboy”,請掃碼並關注以下公眾號,並在公眾號下面回復“FGC”,獲得本文最新內容。

                                                           

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM