在執行共享記憶體系統時,會啟動乙個單獨的程序,然後派生(fork)出多個執行緒,所以當我們談論共享記憶體程式時,我們指的是正在執行任務的執行緒。
需要在程序、執行緒之間平均分配的任務從而滿足使得每個程序/執行緒獲得大致相等的工作量稱為負載均衡(load balancing)。
將序列程式或者演算法轉換為並行程式的過程稱為並行化(parallelization)
我們需要協調程序/執行緒之間的工作,這些程序中,我們需要
安排程序、執行緒之間的同步
安排程序、執行緒之間的通訊
在共享記憶體系統,變數可以是共享的(shared)或者是私有的(private)。共享變數可以被任何執行緒讀、些,而私有變數只能被單個執行緒訪問。執行緒間的通訊是通過共享變數實現的,所以通訊是隱式的,而不是顯式的。
動態執行緒和靜態執行緒
在很多情況下,共享記憶體程式使用的動態執行緒,在這種正規化中,有乙個主線程,並且在任何時刻都有一組工作執行緒(可能為空)。主線程通常等待工作請求,當乙個請求到達時,它派生出乙個工作執行緒來執行該請求,當工作執行緒完成任務,就會終止再合併到主線程中。
在靜態執行緒中,主線程在完成必須的設定後,派生出所有的執行緒,在工作結束前所有的執行緒都在執行。當所有的執行緒都合併到主線程後,主線程需要做一些清理工作,然後也終止。
在任何乙個mimd系統中,如果處理器非同步執行,可能很可能會引發非確定性。
非確定性是兩個執行緒嘗試同時更新記憶體區域x而造成的。
我們常說程式有競爭條件(race condition),因為執行緒或者程序處於競爭狀態下,一次只能被乙個執行緒執行的**塊稱為臨界區(critical section),通常是程式的負責來保證互斥地訪問臨界區。
保證互斥執行的最常用機制是互斥鎖(mutual exclusion clock)或者互斥量(mutex)或者鎖(lock)。互斥量是由硬體軟體的乙個特殊型別的物件。
還需要注意的是,使用互斥量加強了臨界區的序列性(serialization)。因為在臨界區中,一次只有乙個執行緒能執行**,**有效地序列化了。
還有其他可以替代的互斥量的方式,訊號量(semaphore)與互斥量類似,儘管他們的行為細節有很多不同,但是某些型別的執行緒,使用訊號量實現同步比用互斥量實現要簡單。監視器(monitor)能夠在更高層次提供互斥執行,監視器是乙個物件,這個物件的方法,一次只能被乙個執行緒執行。
訊息傳遞的api(至少)要提供乙個傳送和乙個接收函式。程序之間通過它們的序號(rank)互相識別,序號的範圍從0∼p−10\sim p-10∼p−1,其中ppp表示程序的個數。
注意:程式段是spmd,兩個程序使用相同的可執行**,但是執行不同的操作。它們所執行的操作依賴於它們的序號
不同的程序中,變數message指的是不同的記憶體塊
假設執行緒0能夠寫stdout。通常情況下,即使訊息傳遞api沒有顯式的支援,但大多數實現訊息傳遞的api程式都允許所有的程序訪問stdout和stderrr。
在訊息傳遞中,乙個程序必須呼叫乙個傳送函式,並且傳送函式必須與另乙個程序呼叫的接收函式匹配。任何通訊都需要兩個程序的顯示參與。在單向通訊(one-sided communication)或者遠端記憶體訪問(remote memory access)中,單個處理呼叫乙個函式。
在這個函式中,或者用來自另乙個程序的值來更新區域性記憶體,或者使用來自於呼叫程序的值更新遠端記憶體。這種方式能夠簡化通訊,因為它需要乙個程序參與,此外,還消除了兩個程序間同步的代價,有效的降低了通訊的開銷,它取消了乙個函式,也可以減少開銷。
自動軟體設計
在1973年,美國人peter freeman在他的文章 自動軟體設計 automating software design 中有這樣的假設 如果有這樣一台機器 當我們告訴它我們需要什麼軟體的時候,它立刻就會滿足我們的要求,自動生成我們需要的程式。這台機器我稱之為萬能機。當我們提出需求的時候,需要關...
軟體設計原則
開閉原則 ocp 軟體設計的最大原則 這個原則說的是 對擴充套件開放,對修改關閉。其實意思是說,給系統新增新的功能,但不修改原有 如果能做到呢,關鍵在於抽象化,也就是封裝變化,抽象層不變,讓具體實現依賴抽象隨需求變化。使得系統具有很強的擴充套件性和可維護性。黎克特制代換原則 任何基類可以出現的地方,...
軟體設計原則
高內聚 低耦合 乙個軟體系統要有乙個穩定的架構,不會隨需求的改變而發生巨大的變動。因此,高內聚 低耦合是乙個軟體系統設計中必須遵循的基本原則 面向抽象程式設計 在面向過程的軟體開發中,上層元件呼叫下層元件,就意味著上層元件依賴於下層元件,當下層元件發生劇烈變化時,上層元件也要跟著一起發生變動,這將導...