1
對應「並行和多執行緒程式設計」的 Atomics 操作, Thread Pool
〈UNIX 作業系統 fork/exec 系統呼叫的前世今生〉提及 1963 年電腦科學家 Melvin Conway 博士提出的 fork-join 模型,亦即將任務切割成多個子任務,最終彙整各個子任務的結果並得到原任務之結果:
Work-stealing 演算法是指某個執行緒從其它工作佇列裡「竊取」(steal) 任務來執行,運作流程圖如下:
設想目前的情境下有個較大的任務,我們可將這個任務分解成許多彼此獨立的子任務。為了減少執行緒之間的競爭,我們將這些子任務分別放入不同的工作佇列 (workqueue) 中,並為每個佇列建立一個獨立的執行緒來執行工作佇列中的任務。執行緒與工作佇列逐一對應,例如執行緒 A負責處理工作佇列 A 中的任務。然而,有些執行緒可能會先完成自身佇列中的任務,其他執行緒對應的工作佇列中卻仍有任務在等待處理。
因此,那些經完成指派任務的執行緒會空閒下來。與其閒置,不如去幫助其他執行緒完成剩下的任務。於是,這個已沒有任務的執行緒就會去其他工作佇列中「竊取」(或說「認領」)一個任務來執行,於是,它們會存取到同一個工作佇列。為了減少竊取任務的執行緒與被竊取任務的執行緒之間的競爭,通常會使用雙向佇列 (double-ended queue,通常縮寫為 deque,發音為 [dek]),被竊取任務的執行緒永遠從雙向佇列的開端處取出任務來執行,而竊取任務的執行緒永遠從雙向佇列的尾端處取出任務來執行。
延伸閱讀:
我們嘗試以 C11 Atomics 撰寫 work stealing 程式碼,參見 work-steal.c (部分遮蔽),編譯和測試: (執行順序可能略有不同)
補完程式碼,使其運作符合預期。作答規範:
x+y
,而是 x + y
(+
運算子前後各有一個空白字元)1 + x
,而是 x + 1
,除非後者會導致不同的運算結果AAAA
, BBBB
, CCCC
, DDDD
, EEEE
均為表達式延伸問題:
2
對應「並行和多執行緒程式設計」的 Atomics 操作, Linux 核心同步機制, 多核處理器
為了檢驗學員對〈建立相容於 POSIX Thread 的實作〉的認知,以下嘗試使用 GCC Built-in Functions for Memory Model Aware Atomic Operations 和 futex 來實作 multiple-producer/multiple-consumer (MPMC):
futex 全名為 fast user-space mutex locking,是 Linux 核心一種機制,主要提供使用者層級中有效與多執行緒的同步方式,並降低 Linux 核心的介入。可參考 Basics of Futexes。futex 主要有 wait 和 wake 等二個操作,其定義如下:
編譯方式:
參考執行輸出如下:
原始程式碼可見 mpmc.c (部分遮蔽)。請補完程式碼,使其運作符合預期。作答規範:
ZAAA
和 ZCCC
為整數ZBBB
為表示式,使用 lab0-c 的程式碼風格ZDDD
為巨集名稱(
和 )
)延伸問題:
提示: 加上編譯參數
-fsanitize=thread