並行性和並行性都用於多執行緒程式,但它們之間的相似性和差異存在很多混淆。 在這方面的一個大問題是:並行是不是就是並行? 雖然這兩個術語看起來很相似,但對上述問題的答案是否定的,並行性和並行性並不相同。 現在,如果它們不一樣,它們之間的基本區別是什麼?
簡而言之,並行處理的是處理來自不同執行緒的共用狀態存取,而並行處理利用多個CPU或其核心來提高硬體效能。
並行是兩個任務在執行過程中重疊的時候。 這可能是一個應用程式正在同時處理多個任務的情況。 我們可以用圖解理解它; 多項任務正在同時取得進展,如下所示 -
在本節中,我們將討論程式設計方面的三個重要級別的並行性 -
1. 低階並行
在這種並行級別中,顯式使用了原子操作。 我們不能在構建應用程式時使用這種並行性,因為它非常容易出錯並且很難偵錯。 即使Python不支援這種並行性。
2. 中級並行
在這種並行中,沒有使用顯式的原子操作。 它使用顯式鎖。 Python和其他程式設計語言支援這種並行性。 大多數應用程式員使用這種並行性。
3. 高階並行
在這種並行中,不使用顯式原子操作也不使用顯式鎖。 Python有concurrent.futures
模組來支援這種並行。
要使程式或並行系統正確,一些屬性必須由它來滿足。 與終止系統相關的屬性如下 -
正確性屬性
正確性屬性意味著程式或系統必須提供所需的正確答案。 為了簡單起見,可以說系統必須正確地將啟動程式狀態對映到最終狀態。
安全屬性
安全屬性意味著程式或系統必須保持「良好」或「安全」狀態,並且從不做任何「壞」的事情。
活躍度屬性
這個屬性意味著一個程式或系統必須「取得進展」,並且會達到一個理想的狀態。
並行系統的行為者
這是並行系統的一個常見屬性,其中可以有多個進程和執行緒,它們同時執行以在他們自己的任務上取得進展。 這些進程和執行緒稱為並行系統的角色。
並行系統的資源
行為者必須利用記憶體,磁碟,列印機等資源來執行任務。
某些規則集
每個並行系統必須擁有一套規則來定義執行者要執行的任務型別和每個任務的執行時間。 任務可能是獲取鎖,共用記憶體,修改狀態等。
在實現並行系統時,程式員必須考慮以下兩個重要問題,這可能是並行系統的障礙 -
共用資料
實現並行系統時的一個重要問題是在多個執行緒或進程間共用資料。 實際上,程式員必須確保鎖保護共用資料,以便所有對它的存取都被序列化,並且一次只有一個執行緒或進程可以存取共用資料。 如果多個執行緒或進程都試圖存取相同的共用資料,那麼除了其中至少一個以外,其他所有進程都將被阻塞並保持空閒狀態。 換句話說,在鎖定生效時,我們只能使用一個進程或執行緒。 可以有一些簡單的解決方案來消除上述障礙 -
資料共用限制
最簡單的解決方案是不共用任何可變資料。 在這種情況下,我們不需要使用顯式鎖定,並且可以解決由於相互資料而導致的併行障礙。
資料結構協助
很多時候並行進程需要同時存取相同的資料。 與使用顯式鎖相比,另一種解決方案是使用支援並行存取的資料結構。 例如,可以使用提供執行緒安全佇列的佇列模組。 也可以使用multiprocessing.JoinableQueue
類來實現基於多處理的並行。
不可變的資料傳輸
有時,我們使用的資料結構(比如說並行佇列)不適合,那麼可以傳遞不可變資料而不鎖定它。
可變資料傳輸
繼續上面的解決方案,假設如果它只需要傳遞可變資料而不是不可變資料,那麼可以傳遞唯讀的可變資料。
共用I/O資源
實現並行系統的另一個重要問題是執行緒或進程使用I/O資源。 當一個執行緒或進程使用I/O很長時間而另一執行緒或進程閒置時會出現問題。 在處理I/O大量應用程式時,我們可以看到這種障礙。 可以通過一個例子來理解,從Web瀏覽器請求頁面。 這是一個沉重的應用程式。 在這裡,如果資料請求的速率比它消耗的速率慢,那麼在並行系統中就會有I/O障礙。
以下Python指令碼用於請求網頁並獲取網路用於獲取請求頁面的時間 -
import urllib.request
import time
ts = time.time()
req = urllib.request.urlopen('https://www.tw511.com')
pageHtml = req.read()
te = time.time()
print("Page Fetching Time : {} Seconds".format (te-ts))
執行上述指令碼後,可以獲取頁面獲取時間,如下所示。
Page Fetching Time: 0.999139881798332 Seconds
可以看到,獲取該頁面的時間差不多是一秒鐘。 現在,如果我們想要存取數千個不同的網頁,您可以大概知道存取網路需要多少時間。
並行可定義為將任務分解為可同時處理的子任務的技術。 如上所述,它與並行性相反,其中兩個或更多事件同時發生。 我們可以用圖解理解它; 一個任務被分解成可以並行處理的多個子任務,如下所示 -
並行但不平行
應用程式可以是並行的,但不是並行的,意味著它可以同時處理多個任務,但任務不會分解為子任務。
並行但不並行
一個應用程式可以是並行的,但不是並行的,意味著它一次只能在一個任務上工作,並且分解為子任務的任務可以並行處理。
既不平行也不並行
應用程式既不能並行也不能並行。 這意味著它一次只能處理一項任務,並且任務不會被分解為子任務。
並行和併行
應用程式既可以是並行的,也可以是並行的,這意味著它既可以同時在多個任務上工作,也可以將任務分解為子任務並行執行。
我們可以通過在單CPU的不同核心之間或網路內連線的多台計算機之間分配子任務來實現並行。
考慮以下要點來理解為什麼有必要實現並行性 -
有效的程式碼執行
借助並行性,我們可以高效地執行程式碼。 它將節省時間,因為部分中的相同程式碼並行執行。
比順序計算更快速
順序計算受到物理和實際因素的限制,因此無法獲得更快的計算結果。 另一方面,這個問題可以通過平行計算來解決,並且比順序計算提供更快的計算結果。
執行時間更短
並行處理減少了程式程式碼的執行時間。
如果要談論真實生活中並行性的例子,我們計算機的圖形卡就是一個例子,它強調了並行處理的真正能力,因為它擁有數百個獨立工作的獨立處理核心,並且可以同時執行。 由於這個原因,我們也能夠執行高階應用程式和遊戲。
我們知道並行性,並行性以及它們之間的差異,但是它將如何實現。 理解將要實施的系統是非常必要的,因為它使我們在設計軟體時能夠做出明智的決定。有以下兩種處理器 -
單核處理器
單核處理器能夠在任何給定時間執行一個執行緒。 這些處理器使用上下文切換來在特定時間儲存執行緒的所有必要資訊,然後再恢復資訊。 上下文切換機制有助於我們在給定秒內的多個執行緒上取得進展,並且看起來好像系統正在處理多種事情。
單核處理器具有許多優點。 這些處理器需要更少的功率,並且多個核心之間沒有複雜的通訊協定。 另一方面,單核處理器的速度有限,不適合更大的應用。
多核處理器
多核處理器具有多個獨立處理單元,也稱為核心。
這種處理器不需要上下文切換機制,因為每個核心都包含執行一系列儲存指令所需的所有內容。
多核處理器的核心遵循一個執行週期。 這個週期被稱為讀取 - 解碼 - 執行週期。 它涉及以下步驟 -
讀取
這是迴圈的第一步,它涉及從程式儲存器讀取指令。
解碼
最近讀取的指令將被轉換為一系列觸發CPU其他部分的信號。
執行
這是獲取和解碼指令將被執行的最後一步。 執行結果將儲存在CPU暫存器中。
這裡的一個優勢是多核處理器的執行速度比單核處理器的執行速度快。 它適用於更大的應用程式。 另一方面,多核之間的複雜通訊協定是一個問題。 多核需要比單核處理器需要更多的功率。