iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 14
0
自我挑戰組

非本科系也能懂和該懂得作業系統系列 第 14

Day 14 - Multi-Thread Programming

  • 分享至 

  • xImage
  •  

今天我們來講如何把一個程式多執行緒化。首先,多執行緒的程式需要有相對應的硬體支援,昨天講到說每個執行緒會被一個CPU的核心所執行,所以在硬體方面至少需要一個多核心的CPU,不然的話多個執行緒都給同個人執行,不會比較快反而會比較慢而已。

雖然前面把多個執行緒講的如此神奇,但實際做起來的時候會發現諸多限制、考量與麻煩。

  • 資料的處理:同一個process底下的threads會彼此共用data section,一方面是方便,但另一方面就很容易彼此污然資料,可能這筆資料A執行緒寫過了又被B複寫導致錯誤,又或者是A把B處理到一半的資料當作處理完的來使用。
  • 任務切分:正常情況每個CPU core的能力應當是不相上下的,最好的情況就是能夠把所有執行緒的任務切分的差不多大小,才不會出現多數執行緒在等待少數執行緒的情況。
  • Debug困難:多執行緒的邏輯與一般程式的邏輯非常不一樣,且常常寫錯的時候很難發現(時好時對),甚至有時候沒寫好會出現程式整個卡死(deadlock)的狀態。

Race Condition

Race Condition是一個我自己在寫多執行緒時常常遇到的問題,既然提到了mult-thread當然要說明一下,更可以體會我在上面所說的不方便。

舉一個非常簡單的例子,假設今天我想讓0這個數字被+1三次,最終的解答應該是3
如果是一個執行緒的情況應該會是這樣:

0 + 1 = 1
1 + 1 = 2
2 + 1 = 3

其中一次 +1 做的事情有三件

  1. 拿到現在的數字 (一開始是0)
  2. 運算拿到的數字加一 (0 + 1)
  3. 把運算後的結果存回去 (1)
    一直輪迴三次。如果一個執行緒做三次這三件事情,那三個執行緒應當只需要各做一次,如果今天換作是多個執行緒在處理這個問題會變成這樣:
執行緒A拿取現在的數字 (0)
執行緒A把0+1 (0 + 1)
執行緒B拿取現在的數字 (0)
執行緒A把結果存回去(1)
執行緒C拿取現在的數字(1)
執行緒B把拿到的數字加一 (0 + 1)
執行緒C把拿到的數字加一 (1 + 1)
執行緒C把結果存回去(2)
執行緒B把結果存回去(1)

最後輸出的結果居然是1,因為沒辦法判斷哪個執行緒會先做後做,以及做到哪個階段,導致相互污染彼此的資料,這種情況就叫做Race condition。

人生苦短,珍惜光陰,愛用多執行緒

還記得我第一次在寫multi-thread的經驗,那個時候在寫一支用來算遊戲佈局最佳化的程式,因為我選擇的最佳化演算法需要經過一輪一輪的迭代(基因演算法),一算下來可能會花上不少時間,造成我在校調演算法的過程中,改動幾個參數我要等上一個多小時才能夠觀測到結果,於是就導入了multi-thread 在我的程式中,那個時候使用的是openMP這個函式庫,把電腦的CPU用好用滿,速度快了4.6倍。


上一篇
Day 13 - Thread and Multiple-Threads
下一篇
Day 15 - CPU Scheduling
系列文
非本科系也能懂和該懂得作業系統30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言