contributed by <finalallpass
>
RayPan
所幸最後在學長的幫忙下有安裝成功。(有向老師粉專詢問不過當時按下Ctrl+Alt+F7也沒有反應)
安裝過後花了點時間了解linux。
請升級到 Ubuntu 16.04,否則可能會遇到套件太舊的狀況 jserv
畫面本來就是 Linux 終端,就可以輸入指令
嘗試將原本的phonebook_opt.h更改為
#ifndef _PHONEBOOK_H
#define _PHONEBOOK_H
#define MAX_LAST_NAME_SIZE 16
/*
typedef struct __PHONE_BOOK{
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];
};
*/
typedef struct __PHINE_BOOK_ENTRY {
char lastName[MAX_LAST_NAME_SIZE];
//struct __PHONE_BOOK;
struct __PHONE_BOOK_ENTRY *pNext;
}entry;
entry *findName(char lastName[], entry *pHead);
entry *append(char lastName[], entry *e);
#endif
這樣跑出的結果為
size of entry : 24 bytes
execution time of append() : 0.032780 sec
execution time of findName() : 0.001741 sec
可以看到跟原本相比進步了不少
size of entry : 136 bytes
execution time of append() : 0.050244 sec
execution time of findName() : 0.005072 sec
使用gnuplot將圖形描繪出方便對照
然後再對照兩者的cache missed
未改善前的cache-misses高達90.513%
Performance counter stats for './phonebook_orig' (100 runs):
4,486,432 cache-misses # 90.513 % of all cache refs
4,946,858 cache-references
262,201,908 instructions # 1.59 insns per cycle
改善struc之降為68.396%
Performance counter stats for './phonebook_opt' (100 runs):
956,466 cache-misses # 60.158 % of all cache refs
1,625,589 cache-references
241,776,255 instructions # 2.33 insns per cycle
103,304,383 cycles
和原本相比已經好上了不少,90% -> 60%。
接下來想說在新的結構中加上指標指向原本更加詳細的資訊
typedef struct __PHONE_BOOK{
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];
}more;
typedef struct __PHINE_BOOK_ENTRY {
char lastName[MAX_LAST_NAME_SIZE];
struct __PHONE_BOOK *more;
struct __PHONE_BOOK_ENTRY *pNext;
}entry;
entry *append(char lastName[], entry *e)
{
e->pNext = (entry *) malloc(sizeof(entry));
e->more= (more *)malloc(sizeof(more));
e = e->pNext;
strcpy(e->lastName, lastName);
e->pNext = NULL;
return e;
}
這樣會變成
size of entry : 32 bytes
execution time of append() : 0.049442 sec
execution time of findName() : 0.001894 sec
entry的部份因為結構中多了一個指標而多了8bytes
和原本entry為24bytes時相比,append的時間稍微多了一些,但還是比original的好。
hashIndex hash(char *key)
{
unsigned int seed = 13;
unsigned int hashVal = 0;
while (*key) {
hashVal = hashVal * seed + (*key++);
}
return hashVal;
}
試算了一下BKDR可能出現的hash值非常大,所以會造成overflow 導致錯誤。那修改最後return的部份,去取餘數。
unsigned int seed = 13;
unsigned int hashVal = 0;
while (*key) {
hashVal = hashVal * seed + (*key++);
}
return hashVal % tablesize;
重新測試一次
size of entry : 24 bytes
execution time of append() : 0.048484 sec
execution time of findName() : 0.000027 sec
Performance counter stats for './phonebook_opt' (100 runs):
397,301 cache-misses # 34.368 % of all cache refs
1,164,390 cache-references
282,565,019 instructions # 2.17 insns per cycle
130,712,769 cycles
0.045373804 seconds time elapsed ( +- 2.29% )
hashIndex hash(char *key)
{
unsigned int hashVal = 0;
while (*key != '\0') {
hashVal = (hashVal << 5) + *key++;
}
return hashVal % sizetable;
}
size of entry : 24 bytes
execution time of append() : 0.055109 sec
execution time of findName() : 0.000005 sec
可以看到findName的時間大幅度的減少
再來檢測cache-mises
Performance counter stats for './phonebook_opt' (100 runs):
381,434 cache-misses # 32.500 % of all cache refs
1,153,347 cache-references
283,006,169 instructions # 2.18 insns per cycle
123,954,407 cycles
0.047213072 seconds time elapsed ( +- 1.06% )
和只修改structure相比cache-misses也少了快要30%
不過為了做hash function的優化,我有修改main.c的程式碼,現在要去研究一下Makefile將圖繪出比較。
運用了#if defined在main.c中讓他可以同時run opt跟orig。可以得到下圖。
雖然append時間變成但findName變得十分的快。