帶寬是存盤系統一個的一個非常重要的衡量指標,記憶體帶寬指的是CPU從記憶體讀取或寫入資料到記憶體的速率,我們今天來思考一個問題,在你的應用程式里記憶體的訪問帶寬能夠達到多少?
各代記憶體帶寬規格
理論上記憶體帶寬的計算公式是:Band Width = Speed * Data Width,在這個公式的基礎上,我們來看一下各代規格的記憶體帶寬表現,

從上圖來看,DDR3代的記憶體 DDR3代1066MHz的帶寬都已經達到了8.5GB/s, DDR4代3200MHz更是達到了驚人的25.6G, 廠家在進行銷售的時候也都是用這個公式來算,言外之意就是告訴你:“我家的產品非常快,大家趕快來買啊!”
廠家這么宣傳似乎也不算錯,但是有誘導性的謊言在其中, 廠家這個資料的基礎是記憶體嚴格以順序IO的方式作業,而且把傳輸的記憶體地址也當資料來看,進而計算出的結果,但我們在《記憶體隨機訪問也比順序慢,帶你深入理解記憶體IO程序》中明白了的是,記憶體在并一定是所有的Data Speed周期都在源源不斷往外吐資料,在CPU傳入了行地址后,記憶體打開一行需要tRCD+tRP個時鐘周期的延遲,輸入列地址后,又需要等待CL個時鐘周期,而記憶體作為易失性存盤元器件,又需要定時對所有的行進行充電,來保證資料不丟失,所以,在實踐中,我們并不是總是能夠達到廠家宣傳的理論帶寬值,
注意:理論帶寬值計算時采用的是記憶體的Speed,也就是其資料頻率,而記憶體的延遲呢,用的是時鐘周期,現代的記憶體在時鐘周期的上沿和下沿都可以傳輸資料,所以資料頻率比Speed又慢了一半,對于筆者Speed為1067MHz的記憶體條,其時鐘頻率是553MHz,
鄧爺爺說過,實踐是檢驗真理的唯一標準,我們今天就來進行一下實際的測驗,看看記憶體的到底每秒能給我們吐出多少的資料,和前文《實際測驗記憶體在順序IO和隨機IO時的訪問延時差異》的測驗方法類似,我們今天對方法進行下小改動,用它來測驗帶寬,
順序IO情況核心測驗方法
測驗代碼主體上和延遲測驗差不多,定義一個指定大小的陣列,然后以指定步長對其進行訪問,
void init_data(double *data, int n){
int i;
for (i = 0; i < n; i++) {
data[i] = i;
}
}
void seque_access(int elems, int stride) {
int i;
double result = 0.0;
volatile double sink;
for (i = 0; i < elems; i += stride) {
result += data[i];
}
sink = result;
}
考慮到記憶體對齊能提高性能,所以公平起見,我們每次都是按記憶體位寬去取的(一個double 8個位元組,正好是一個記憶體位寬),帶寬就是一秒內訪問過的位元組總數,所以我們通過如下代碼進行計算,
result = total_accessed_bytes * 1000 / used_microseconds;
順序IO情況帶寬測驗結果
筆者的服務器上的記憶體條是DDR3,1067MHz,延遲引數為7-7-7-24,我們進行了多場景的測驗,
場景一: 固定陣列大小2K,調節步長

陣列為2k,足夠小到L1 cache全部都能裝的下,這時候其實基本實際記憶體IO發生的很少,大部分都是更高效的L1 cache的IO,在CPU內部就完成了,但最高值也才6G而已,也沒有達到廠家宣稱的8GB,
場景二: 固定步長為8,陣列從32K到64M

陣列越大,Cache越裝不下,資料訪問的IO會更多地往后穿透到L2、L3和記憶體,L1、L2、L3和記憶體IO的性能依次遞減,因此陣列越大,平均帶寬就會越低,
場景三: 步長為32,陣列從32K到64M

步長增加后,穿透到記憶體的次數進一步增加,帶寬進一步下降,這個時候,我們應用程式視角看到的資料帶寬已經下降到1GB以下了,
再測隨機IO情況
前面的測驗情況,雖然步長也在變化,但都是有序遞增,這樣記憶體的連續兩次IO之間,雖然列地址會變,但是行地址極有可能不發生變化,因此效率還是算比較高, 我們這次是來徹底隨機進行訪問,再來看一下,
** 隨機訪問,陣列從8K到64M **

當陣列比較小的時候,雖然亂序訪問,但是cache能兜住,因此記憶體IO實際上發生的很少,但當陣列增加到64M的時候,再加上哪一級Cache都兜不住了,再加上訪問又足夠隨機,因此都穿透到了記憶體,而且行的行地址也極大可能發生變化,這時,記憶體帶寬竟然下降到了474M,
結論
廠家在宣傳的記憶體帶寬資料的時候,用的是嚴格順序IO情況下的資料,而且把地址的傳輸也當資料算了,但是廠家不會告訴你,在實際中記憶體的帶寬并沒有你想象的那么快,在隨機IO作業模式的情況下,帶寬只有474M而已, 現在SSD固態硬碟順序IO也差不多能達到這個數量級了,所以,我們以后不要魯莽地說記憶體比硬碟要快很多,快不快,關鍵取決于你怎么用!

開發內功修煉之記憶體篇專輯:
- 1.帶你深入理解記憶體對齊最底層原理
- 2.記憶體隨機也比順序訪問慢,帶你深入理解記憶體IO程序
- 3.從DDR到DDR4,記憶體核心頻率其實基本上就沒太大的進步
- 4.實際測驗記憶體在順序IO和隨機IO時的訪問延時差異
- 5.揭穿記憶體廠家“謊言”,實測記憶體帶寬真實表現
- 6.NUMA架構下的記憶體訪問延遲區別!
- 7.PHP7記憶體性能優化的思想精髓
- 8.一次記憶體性能提升的專案實踐
- 9.挑戰Redis單實體記憶體最大極限,“遭遇”NUMA陷阱!
我的公眾號是「開發內功修煉」,在這里我不是單純介紹技術理論,也不只介紹實踐經驗,而是把理論與實踐結合起來,用實踐加深對理論的理解、用理論提高你的技術實踐能力,歡迎你來關注我的公眾號,也請分享給你的好友~~~
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/200668.html
標籤:PHP
上一篇:gin HTTP/2 服務器推送
