多處理器排程(multiprocessor scheduling)
單 CPU 排程是一位廚師、許多訂單。多處理器排程則是一間有好幾位廚師的廚房:現在的問題不只是「下一個煮什麼」,還有「哪位廚師來煮」、以及如何讓所有廚師都忙著、又不會有兩位去搶同一個鍋。在有多顆 CPU 核心時,作業系統必須決定每個就緒行程在哪顆核心上跑,而不只是順序。
它的組織方式:有兩種大方向。單一共享就緒佇列在概念上很簡單——每顆核心都從一個共同佇列拉下一個行程——但那個佇列會成為爭用瓶頸,因為每顆核心都必須鎖住它,而且它忽略了快取的區域性。主流的現代做法是給每顆核心自己的逐核心執行佇列。這避免了鎖的爭用、也讓行程留在它先前暖好的快取附近,但它製造了新問題:佇列可能變得不平衡,一顆核心過載而另一顆閒置。決策也可以是對稱的(每顆核心自己排自己,今日常見的設計)或非對稱的(一顆主核心處理所有排程)。
為什麼重要、以及它帶出的新顧慮:更多核心能平行做更多工作,但前提是排程器讓它們都有事做且尊重硬體。兩個在單 CPU 上根本不存在的議題現在成了主角:處理器親和性——把行程留在同一顆核心上的強烈誘因,好讓它受惠於那顆核心快取裡已有的資料;以及負載平衡——在核心間搬移行程,使沒有一顆閒置、而另一顆被淹沒。這兩個目標彼此衝突(再平衡會破壞親和性),好的多核心排程器大半的巧思都花在管理這份張力上。
四顆核心,各有自己的執行佇列。核心 0 排了六個就緒執行緒;核心 3 一個都沒有。一個負載平衡器注意到這個不平衡,把兩個執行緒從核心 0 遷移到核心 3——但每個被遷移的執行緒現在在核心 3 的快取上是「冷」的,失去了它在核心 0 上原有的親和性好處。
逐核心佇列需要負載平衡,但每次遷移都犧牲它剛擁有的親和性——這是多核心排程的核心張力。
更多核心不會自動帶來按比例增加的產出率:共享佇列或共享記憶體的爭用,加上親和性與平衡的取捨,可能讓核心閒置或快取空轉——多核心可擴展性是一個真實而獨立的問題。