contributed by <jkrvivian
>
A is not sequenced-before B and B is not sequenced-before A ==>執行順序不一定,求值時可能會重疊,優化後的執行順序會交錯
value computation V.S. side effect
有點混亂了@@
i++這類的後置運算子,value computation會先於side effect對於assignment operator而言(=, +=, -=之類的),會先進行運算元的value computation,之後才是assigment的side effect, 最後是整個assigment expression的value computation
happens-before : 前一個操作的效果在後一個操作執行之前必須要 可見
synchornized-with :兩個不同thread間的同步行為,當A synchronized-with B的時,代表A對記憶體操作的效果,對於B是可見的。而A和B是兩個不同的thread的某個操作
synchronized
in java
volatile
in java
memory consistency models: 系統要想辦法在保證 正確 的情況下,盡可能的最佳化,讓程式跑的又快又好
cache architecture 與 sequential consistency
影片
parallelism can come from better expression of concurrent problem
過往接觸過的:
A每次呼叫B或C都是從兩人的最開始執行到最後再回到A
coroutines:
每次都是回到ABC三者的中斷點再接續執行,而不是從頭開始
若有使用到local變數,那執行結果可能就不如預期了
解決辦法:allocate separate stack space for each function that is running as a thread
讀Jserv老師的部落格還有文中提到的經典文章coroutines in C,完全不知道switch可以這樣用(跪),還沒完全看懂,研讀中~
a case statement is still legal within a sub-block of its matching switch statement
pthread_create 之前定義或在其所呼叫的函數中定義的變數來完成其工作,並將他的成果經由整體變數合併。對這些大家都可以存取的變數,我們必須加以控制。
回想之前實作raytracing使用omp進行優化時,就是因此才需要使用
private()
保護變數
檢查thread函式是否正確執行是必要的,若失敗大多數都回傳-1
critical section:
reentrant:
mutual exclusion:
size of entry : 24 bytes
execution time of append() : 0.009720 sec
execution time of findName() : 0.004989 sec
Performance counter stats for './phonebook_opt' (100 runs):
774,269 cache-misses # 49.546 % of all cache refs ( +- 1.73% )
1,562,737 cache-references ( +- 1.64% )
225,877,891 instructions # 1.25 insns per cycle ( +- 0.04% )
181,307,063 cycles ( +- 1.23% )
0.129546375 seconds time elapsed ( +- 6.50% )
plot
phonebook_opt.c
中已有個show_entry()
的function可以列出所有entry中的last name,因此可以與原有的words.txt
比對
打開opt版本的字典檔發現與原本的words.txt
不同
直接看是不對的啊!因為輸出檔沒有排序,直接看下來當然會不同@@
diff
指令發現多處不同,其一原因是phonebook_opt
的output並沒有sort,因此先執行sort
指令排序
0a1,4
> aaaa
> aaaaa
> aaaaaa
> aaaaaaa
for (int i = 0; i < THREAD_NUM; i++) {
if (i == 0) {
pHead = app[i]->pHead->pNext;
dprintf("Connect %d head string %s %p\n", i, app[i]->pHead->pNext->lastName, app[i]->ptr);
} else {
etmp->pNext = app[i]->pHead->pNext;
dprintf("Connect %d head string %s %p\n", i, app[i]->pHead->pNext->lastName, app[i]->ptr);
}
etmp = app[i]->pLast;
dprintf("Connect %d tail string %s %p\n", i, app[i]->pLast->lastName, app[i]->ptr);
dprintf("round %d\n", i);
}
把pHead = app[i]->pHead->pNext
和etmp->pNext = app[i]->pHead->pNext
裡的pNext
拿掉就對了
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
refactoring(重構)的定義:「在不改變軟體的外在行為之下,改善既有軟體的內部設計」
甚麼是refactoring有提到22種壞味道
main.c
58行開始及77行include和define搬到最前面,個人習慣,看起來比較整齊
#ifndef OPT
#include "file.c"
#include "debug.h"
#include <fcntl.h>
#ifndef THREAD_NUM
#define THREAD_NUM 4
#define ALIGN_FILE "align.txt"
#endif
struct timespec mid
雖然有gettime()
,但之後完全沒有用到,所以直接刪除struct timespec mid
刪除後就可以合併前後的#ifndef OPT
內的程式碼,並把struct timespec start, end
搬到外面
#ifndef OPT
FILE *fp;
int i = 0;
char line[MAX_LAST_NAME_SIZE];
struct timespec start, end;
double cpu_time1, cpu_time2;
/* check file opening */
fp = fopen(DICT_FILE, "r");
if (!fp) {
printf("cannot open the file\n");
return -1;
}
#else
file_align(DICT_FILE, ALIGN_FILE, MAX_LAST_NAME_SIZE);
int fd = open(ALIGN_FILE, O_RDONLY | O_NONBLOCK);
off_t fs = fsize(ALIGN_FILE);
#endif
for (int i = 0; i < THREAD_NUM; i++) {
app[i] = new_append_a(map + MAX_LAST_NAME_SIZE * i, map + fs, i, THREAD_NUM, entry_pool + i);
pthread_create( &tid[i], NULL, (void *) &append, (void *) app[i]);
}
system embedded
HW 2