dict 改善 & 效能探討
contributed < asd757817
,yichung279
>
原專案 bugs 修正
- 原專案在讀取 cities.txt 時,遇到地名含有空白會有 bug
fscanf 在遇到空白、換行都會停止讀取,因此城鎮名稱含有空白的會儲存錯誤,修改後只會紀錄地名或城鎮名(cities.txt 內的格式為:地名, 城鎮, 國家 OR 城鎮名, 國家)
- 原專案 bloomfilter 宣告 table 時,使用 malloc(),但未將 table 初始化,因此改用 calloc()。
改為
- 使用易於增加數量的雜湊函數
由於舊的 bloom filter 使用雜湊函數 (hash function) 時,只將兩種不同的雜湊函數放進 bloom filter 中,如此一來難以更改函數數量,也給測試帶來許多不變,因此改用 murmur3 這個能加入種子 (seed) 的函數做為雜湊函數。
bloom filter 結構修改
- bloom filter:
包含 hash function,一個 table 還有 table size。
- hash function:
以 linked list 的結構串在一起,每個結點包含一個指向函式的指標。修改之後增加 seed,讓每個 hash function 自行記錄自己的 seed。
bloom filter error rate 視覺化
以 hash function的數量、table size 的大小做為橫軸縱軸,以錯誤率做為深淺。而畫面中紫色的線為 ,其中93827 為字典中 item 數量。
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
- 把線性規劃的概念代入,我們想要最小的空間及執行速度,並符合一定的錯誤率,我們可以很清楚的知道我們想要的值在可行域的左下角。
為了讓圖片不明顯的部分,能被看得清楚,將圖片轉為灰階後做直方圖均衡化
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
- 把此圖視為高線圖,可以發現山谷都在 上,而在這裡實際的意義就是錯誤率最小值發生在 與推導的結果相符
透過開四次方根把錯誤率之間的差距加大在畫一次圖,我們能更明顯的看出上述的內容。
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
Bloom filter 的 hash function 數目、 table size 與搜尋時間之關係探討
使用 make plot 呈現不同 hash function 數量與 table 大小的搜尋效能
- hash function 數量從 1 至 15,hash table 大小從 1 至 40,統計各種組合的總搜尋時間,與單純使用 prefix search 做 600次比較。
- 測試檔案:將原字典內字串第二字取代為$,即第二個字元便不在 tree 中。
測試檔說明
原 cities.txt 檔案內容
- 測試檔以原 cities.txt 為基礎,將第 n 個字元取代成 "$",表示搜尋到第 n 字元即可判斷搜尋字串不在字典內部
- 測試檔命名為: case_n.txt,n 表示第 n 個字元取代成 "$"
如: case_02.txt 內容如下
實驗:
- bloom filter 雜湊函式數量從 1 ~ 15、table size 由 1~40 共600種組合
- 與不加 bloom filter 做600次進行比較
測試環境
情境1: 搜尋字串全部在字典內(以 cities.txt 作為輸入搜尋)

從結果中可以發現:
- tst_search 重複測試 600 次的搜尋時間大致上相同
- 因為全部的搜尋字串都在字典內,因此 bloom filter 進行的預測時間是浪費的,隨著table size、雜湊函式數量提高,浪費的時間愈多
情境2: 搜尋字串在第一個字元即可判斷不在字典內(case_1.txt)

-
加上 bloom filter 後的執行時間為 L 型:
在這個情境中,若 bloom filter 預測錯誤,進行一個搜尋所花的時間為 bloom filter + tst_search 的時間;若是預測正確則是只需要花 bloom filter 的時間,因此預測的錯誤率愈低搜尋所需要的時間愈短。
已知: bloom filter 預測的錯誤率計算公式為
其中 k為 hash function 數量、m 為 table size、n 為字串數量
依據上述公式,當 k 固定時,m 增加錯誤率會逐漸下降,繪製出的圖形也是呈現 L 形與輸出結果相符。
-
把這張圖 bloom filter 的部分與 bloom filter錯誤率的 heat map 一起看,由於錯誤率與執行時間成正比,這張圖 bloom filter 的部分,正是一列一列拆開的 heat map。
-
因為在第一個字元就可以判斷出字串不在字典中,tst_search 進行搜尋的時間反而少於進行 hash 的時間。
情境3: 搜尋到最後一個字元才發現字串不在字典內

- 第三個 L 之後加入 bloom filter 的搜尋時間全在不加 bloom filter 之上,這與搜尋的字串長度有關,雖然搜尋字串全部不在字典中且需要到最後一個字元才能發現,但因為字串長度不長,當雜湊函式的數量大於3個之後,進行雜湊運算與預測的時間反而大於 tst_search,因此在輸入的搜尋字串長度與本次情境相近時,bloom filter 的雜湊函式數量小於3個才可以使效率提高。
以 Perf 效能分析工具探討程式效能
Perf 可以取樣的事件種類很多,利用其中的 cache-misses 可以分析程式是否有善用 Locality of reference.
分析 ./test_cpy –bench
測試情境1: 以 cities.txt 作為輸入,檢查程式在空間局部性的利用狀況
miss 的數量非常多,可見程式在空間局部性的利用很差,進一步使用 perf 查看造成高 miss 的函式
可以發現 tst_free_all 與 tst_search 兩函式是造成高 miss 的主因。
發現是 tst_search 中計算搜尋字串與當前節點的差 int diff = *s - curr->key;
一步實驗後,發現*s
dereference 搜尋字串是罪魁禍首,由於每次搜尋的字串都略有不同,對於 cache 來說每次都是第一次存取,自然有 cache misses。
相反地,若短時間內重複搜尋,便有時間上的 locality,進而避免 cache misses。我們將在下方的實驗證實這件事。
分析過後,我們知道除了搜尋外,還有其他無可避免的 cache misses,我們搜尋空字串後,觀察程式運作基本 miss 數量。
以上面得到的數量作為程式運作基本 miss 數量。
情境2:驗證搜尋過的字串確實有存入 cache 中
分為3個情況進行檢查:
- 原輸入
輸入檔1:
- 同一個輸入重入輸入3次
輸入檔2:
- 原輸入搜尋後再以原輸入搜尋一次
輸入檔3
結果1
結果2
結果3
結果1、2、3都必須再減去程式基本的 miss 數量。
依據輸出結果1、2來推斷:由於第一次搜尋時會把資料存放在 cache 中,因次再次搜尋時並沒有發生 cache miss,因此兩個情境的 cache miss 數量相差不多。
結果1、3在減去基本的 miss 數量後,兩者差距約2倍,表示在第二次搜尋時 cache 中已經沒有前一次的輸入,出現第二次的 miss。
將輸入每 n 個分成一組,以組為單位重複搜尋,測試 cache 大約可以存放多少筆輸入:
n = 20
n = 1000
n = 1500
n = 2000
依照實驗的電腦配備,約1000個輸入內重複的輸入可以直接在 cache 中取得資料