contributed by < ktvexe
>
繼續之前的實作,研究尚未討論的議題。
jserv
fineName()
的操作,但缺乏不同 hash function 的效能比較和設計取捨append()
中,malloc()
是個顯著的時間開銷,缺乏減緩效能衝擊的方案,而且沒考慮到 malloc()
失敗的情況phonebook_orig
執行都會失敗:main.c
無法透過 function pointer 來切換和比較不同實做的效能落差,應該先設計一份可通用的軟體界面,然後將 binary tree, hash table, trie 等不同實做機制加入append()
和 findName()
時間加入統計的意義不大,真實應用往往是個別操作,特別在圖表的呈現我們知道phonebook這份作業考量到cache miss的議題
先來複習一下電腦的規格:
看到L1d,L1i好高興阿,回想了Architecture的觀念,來貼個圖增加印象
看圖說故事:在Harvard 架構下,我們可以同時進行指令與資料的存取,因為指令與資料是分開存放在不同的記憶體中,並且各自有自己的bus連接 CPU。
但是CPU與DRAM的速度還是差太多了,這樣的架構會導致效能不佳的結果,所以才有了L1i與L1d,如圖:
linux kernel:
$ ./phonebook_orig & sudo perf top -p $!
更改phonebook_opt
重點提示:
可能的效能改進方向:
其實phonebook_orig.c非常的簡單,只是單純的重頭找到尾而已,entry是他的struct type
結果:
cache miss 高達96%
in main
,可以發現不管append還是findName其實都也只用到lastname
所以一開始先從struct下手,先把其他欄位都給comment out
不過只有lastname的電話簿是不符合規定的,所以說把結構內加入char*,到時想要增加其他的資訊再另外加。
所以結果如下:
處理時間上差異不大,可以看出明顯差異的是entry的大小改變。
接下來把其他資料補完後
phonebook_opt.h
程式碼:
總共96 bytes,而cache miss也降到72%,這是可以想像的,結構變小,cache會因為超出容量而踢block。
shell Performance counter stats for './phonebook_opt' (100 runs): 1,098,896 cache-misses # 71.509% of all cache refs 1,529,886 cache-references 259,741,175 instructions # 1.53 insns per cycle 165,656,122 cycles 0.062172392 seconds time elapsed ( +- 1.14% )
不過要是只有這樣entry size還是很大,結構愈大,能放入block的數量愈少,但是要如何改善呢?
所以接下來嘗試把lastname包在同一個struct,使其記憶體連續,以增加cache hit。
所以我將struct加入了index,可以用於紀錄lastName存到哪一個index,並更改findName使他多回傳一個index參數,結構如下,一個struct我裝了128個lastName,所以index用unsigned char。
程式碼:
結果:
cache miss並沒有下降,可能是我一個struct大約是2KB,而cache是32K,如此雖然可裝16*128個lastName,但卻並不合block的大小,導致這樣的配置沒有將成果發揮出來。
如果將結構增加一個index,在append時記下各開頭的index,這樣的話findname時直接從其index開頭開始搜尋,換句話說就是將原本只有1條的link-list拆成多條,這應該也可以提升執行效能,best case當然是如果每條差不多長,記憶體不會隔太遠,就能降低cache miss,且不嚴重增加append的時間,又能使findName迅速。
根據作業要求中的提示,來實作hash,以加快findName性能,不過這hash怎麼做呢?
google搜尋一下,選擇了BKDR-Hash。
網路上找到的範例code長著樣,依樣畫葫蘆,照著寫一段。
因為我本身每個struct中有128個lastName,所以我將bucket先設成256。
預測分析:
當然這樣的方式有可能可以減少link list的長度,長度變短,像我的struct可以裝128比資料,所以長度可以縮短128倍,要append的時間就可以縮短,因為跑到尾端的距離較短,不過也可能因為每個entry過大,導致cache miss,而損失的效能。
實驗結果:
findName如同預期的效能提升了,而且非常的明顯,不過我沒有想到的是,append的效能也一起提升,我感覺這並不太正常,原先append雖然將全部資料串在一起,資料亮大時會很長,不過作hash明明還要找bucket,然後要串各比資料時,記憶體應該更為分散,應該不會有效能的提升才是阿。
最後來寫一個free來解決memory leak。
我覺得自己在整理資料上,都要花費比別人還長的時間,而且成果也沒有比較完善,很羨慕能快速整理重點、彙整資訊的人,我閱讀資料時經常會發散,書一本又一本的開,google分頁愈開愈多,只得到越來越多資料,也不確定哪些是我需要的,很佩服其他能再時間內完成3種、4種實作的同學,覺呢能跟他們一起學習真是太好了,希望能一起變強。
我覺得這次phonebook的分析真的可以複習很多以前學過的東西,當然還有很多沒有學過的,而且透過跟大家學習,可以知道自己的不足,還來不及完成的實作,我也會在以後陸續補上。