GOGOGOGOGOGOG
Makefile
以允許 $ make plot
時,視覺化 ternary search tree + bloom filter 的效能表現。注意,需要設計實驗,允許不同的字串輸入並探討 TST 回應的統計分佈
sudo apt-get install linux-tools-common
系統便會開始自行安裝,但要注意的點是安裝的檔案版本不同的問題,老師所給的指令$ sudo apt-get install linux-tools-3.16.0-50-generic linux-cloud-tools-3.16.0-50-generic
其版本不一定適用於每個人,需要根據提示字元進行安裝。sudo sh -c " echo -1 >/proc/sys/kernel/perf_event_paranoid"
來開啟權限。Trie ,又叫做前綴樹或是字典樹,是一個動態配置或關聯性配置的資料結構,用來保存關聯數組,常用在 string。 而當運用在 string 時, Trie 中每個節點由一個字元組成。
Trie樹的基本性質可以歸納為:
Trie 的應用: 主要在 bioinformatics , information retrieval
Trie 樹的結構,它的實現簡單但空間效率低。如果要支持26個英文字母,每個節點就要保存26個指針,假如還要加入標點符號、區分大小寫,內存用量就會急劇上升,以至於不可行。
因為 trie 的節點數組中保存的空指針,佔用了太多內存,因此考慮改用其他數據結構去代替,像是用 hash map。但是管理成千上萬個 hash map 不是什麼好主意,而且它還會使數據的相對順序信息丟失,所以使用 Ternary Tree 替代 trie。
Binary Search Tree 查詢與建表時間是 O(log2n),但是在最糟的情況下時間複雜度可能轉為 O(n),除了要儲存的字串外不須另外分配空間。
Trie 的時間複雜度是 O(n),能夠實現前者難以做到的 prefix-search,缺點是會有大量的空指針表,造成空間開銷過大。
Ternary Search Tree,是一種 trie(亦稱 prefix-tree) 的結構,並且它結合字典樹的時間效率和 BST 的空間效率優點。
Ternary Search Tree 的應用:
reference: [Ternary Search Tree 的應用]
(http://www.cnblogs.com/rush/archive/2012/12/30/2839996.html)
首先一樣的fork本次的作業,並且進行git clone https://github.com/GOGOGOGOGOGOG/dict.git
但要注意的點是本次作業除了要git init
以外,需要先安裝pref等等套件才可以執行。
前半部份為:
TESTS
是進行test_cpy和test_ref的程式碼,也就是進行make後的所產生的執行碼。TEST_DATA
測試的字串,原本為 Tai 但未來滿足作業需求進行實驗,我改成了Calva,下面會解釋實驗流程。CFLAGS
代表 GCC
編譯時用的參數。TEST
輸入 make test
會使用 pref
去測試 test_cpy
和 test_ref
總共會測試100次。make bench
則會對兩個執行檔 test_cpy
和 test_ref
進行檢測。make clean
會對執行檔和txt檔進行清除。make plot
之前我們必須先整理清楚各個GNU的.gp檔所需要的內容是什麼,例如:runtime.gp 是需要output.txt
而 runtime3.gp 則是需要test_cpy.txt
等等…bench_cpy.txt
bench_ref.txt
ref.txt
cpy.txt
output.txt
我會在後面的bug標題進行說明。)plot
在第一行中代表的是輸入plot指令後需要的檔案,分別為bench_cpy.txt
bench_ref.txt
和 output.txt
而指令 gnuplot scripts/runtime.gp
則是執行gnuplot該gp檔的程序,eog runtime.png
則是顯示圖形。執行畫面如下:
首先鍵入指令make plot
後,輸入完密碼開始進行檢測並紀錄執行時間。
執行完成後會產生三張圖形:分別是cpy和ref的執行時間比;cpy的搜尋效率;ref和cpy的搜尋效率對照,如圖:
本次作業的要求:
視覺化 ternary search tree + bloom filter 的效能表現。注意,需要設計實驗,允許不同的字串輸入並探討 TST 回應的統計分佈。於是我做了以下實驗,其得到的結果是:ref的執行效率低於cpy並且會隨著輸入字串的增加越來越明顯,如同我上述所提到的我將測試的字串改為Calva
但其實我一開始是從字串C
開始進行實驗然後再逐一增加字串數量,例如增加為Ca
等等…測試的結果如下
增加為Ca
增加為Cal
增加為Calv
增加為Calva
可以發現雙方的執行時間從0.38秒的差距拉開到0.47秒,可知ref和cpy的效率的確是差了一些。
探討造成此現象可能的原因?
10/15 將runtime.gp作修改:
首先比較容易發現的bug在test_cpy.c和test_ref.c之間的差異,執行完程式碼後會發現無法生成ref的文字檔,其原因是在於test_ref.c中程式碼少了輸出txt檔的程式碼:如下:
將此程式碼輸入後即可產生bench_ref.txt
除此之外也要記得執行calculate.c檔來產生output.txt
不過最讓我好奇的還是:
如圖:
會發現在輸入A後會出現segfault的狀況,後來發現其問題是出在 tst.c檔中:
參考了:(https://hackmd.io/nLSb34t0SE2V-56Gxi7ErA?both# )之後才發現原來是因為,*n不斷的滿足條件進入遞迴(return)當進行到330行時,程式早已經不符合原來的設定了,*n的持續增加會造成存取到不正確的記憶體。需要將程式修改成:
即可修復這個bug。
可以看到cpy和ref在輸入功能中仍舊是cpy的速度較快,其中原因我想也來自於cpy和ref存取的方式不同,前者是用TST不過後者是用bloom filter,但關於本次作業要求要兩個都加入bloom filter還是不懂。
10/17更新: ref還使用了bloom filter去搜尋字串所以可能是因為這樣,在時間上才會高於cpy。
時間不夠待補上 對ref進行perf分析時,會導致coredumped,如圖:
10/19更新:
在test_cpy新增bloom_filter進行測試:
後來經過討論後,發現原來 test_ref是代表tst加上bloom_filter,而test_cpy則是只有tst而已,而在之前的圖形中,之所以ref需要的時間會比cpy還的長的原因是因為bloom_filter需要建立還有更新的時間,再兩者都加入bloom_filter後所產生的搜尋圖形和新增圖形之比較如下:
由上圖可知,兩者所需的時間是差不多的。
提問:
上面的圖形是關於新增功能的比較,但不太清楚過程中的波動是因為什麼原因造成的?