執行緒與並行模型

多對多模型(many-to-many model)

想像一個客服中心有五十位專員,但只有八條對外的電話線。五十位專員處理工作,由一位主管在電話線空出來時把他們多工地安排到那八條線上,於是公司得到五十位員工的反應能力,卻不必負擔五十條線。多對多模型替執行緒做的就是這件事:它把許多使用者層級執行緒對映到數量較少或相等的核心執行緒上。你得到大量便宜的使用者執行緒,但只用到你需要的那麼多昂貴的核心執行緒。

具體來說,在多對多裡,使用者空間的排程器把你的使用者執行緒多工地安排到一池核心執行緒上(例如每個 CPU 核心一條)。程式可以建立上千條使用者執行緒;執行期保有一組數量適中的核心執行緒,並讓任何就緒的使用者執行緒在任何可用的核心執行緒上執行。一個常見的變體,兩層模型,額外提供把某條特定使用者執行緒在需要時直接綁定到它自己一條核心執行緒的選項。這的目標是結合兩個極端的優點:多對一便宜又充裕的使用者執行緒,加上一對一真正的平行。

誠實的描述是利弊參半。原則上多對多讓你想建多少執行緒就建多少、能在多個核心上跑、又能避免整個行程阻塞,因為當一條使用者執行緒在核心裡阻塞時,執行期可以在另一條核心執行緒上去跑別的使用者執行緒。但實務上這個模型確實很難實作得好;使用者空間排程器與核心排程器之間所需的協作很複雜,有好幾個作業系統嘗試過後又改回單純的一對一。它的理念在現代語言執行期裡存活得最成功(例如 Go 的 goroutine),它們在一對一核心執行緒之上建了一個 M 對 N 的排程器。

Go 程式常常同時跑數十萬個 goroutine,而執行期只保有少少幾條核心執行緒(大約每核心一條)。Go 的排程器把 goroutine 多工地安排到那些核心執行緒上,當一個 goroutine 阻塞時就把它停住、換進另一個,這是一個建立在一對一作業系統執行緒之上、能實際運作的 M 對 N 設計。

許多便宜的使用者執行緒被多工到少數核心執行緒上,靈活但難以打造。

多對多承諾兩全其美,但在核心裡很難實作,所以好幾個作業系統棄它改用一對一。它在現實世界最大的成功,是在疊於一對一執行緒之上的語言執行期裡。

又称
M:N modeltwo-level model多對多執行緒模型兩層模型