os-2020
學號:P76091129
姓名:王子源
系級:資工所碩一
input size:1004 Mb
秒數 :77.2413s
thread 數⽬: 6
lines_per_thread : 50
程式開發概念
此次作業是希望能夠透過多執⾏緒,⽬的希望將 csv 檔案轉成 json 檔案。在讀檔時,能夠⾃⾏選定要多少條 thread 同時執⾏,每條 thread 會負責處理轉換特定幾⾏字串後,再換下⼀條 thread。
在寫完後才看到作業要求裡⾯提到 Stage 最少會包含讀檔、資料處理、輸出三個階段。⾃⼰這邊的處理並不是如作業要求的⽅式,⽽是這三個階段不斷重複性地做。會這樣寫是想說試著減少執⾏時間,不希望將⼤筆資料載入後⼜從頭做資料處理,做完⼜做⼀次輸出結果。
程式架構
在寫 HW1、HW2 的作業都有⼀個感想,就是必須去處理⼀些特殊的情況,尤其是在讀檔最後⼀ run 時。以這次作業來講,我希望每條 thread 可以負責轉換特定⾏數(不同⾏數會影響到執⾏時間,在下⾯效能分析有另外討論),並且在執⾏完所有 thread 後,依序等待每個 thread 的結果,此時就會依序將結果輸出。會在⼀開始建立需要⽤到的 thread 以及每個 thread 需要的參數
接著使⽤ pthread api 產⽣新的 thread
這裡有兩個部分需要注意
透過上述 API 產出新的 thread 之後,就要去執⾏每個 thread 需要做的 task,定義如下
因為希望當⼀個 thread 在處理轉換的過程時,不希望被其他的 thread ⼲擾,所以這部分需要使⽤ mutex 來產⽣⼀個 critical section,⽽ str_to_json 就只是基本字串處理。
當產的 thread 數量已經達到限制的數字時,就要將結果輸出成檔案。因為 multi-thread 的特性就是 non-synchronize,若不額外做處理的話,就會依據哪條 thread 做完就輸出哪條thread,這會導致輸出的結果沒有順序性。所以需要透過 pthread_join 的⽅式,讓所有的 thread 有順序的結束並將結果輸出,程式碼如下
先做的 thread 先輸出,符合 FIFO 原則的話,這樣的結果就會是有順序性的了。重複以上的步驟直到結束時,基本上就能處理 99% 左右的資料了,剩下的就是⼀些特殊的case 需要額外做處理。以我的程式碼設計,唯有 thread 產出達到指定的數⽬時,才會執⾏ pthread_join 並且輸出,那假如在最後⼀回合沒有達到指定數⽬呢?這樣會有⼀些thread 被產⽣,但沒有將他們回收,所以需要在讀完檔離開 while 迴圈後,加了⼀段
來進⾏檢查。
另外,還需要檢查另⼀個 case,每條 thread 都有負責的 lines_per_thread 列數需要處理,如果最後⼀回合沒有達成的話,那也需要在 while 迴圈後另外處理。
測試資料
這邊測試使用了 thread 數目為 1, 5, 10,另外還有調整了 lines_per_thread
的大小為 1, 5, 10, 50, 100, 500,lines_per_thread
大小是控制每條 thread 應該處理多少條 line,為求測試速度效率,使用了約 52M 小筆資料當實驗 input file。
量測結果
上圖使用 gnuplot
量測工具幫忙繪圖,並且以測試時間當作 y 軸來探討,而做完實驗後覺得可以整理出以下 2 件觀察
越多 thread 越好嗎?
我想以時間的結果來看則是未必,可以看出其實最省時的是只有 1 條 thread 的情況去執行此程式,其中可能會有很多的因素,而自己認為就是因為越多的 thread 會導致 OS 管理上的負擔,使得越多 thread 反而時間花越久
lines_per_thread
越大越好嗎?
這個 lines_per_thread 是指 thread 負責要處理多少列的資料,從圖中可以看出個有趣的部分,是當 lines_per_thread 在大約 50 時,會是時間花最少的。
如果 lines_per_thread 越少,表示每條 thread 負責少量的資料,那將會重複更多回合在上面的步驟,產生 thread 的次數也將會變多次,所花時間越多。而 lines_per_thread 越大表示每個 thread 要負責的資料量越多,我在猜想會導致時間越多的原因,有可能是因為在 pthread_join
時要等待其他 thread 做完的時間變久了,而導致要花的時間也變多。
此外,這次還有使用一個第三方程式 KSar 來協助更詳細的監控作業系統,以下附上數據結果
CPU usage
以下這張圖是多筆測資綜合起來一起看的,圖中每個高峰的順序分別是 thread 數目為 1, 5, 10,另外還有調整了 lines_per_thread
的大小為 1, 5, 10, 50, 100, 500(每個 thread 由左到右)
從結果可以觀察出下列幾件事情:
多執行緒的 CPU usage 普遍比 1 條 thread 的使用量還高
當 lines_per_thread 提高時,同時也降低了不斷重複產生新的 thread 的次數,所以紅色的部分(%sys)看起來有明顯變少
此部分也可以從 I/O 的 TPS (the number of transfers per second) 觀察出相同的結果
process
下圖指出了 Task creation 以及 Context switch
可以看到當 lines_per_thread 變大時,兩個觀察項目的縮減相當明顯,也可以看出程式在 lines_per_thread 很小時,會發生多次的 context switch 以及 task creation ,所以才會使得上面量測結果的圖,在起初的 lines_per_thread 時間會花那麼多的原因。
另外,也蠻好奇不確定是因為自己電腦是 6 核心的,所以在 10 threads 表現上並沒有比 5 threads 還高,還是其他原因沒有發現的。
更多未提到的分析將會在 「結果分析.pdf」呈現,裡頭尚包含了每個 CPU 的使用狀況、Kmem 以及 Swap 使用情形。