# 2017q1 Homework1 (phonebook) contributed by < `ga639487` > >請加速,共筆請照指定格式撰寫[name=亮谷][color=#af4] --- ### Review by <`tina0405`> *在內容中提到HASH FUNCTION有好幾種不同的,可以都嘗試看看。 *BINARYTREE的結果我本身還在嘗試,想多看看別人不同的實做想法。 ## 安裝 ubuntu [asus gl552vw](http://58703110.blogspot.tw/) 由於電腦問題,安裝作業系統有些困難, 同一型號可參考這篇。(另外感謝助教大力幫助) --- ## 開發環境 ``` Architecture: x86_64 CPU 作業模式: 32-bit, 64-bit Byte Order: Little Endian CPU(s): 8 On-line CPU(s) list: 0-7 每核心執行緒數:2 每通訊端核心數:4 Socket(s): 1 NUMA 節點: 1 供應商識別號: GenuineIntel CPU 家族: 6 型號: 94 Model name: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz 製程: 3 CPU MHz: 1284.867 CPU max MHz: 3500.0000 CPU min MHz: 800.0000 BogoMIPS: 5183.95 虛擬: VT-x L1d 快取: 32K L1i 快取: 32K L2 快取: 256K L3 快取: 6144K NUMA node0 CPU(s): 0-7 ``` 由指令`$ lscpu` 取得 kernel的部份 `Linux ga639487-GL552VW 4.4.0-31-generic` 由指令`$ uname -a`取得 --- ## Original 先打開phonebook,執行 `$ cd phonebook` `$ ./phonebook_orig` 結果如下 ``` size of entry : 136 bytes execution time of append() : 0.044711 sec execution time of findName() : 0.004928 sec ``` 再用perf stat測試cache-misses `$ sudo perf stat --repeat 100 -e cache-misses,cache-references,instructions,cycles ./phonebook_orig` 結果為 ``` 4,445,825 cache-misses # 90.981 % of all cache refs ( +- 0.16% ) 4,886,546 cache-references ( +- 0.11% ) 260,738,922 instructions # 1.50 insns per cycle ( +- 0.02% ) 174,137,398 cycles ( +- 0.15% ) 0.057684120 seconds time elapsed ( +- 0.62% ) ``` cache-misses為90.981% --- ## 可能的改進方向 讀過老師提供的資料及同學的共筆後,以下是幾個較常使用的改進方法。 * 從struct改動,因為原本的程式在執行時其實只有lastname的部份被使用到,但因其他的部份跟著被讀取而造成效能的降低,可以從這方面著手,建立新的struct解決。 * 使用hash function * 使用 binary tree進行改寫 * 使用字串壓縮演算法壓縮字串,降低資料成本 --- ## 優化 ### 1.struct phonebook_orig.c ```clike= entry *findName(char lastName[], entry *pHead) { while (pHead != NULL) { if (strcasecmp(lastName, pHead->lastName) == 0) return pHead; pHead = pHead->pNext; } return NULL; } entry *append(char lastName[], entry *e) { /* allocate memory for the new entry and put lastName */ e->pNext = (entry *) malloc(sizeof(entry)); e = e->pNext; strcpy(e->lastName, lastName); e->pNext = NULL; return e; } ``` phonebook_orig.h ```clike= typedef struct __PHONE_BOOK_ENTRY { char lastName[MAX_LAST_NAME_SIZE]; char firstName[16]; char email[16]; char phone[10]; char cell[10]; char addr1[16]; char addr2[16]; char city[16]; char state[2]; char zip[5]; struct __PHONE_BOOK_ENTRY *pNext; } entry; entry *findName(char lastName[], entry *pHead); entry *append(char lastName[], entry *e); #endif ``` 從初始版本中可以看出,在orig.h的struct中宣告了許多變數,但在orig.c的findName和append中只使用到lastName,所以可以將其他沒有使用到的變數寫進另外一個struct裡。 因此,將opt.h的程式碼改為 ```clike= typedef struct __PHONE_BOOK_ENTRYdetail { char firstName[16]; char email[16]; char phone[10]; char cell[10]; char addr1[16]; char addr2[16]; char city[16]; char state[2]; char zip[5]; } entrydetail; typedef struct __PHONE_BOOK_ENTRY { char lastName[MAX_LAST_NAME_SIZE]; struct entrydetail *detail; struct __PHONE_BOOK_ENTRY *pNext; } entry; entry *findName(char lastName[], entry *pHead); entry *append(char lastName[], entry *e); #endif ``` 再次執行後得到 ``` size of entry : 32 bytes execution time of append() : 0.034947 sec execution time of findName() : 0.001787 sec ``` ``` Performance counter stats for './phonebook_opt' (100 runs): 1,437,032 cache-misses # 63.929 % of all cache refs ( +- 0.47% ) 2,247,868 cache-references ( +- 0.16% ) 244,743,154 instructions # 2.08 insn per cycle ( +- 0.02% ) 117,680,863 cycles ( +- 0.15% ) 0.038929938 seconds time elapsed ( +- 0.21% ) ``` cache-misses從原本的90.981 %降到63.929 % `$ make plot` ![](https://i.imgur.com/RmdfHEv.png) --- ## 參考資料