contributed by <chiehen
>
linux2021
有四種結構
jobqueue_t 和 threadtask_t
threadtask_t
首先看 main function, 在第 5 行後, thread 開始執行,但此時 jobqueue 為空,直到第 10 行的迴圈 task 開始被放入。
接著在透過第 13 行的迴圈將各自的運算結果相加,第 20 行將 thread pool 摧毀。
其中用到了 5 個函式:
建立 thread pool, thread 開始執行:
在此函式中建立 jobqueue 及所須數量的 thread,其中 jobqueue_fetch 為執行緒要執行的函式,在下部份會解釋。
值得注意的是此過程若有一個階段 malloc 失敗,要釋放先前所要求的記憶體及中止執行緒,及摧毀 jobqueue
持續從 jobqueue 拿取任務並執行
建立任務並放進 jobqueue,回傳該任務的 future object:
建立一個任務和一個 future object, 並將任務放入 jobqueue,在對 jobqueue 進行變動時要使用 mutex lock 以避免有其他執行緒同時操作 jobqueue。
當 jobqueue 中原本是空的時,使用pthread_cond_broadcast,通知正在等待的 thread 現在有可執行的任務。
從 future object 取得運算結果
pthread_cond_timedwait
,此函式在超過指定時間時將回傳 error,而此時將取得 lock摧毀 future object
摧毀 thread pool
在 second 不為 0 時,執行程式後會得到 segmentation fault
使用 gdb 發現問題出在
如果 timeout 發生則 result 會為 null
因此將程式碼改為先確認回傳值
解決 segmentation fault,但再次執行會發現仍會超時造成運算結果錯誤
但理論上不應超時,因為總執行時間並不到 1 秒
查看 manual 中的 pthread_cond_timedwait 有一段:
If the Clock Selection option is supported, the condition variable shall have a clock attribute which specifies the clock that shall be used to measure the time specified by the abstime argument.
發現 condition variable 可以設置 Clock 的類型
透過 gdb 查看, 發現 condition variable 的 clock ID 為 CLOCK_REALTIME 與
tpool_future_get 使用的 CLOCK_MONOTONIC 不同
修改 tpool_future_create
使用 pi_timeout.c 測試 timeout 並開啟 Adress Sanitizer 執行
發現 memory leak:
問題出在如果發生 timeout, 程式將進入 if 的區塊,jobqueue_fetch 中的 ret_value 則不會有機會被釋放
因此在增加記憶體釋放的程式碼
Todo: 修改 blocking wait, cancel, 大的 critical section
在 quiz4 中提到兩種計算 pi 的方程式: Leibniz’s Formula for Pi 和 Bailey–Borwein–Plouffe formula
原本疑惑為什麼兩者都可以平行化運算,為什麼不使用 Leibniz’s Formula,後來發現這個方法有收斂很慢的問題。
改寫 quiz4 的 compute_pi_leibniz:
發現要達到小數點後第五位的精準度, N 大約為 150000
而使用 Bailey–Borwein–Plouffe formula 時, N 設為 100 時, 精準度能達到小數後 15 位
在運算時間上也有很大的差距
為了便於理解,以下程式僅留下適用於 GNU C 的部份
在 at_thpool.h 中
呼叫 lfqueue_enq 將 task 放入 taskqueue
equeue 的作法是透過迴圈不斷:
此方式能確保一次只有一個 thread 修改 tail
Thread pool 中所執行的程式
_dequeue():
保證 thread-safe:
在迴圈內不斷確認
dequeue 方法:
當 head 與 tail 不相同(queue 中有兩個以上元素), 回傳第二個元素的 value, 並將 head 更新, 舊的 head push 進 free queue