天天看點

IO密集型和CPU密集型如何區分

CPU 密集型

CPU密集型也叫計算密集型,指的是系統的硬碟、記憶體性能相對CPU要好很多,此時,系統運作大部分的狀況是CPU Loading 100%,CPU要讀/寫I/O(硬碟/記憶體),I/O在很短的時間就可以完成,而CPU還有許多運算要處理,CPU Loading很高。

IO密集型和CPU密集型如何區分

比如說要計算1+2+3+…+ 1億、計算圓周率後幾十位、資料分析。都是屬于CPU密集型程式。

此類程式運作的過程中,CPU占用率一般都很高。

假如在單核CPU情況下,線程池有6個線程,但是由于是單核CPU,是以同一時間隻能運作一個線程,考慮到線程之間還有上下文切換的時間消耗,還不如單個線程執行高效。

是以!!!單核CPU處理CPU密集型程式,就不要使用多線程了。

假如是6個核心的CPU,理論上運作速度可以提升6倍。每個線程都有 CPU 來運作,并不會發生等待 CPU 時間片的情況,也沒有線程切換的開銷。

是以!!!多核CPU處理CPU密集型程式才合适,而且中間可能沒有線程的上下文切換(一個核心處理一個線程)。

簡單的說,就是需要CPU瘋狂的計算。

IO密集型

IO密集型指的是系統的CPU性能相對硬碟、記憶體要好很多,此時,系統運作,大部分的狀況是CPU在等I/O (硬碟/記憶體) 的讀/寫操作,但CPU的使用率不高。

IO密集型和CPU密集型如何區分

是以用腳本語言像python去做I/O密集型操作,效率就很快。

簡單的說,就是需要大量的輸入輸出,例如讀檔案、寫檔案、傳輸檔案、網絡請求。

差別和使用:

計算密集型任務的特點是要進行大量的計算,消耗CPU資源,比如計算圓周率、對視訊進行高清解碼等等,全靠CPU的運算能力。這種計算密集型任務雖然也可以用多任務完成,但是任務越多,花在任務切換的時間就越多,CPU執行任務的效率就越低,是以,要最高效地利用CPU,計算密集型任務同時進行的數量應當等于CPU的核心數。

一般來說:計算型代碼、Bitmap轉換、Gson轉換等

計算密集型任務的特點是要進行大量的計算,消耗CPU資源,比如計算圓周率、對視訊進行高清解碼等等,全靠CPU的運算能力。

這種計算密集型任務雖然也可以用多任務完成,但是,任務越多,花在任務切換的時間就越多,CPU執行任務的效率就越低,

是以,要最高效地利用CPU,計算密集型任務同時進行的數量應當等于CPU的核心數。

計算密集型任務由于主要消耗CPU資源,是以,代碼運作效率至關重要。Python這樣的腳本語言運作效率很低,完全不适合計算密集型任務。對于計算密集型任務,最好用C語言編寫。

第二種任務的類型是IO密集型,涉及到網絡、磁盤IO的任務都是IO密集型任務,這類任務的特點是CPU消耗很少,任務的大部分時間都在等待IO操作完成(因為IO的速度遠遠低于CPU和記憶體的速度)。對于IO密集型任務,任務越多,CPU效率越高,但也有一個限度。常見的大部分任務都是IO密集型任務,比如Web應用。

一般來說:檔案讀寫、DB讀寫、網絡請求等

第二種任務的類型是IO密集型,涉及到網絡、磁盤IO的任務都是IO密集型任務,這類任務的特點是CPU消耗很少,

任務的大部分時間都在等待IO操作完成(因為IO的速度遠遠低于CPU和記憶體的速度)。

對于IO密集型任務,任務越多,CPU效率越高,但也有一個限度。常見的大部分任務都是IO密集型任務,比如Web應用。

IO密集型任務執行期間,99%的時間都花在IO上,花在CPU上的時間很少,是以,用運作速度極快的C語言替換用Python這樣運作速度極低的腳本語言,完全無法提升運作效率。對于IO密集型任務,最合适的語言就是開發效率最高(代碼量最少)的語言,腳本語言是首選,C語言最差。

如何确定線程池大小?

線程數不是越多越好。

由于CPU的核心數有限,線程之間切換也需要開銷,頻繁的切換上下文會使性能降低,适得其反。

IO密集型和CPU密集型如何區分

簡單的總結就是:

Ncpu 表示 核心數。如果是CPU密集型任務,就需要盡量壓榨CPU,參考值可以設為 Ncpu+1

如果是IO密集型任務,參考值可以設定為 2 * Ncpu

上面兩個公式為什麼是Ncpu+1 呢,而不是Ncpu+2 呢,為什麼不是3 * Ncpu 呢?

這樣來計算線程池的線程數目的:

一個基準負載下,使用 幾種不同大小的線程池運作你的應用程式,并觀察CPU使用率的水準。給定下列定義:

IO密集型和CPU密集型如何區分

為保持處理器達到期望的使用率,最優的池的大小等于:

Nthreads = Ncpu x Ucpu x (1 + W/C)      

CPU數量是确定的,CPU使用率是目标值也是确定的,W/C也是可以通過基準程式測試得出的。

對于計算密集型應用,假定等待時間趨近于0,是的CPU使用率達到100%,那麼線程數就是CPU核心數,那這個+1意義何在呢?

計算密集型的線程恰好在某時因為發生一個頁錯誤或者因其他原因而暫停,剛好有一個“額外”的線程,可以確定在這種情況下CPU周期不會中斷工作。      

是以 Ncpu+1 是一個經驗值。

對于IO密集型應用,假定所有的操作時間幾乎都是IO操作耗時,那麼 W/C的值就為1,Ucpu 要達到100%使用率。

根據 Nthreads = Ncpu x Ucpu x (1 + W/C),

那麼對應的線程數确實為 2Ncpu 。

Java代碼中可以通過Rumtime來獲得CUP的數目:

int N_CPUS = Runtime.getRuntime().availableProcessor();      

對于包含I/O操作或者其他阻塞的任務,由于線程不會一直執行,是以線程池的數量應該更多。

有一個思路,CPU計算和IO的阻抗比對原則。

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

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

如果一個web程式有CPU操作,也有IO操作,那該如何設定呢?

有一個估算公式:

最佳線程數目 = ((線程等待時間+線程CPU時間)/線程CPU時間 )* CPU數目      

這個公式進一步轉化為:

最佳線程數目 = (線程等待時間與線程CPU時間之比 + 1)* CPU數目      

以上可以得出一個結論:

線程等待時間所占比例越高,需要越多線程。線程CPU時間所占比例越高,需要越少線程。

Prometheus監控(1)

三豐,公衆号:soft張三豐Prometheus監控(1)

Prometheus監控(2)

三豐,公衆号:soft張三豐Prometheus監控(2)

Prometheus監控(3)

三豐,公衆号:soft張三豐Prometheus監控(3)

Prometheus監控(4)

三豐,公衆号:soft張三豐Prometheus監控(4)

Prometheus監控(5)

三豐,公衆号:soft張三豐Prometheus監控(5)

繼續閱讀