Re: [轉錄][閒聊]內存定址速度,好像大家都不關心?
看板PC_Shopping (個人電腦購買)作者jk21234 ( 1569 11 /47)時間14年前 (2011/03/19 21:58)推噓35(35推 0噓 24→)留言59則, 39人參與討論串1/1
講到軟體對記憶體系統的最佳化就是來釣我的..........
※ 引述《RisingForce (DD)》之銘言:
: ※ [本文轉錄自 C_and_CPP 看板 #1DX4728p ]
: 作者: DrStein (啤酒肚) 看板: C_and_CPP
: 標題: [閒聊]內存定址速度,好像大家都不關心?
: 時間: Sat Mar 19 13:40:15 2011
不是不關心,而是內存(RAM)到緩存(cache)的速度,
啊...實際上就等於記憶體控制器如何去存取DRAM的速度.
對程式設計者來說黑箱的因素太大.最佳化比較單純的
RAM種類如SRAM,1T-SRAM,RAMBUS DRAM(不算太單純但比SDRAM好)
不是主記憶體的主流,而自JEDEC SDRAM以降的體系(包含到目前的DDR2/DDR3)
由於是持續演進的,它的存取規則與cycle的關係雖然可以預期在哪個範圍,
可是很難計算出怎麼樣的位址間隔對它是最佳化的存取順序.
再說就算固定變成成同一個記憶體控制器上好了(意思是,同一顆北橋晶片或者是
同一顆cpu...),記憶體組態不同,使用者插1GBx2雙通道,1GBx2但是單通道,2GBx2,
2GB+1GB,512MBx4等等.這些不同的實體組態會導致記憶體控制器的Bank Open/Close
的policy都不同,最佳化的存取順序也不同.組態只要變化就不同,根本就不能設計
只針對記憶體控制器的效能而非針對cache最佳化的code.....
介紹RAM的文件很多,不過介紹到記憶體控制器如何運作基本的文件我也只看過一篇
An introduction to SDRAM and memory controllers (Benny Akesson),
另外手邊若有Computer Architecture:A Quantitiative Approch第二版的,也有介紹
如何應用Bank Interleave去最佳化.三版四版的有沒有拿掉我不確定....
不然若要詳細知道這問題,從基本功開始練起,可以參閱近期有本書:Memory Systems:
Cache,DRAM and Disks看建立基本觀念後能不能想出一些做法.
基本上我是認為除非組態已經很確定了例如嵌入式系統,否則針對記憶體控制器的
最佳化實在是沒有投入的效益.....一般程式設計者能知道(假如有)scratchpad memory
如何應用,preload指令,改變資料排列的順序或者是大小以適應cache等的做法
(同樣CAAQA第二版也有詳細介紹...新版不太記得)就已經很夠用了.
另外文中提到硬體上的分級是有可能的,因為不同記憶體控制器的實做規則不同
的確會影響很大的效能,比如Sis當年搶先推出首款雙通道DDR-400的655Max,
不過它的記憶體存取效能還輸給Intel E7205裝雙通道DDR-266...不過目前
記憶體控制器都內建在cpu中了,所以能做分級變成cpu層級的問題而不是晶片組.
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.37.182.84
推
03/19 22:01, , 1F
03/19 22:01, 1F
→
03/19 22:01, , 2F
03/19 22:01, 2F
→
03/19 22:03, , 3F
03/19 22:03, 3F
※ jk21234:轉錄至看板 C_and_CPP 03/19 22:04
推
03/19 22:04, , 4F
03/19 22:04, 4F
推
03/19 22:04, , 5F
03/19 22:04, 5F
還是簡化這個問題好了,我們把記憶體容量直接展開成一個二維的東西.
1 2 3 .......
N+1 N+2 N+3 .......
2N+1 2N+2 2N+3 .......
請問我連續存取三筆資料,若是存取1,2,3這順序有甚麼好處?若是存取
1,N+1,2N+1有甚麼好處?當我接連做多次存取,應該採用1,2,3的順序或者是
1,N+1,2N+1 ? 還有,寫軟體的時候我怎麼知道N是多少?基本問題可以這幾個
做例子...
→
03/19 22:05, , 6F
03/19 22:05, 6F
※ 編輯: jk21234 來自: 114.37.182.84 (03/19 22:12)
推
03/19 22:17, , 7F
03/19 22:17, 7F
推
03/19 22:18, , 8F
03/19 22:18, 8F
→
03/19 22:20, , 9F
03/19 22:20, 9F
→
03/19 22:20, , 10F
03/19 22:20, 10F
→
03/19 22:21, , 11F
03/19 22:21, 11F
→
03/19 22:22, , 12F
03/19 22:22, 12F
→
03/19 22:22, , 13F
03/19 22:22, 13F
推
03/19 22:27, , 14F
03/19 22:27, 14F
推
03/19 22:27, , 15F
03/19 22:27, 15F
→
03/19 22:27, , 16F
03/19 22:27, 16F
→
03/19 22:27, , 17F
03/19 22:27, 17F
→
03/19 22:28, , 18F
03/19 22:28, 18F
→
03/19 22:29, , 19F
03/19 22:29, 19F
OK,你的疑問就是你需要的答案,記憶體相關的benchmark不準,
主因是記憶體控制器的排程規則對軟體撰寫者而言就是很黑箱,無從
最佳化起才導致的結果.A軟體寫出來的和B軟體能得到的不同.或者是
由於其它變因不一樣,同樣程式不同環境下的Bank conflict的次數過高等等..
還有可能是我講解的方式的問題,我完全不是拿單一測試來延伸推論,
而是從現成的資料(就算書單-CAAQA二版跟Memory System不看,也應該去看
文章有提的Benny Akesson的pdf,也沒有多少頁,看完才質疑不遲)來推
還有這件事情有點像,某個人想要改車,問的不是改引擎或者是改輪胎等,
而是問如何先把車殼打磨到最低的風阻讓它更快....
而我的解答:
1.計算這東西太複雜了..而且最後的效益又很難證明比你先改引擎跟輪胎好
2.大概要設計高階賽車再來煩惱這問題,否則就很沒效益.
大概是這樣的回答方式...
→
03/19 22:31, , 20F
03/19 22:31, 20F
嗯 如何壓榨出各種記憶體控制器讀寫的最大效率的應用...
有啦,有一個實際例子,Sissoft Sandra的記憶體測試就是有特別針對不同記憶體
控制器最佳化...不過這沒有實際太大的意義.
另外很少需要這方面的應用(除非你是嵌入式系統,PS3/360,或者已經最佳化
到極限)的原因也是很簡單,如果一個程式依賴壓榨記憶體系統最大的速度,表示
在這個程式上cache幾乎不產生效果.那麼不是有很特殊的原因...就是需要如preload
等技巧輔助.
推
03/19 22:35, , 21F
03/19 22:35, 21F
推
03/19 22:35, , 22F
03/19 22:35, 22F
推
03/19 22:49, , 23F
03/19 22:49, 23F
cpu上的cache為主,因為效率差太多了,假設說我的程式原本一秒要做一百萬次記憶體
存取,而其中70%是cache hit,使用3 cycle,而剩下30%是cache miss,使用20個cycle,
光改寫軟體假設提升cache hit達到90%,那麼就會加速很多,而這個過程就是對cache的最
佳化.....
舉例而言....
1.對cache block size的最佳化
cache一次會讀入一個block大小.這個大小可能在8~64byte之間,而同一個block中的
其他資料就不用再重新讀入一次,
假設cache block是32 byte,程式有一個自訂的結構S,有{w,x,y,z,t} 5個int元素,
共有100000組資料使用結構S的陣列儲存,而且程式一開始就要讀入陣列中每個W值...
那麼,由於每讀取兩個W平均超過一個會cache miss,平均cache hit的比例會接近
(32-20)/32=12/32=3/8=37.5%,
但如果把W值另外儲存成一個連續的陣列.那麼平均cache hit的比例就是(32-4)/32=
28/32=87.5%.大約比前者快了兩倍多....
2.對cache size的最佳化
常用在超大矩陣的運算尤其乘法.由於矩陣乘法要循序讀入矩陣的每個ROW,拿去乘完
另外一個矩陣的column.再來同樣全部讀入一次並乘上下一個column...依此類推.
假設矩陣比cpu cache的尺寸大,那麼當ROW X被第二次讀入的時候,cache內早就
被他後面的ROW塞滿,原有的ROW X被捨棄掉....因此又會cache miss而重新讀取一次.
這樣幾乎100%都是cache miss.
那麼只能把這個大型矩陣的乘法拆成小型的,讓每個子乘法程序所要讀取的資料
都小於cache size,那麼cache hit的比率就會很高 而不是幾乎等於0.
3.preload
假定知道程式的某個讀取記憶體動作一定會cache miss,而cache miss後
從記憶體內讀出的cycle時間又差不多已知,那麼就可以在這行的前面N個cycle
的地方先插入preload指令,而執行到原本要讀取的那一行的時候就剛好讀進cache.
可以以cache hit的效率讀取到.
preload也可能別稱latency hidden,同樣技巧其實現實生活中也會出現一樣的例子.
假定我坐捷運從車頭上車,但是我確定等等下車要在台北車站的車尾部分的電扶梯
離開,所以我就在車子行駛中先由車頭走到車尾,省掉下車後才走的時間....這就是
標準的latency hidden的行為(走的距離並無縮短,但是時間減少了....)
推
03/19 22:49, , 24F
03/19 22:49, 24F
→
03/19 22:50, , 25F
03/19 22:50, 25F
→
03/19 22:51, , 26F
03/19 22:51, 26F
推
03/19 23:01, , 27F
03/19 23:01, 27F
推
03/19 23:04, , 28F
03/19 23:04, 28F
推
03/19 23:14, , 29F
03/19 23:14, 29F
推
03/19 23:17, , 30F
03/19 23:17, 30F
推
03/19 23:22, , 31F
03/19 23:22, 31F
→
03/19 23:22, , 32F
03/19 23:22, 32F
推
03/19 23:34, , 33F
03/19 23:34, 33F
推
03/19 23:42, , 34F
03/19 23:42, 34F
推
03/19 23:43, , 35F
03/19 23:43, 35F
推
03/19 23:50, , 36F
03/19 23:50, 36F
推
03/19 23:54, , 37F
03/19 23:54, 37F
memory controller有變化,以往在北橋晶片組的時候會比較明顯.
不同家晶片組,同一家晶片組的高低階(如Intel i875有PAT,i865沒有...)
就會差很多.
但一來這東西太少資料,二來很少軟體可以看出差異.所以就被隱藏了.
因原文在c and cpp版面發表所以想法會比較偏向軟體面的介紹...
推
03/19 23:56, , 38F
03/19 23:56, 38F
推
03/20 00:01, , 39F
03/20 00:01, 39F
推
03/20 00:13, , 40F
03/20 00:13, 40F
推
03/20 00:20, , 41F
03/20 00:20, 41F
→
03/20 00:21, , 42F
03/20 00:21, 42F
→
03/20 00:21, , 43F
03/20 00:21, 43F
推
03/20 00:32, , 44F
03/20 00:32, 44F
→
03/20 00:36, , 45F
03/20 00:36, 45F
推
03/20 01:57, , 46F
03/20 01:57, 46F
推
03/20 01:57, , 47F
03/20 01:57, 47F
推
03/20 03:41, , 48F
03/20 03:41, 48F
推
03/20 09:28, , 49F
03/20 09:28, 49F
推
03/20 09:42, , 50F
03/20 09:42, 50F
推
03/20 11:20, , 51F
03/20 11:20, 51F
→
03/20 11:31, , 52F
03/20 11:31, 52F
推
03/20 12:17, , 53F
03/20 12:17, 53F
→
03/20 12:18, , 54F
03/20 12:18, 54F
→
03/20 12:50, , 55F
03/20 12:50, 55F
※ 編輯: jk21234 來自: 114.37.182.84 (03/20 16:35)
推
03/20 18:07, , 56F
03/20 18:07, 56F
推
03/20 20:24, , 57F
03/20 20:24, 57F
→
03/20 20:25, , 58F
03/20 20:25, 58F
→
03/20 20:26, , 59F
03/20 20:26, 59F
PC_Shopping 近期熱門文章
23
163
PTT數位生活區 即時熱門文章