# 2017q1 Homework4(phonebook-concurrent) contributed by<`yanang`> ###### tags: `yanang` ## 開發環境 * OS: Ubuntu 16.04 LTS * L1d cache: 32K * L1i cache: 32K * L2 cache: 256K * L3 cache: 3072K * Architecture: x86_64 * CPU 作業系統: 32-bit, 64-bit * Byte Order: Little Endian * CPU(s): 4 * Model name: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz * Linux yanang 4.8.0-36-generic #36~16.04.1-Ubuntu SMP ## read * [Concurrency系列(一): 理解Concurrency之路](http://opass.logdown.com/posts/784600-concurrency-series-1-the-road-to-understand-concurrency) * atomic operation : 不可被中斷的一個或一系列操作,多對應特殊的 CPU 指令。在所有的線程同步機制裡原子操作是最迅速的,因為完全不需要加鎖。原子操作是實現 Lock-Free 最重要的武器。 * [Concurrency系列(二): 從Sequenced-Before開始說起](http://opass.logdown.com/posts/788206-concurrency-series-2-starting-from-sequenced-before) * Evaluation - value computations and side effect * A is sequeced-before B : A 必會在 B 之前完成 > 經典的未定義行為 i = i++ > ![](http://josephmansfield.uk/media/images/sequencing-graphs/postincrement.png) > i++ 的 side effect 只 sequenced-before i++ 本身的 result,這個 side effect 可能發生在 assignment 之前或之後。 * [Concurrency系列(三): 朝Happens-Before邁進](http://opass.logdown.com/posts/797113-concurrency-series-3-happens-before) * Happens-before in Java : 當行為 A happens-before B 時,代表 A 的效果可見,而且發生於 B 之前 * differnet between Sequenced-Before and Happens-before : sequenced-before 強調實際上的執行順序,而 happens-before 強調 "visible"-看起來先執行前者再執行後者的效果 > happens-before but not really execute first : > A = B + 1; > B = 1; > 實際上執行時,編譯器有很大的空間可以對程式執行的順序做優化。 > movl B(%rip), %eax > addl $1, %eax > movl %eax, A(%rip) > movl $1, B(%rip) * Happens-before in c++ : (1) A is sequenced-before B (2) A inter-thread happens before B ( Sequenced-before 其實就是同一個 thread 內的 happens-before。) * C++定義 inter-thread 的 happens-before : (1) A synchronizes-with B (A和B有適當的同步) (2) A is dependency-ordered before B (A和B有相依的順序關係) * [Concurrency系列(四): 與Synchronizes-With同在](http://opass.logdown.com/posts/797957-concurrency-series-4-be-with-the-synchronizes-with-relation) * ![](http://preshing.com/images/org-chart.png) * synchronizes-with是一種跨thread間的happens-before關係,可以透過過mutex lock, thread create/join、Aquire and release Semantic來建立 * [Concurrency系列(五): Sequential Consistency的代價](http://opass.logdown.com/posts/809449-concurrency-series-5-the-price-of-sequential-consistency) * Sequential Consistency :(1)對於每個獨立的處理單元,執行時都維持程式的順序(Program Order) (2)整個程式以某種順序在所有處理器上執行 * Write Bufers with Bypassing Capability : 維持 Write->Read 的順序 * Overlapping Write Operations : 維持 Write->Write 的順序 * Non-Blocking Read Operations : 維持 Read->Read, Read->Write 的順序 * cache coherence protocol : 確保程式遵守 SC ## 初步測試 * $ make * $ ./phonebook_opt ``` orginal file size = 3206080 size of entry : 24 bytes execution time of append() : 0.002826 sec execution time of findName() : 0.002683 sec ``` * $ make plot ![](https://i.imgur.com/jsKHw0S.png) ## thread pool ### 概念 > a thread pool maintains multiple threads waiting for tasks to be allocated for concurrent execution by the supervising program. > -- wiki * ![](https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Thread_pool.svg/580px-Thread_pool.svg.png) ### 實作 ```c= threadpool_t *threadpool_create(int thread_count, int queue_size, int flags); int threadpool_add(threadpool_t *pool, void (*routine)(void *),void *arg, int flags); int threadpool_destroy(threadpool_t *pool, int flags); ``` * 先創出 threadpool ,再用將要呼叫的 function 傳入 * threadpool_destroy 先判斷各個 thread 是否完成 , 才 free(threadpool) * 完成後遇到一個 bug ,程式時好時壞 ``` yanang@yanang:~/phonebook-concurrent$ ./phonebook_opt orginal file size = 3206080 size of entry : 24 bytes phonebook_opt: main.c:165: main: Assertion `findName(input, e) && "Did you implement findName() in " IMPL "?"' failed. 已經終止 (core dumped) yanang@yanang:~/phonebook-concurrent$ ./phonebook_opt orginal file size = 3206080 size of entry : 24 bytes execution time of append() : 0.003103 sec execution time of findName() : 0.002744 sec ``` > 觀察 threadpool_add() 的回傳值,thread 正常執行 > 重新看一次 threadpool_destroy() 當中的 pthread_join 是否正常執行 > 發現我傳入的 flags 錯了導致無法正常執行 * 修改後重新執行 $ ./phonebook_opt ``` orginal file size = 3206080 size of entry : 24 bytes execution time of append() : 0.003631 sec execution time of findName() : 0.002710 sec ``` * $ make plot ![](https://i.imgur.com/UhG33Ca.png) > 時間少量的增加了,因為我在中間呼叫 thread_join 之後,就立刻 free(thread pool) > 增加了釋放記憶體的時間 ## 參考資料 * [C 的 Thread Pool 筆記](http://swind.code-life.info/posts/c-thread-pool.html)