程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 並行思維(一)

並行思維(一)

編輯:關於.NET

聲明:

這篇文章主要想描述一下該怎樣以一種安全和可伸縮性的方式使得程序並行化。在多核的今天,我們可能更加需要思考如何編寫一個良好的並行程序。文中有相當的內容來自《Intel Threading Building Blocks》,雖說它針對 C++ 講解,但原理通用,在跟語言,平台有關聯的時候,樓主會使用 .NET 闡述。

每個軟件開發人員都不得不面對並行編程。以前以及現在,我們在完成任務時,首先會考慮選擇最佳算法,實現語言等。但現在我們必須首先考慮任務的內在並行性。而這反過來又會影響我們對算法和實現的抉擇。如果試著在最後考慮並行,還不如不要思考並行。程序也不能很好的工作。

現實中,我們每天都在並行思考。舉兩個例子:

長時間等待。比如生病了,要去醫院看醫生。掛完號到門診前時,發現排起了一條長龍,需要很長時間才能就診。這時,我不會傻站著干等。在病情無大礙的情況下,我會一邊做一些耗時更短的事情,一邊等待就診。比如打開 MP3 聽聽音樂,跟周圍的病友們聊天,諸如此類。

大量重復性工作。當手頭有個繁重的重復性任務,而周圍又有多位相熟的朋友很悠閒,那我肯定希望這些人來幫忙以便更快的完成任務。比如搬家,網絡管理員要在每台機器上安裝同一個軟件等。

我們對並行並不陌生。實際上,並行是相當自然的思維方式。只是似乎開發人員並不常用這種方式。一旦關注並且使用並行編程,那我們便會思考並行。那時我們將會首先思考整個項目的並行性,然後才考慮如何進行編碼。

應該怎樣來實現程序並行呢?本文將講述一種重要的思維方式:並行分解。

應用程序有多種並行方式,下面將分別描述。

數據並行

如圖1所示,它是一種很典型的數據並行示例:擁有大量的數據,並且這些數據都采取同一種操作來轉換每一塊數據。

 

圖1

圖1表示,把數據集中的每一個英文小寫字母均轉換成相對應的英文大寫字母。這個很簡單的示例向我們展示了要操作的數據集和同時應用於每個元素的轉換操作。那些為超級計算機編碼的開發人員最喜歡碰到這種問題,因為要使其並行化實在簡單。

任務並行

數據並行往往最終受限於你要處理的數據量。現實中,CPU 擁有多少核心數也無法應付巨大的數據增長,即使 CPU 可以亂序並行執行多個指令。而且很多時候瓶頸並不在 CPU 處,內存,緩存也有著重要的影響,甚至我們可以讓 GPU 來參與處理。這時,我們就要轉向任務並行了(如圖2)。

任務並行意味著擁有大量不同的,獨立的,由共享數據聯系起來的任務。圖2表示在相同的數據集上應用一些數學運算規則來獲取其值,而這些值都相對獨立。換句話說,我們可以單獨計算其值,而不受其他計算的影響。

 

圖2

管道/流水線(合並數據和任務並行)

發現純粹的任務並行要比純粹的數據並行難的多。很多時候,當你發現任務並行時,它同時也是一種特定的管道/流水線。許多獨立的任務需要應用到數據流上。每一項都會被階段性處理,正如圖3中從 a 到 A 所展示的那樣。

 

圖3

假如使用管道/流水線,數據流 A 可以被處理的更快速。因為不同項的不同階段可以並行處理。管道/流水線比其他處理方式更高級:它可以更改數據或者針對選定的項跳過某些步驟。汽車工廠的裝配線就是一個管道/流水線的良好示例。如圖4:

圖4

混合方案

考慮下在信紙上寫完你的濃濃情思之後,該如何寄信。大概需要六個步驟:折疊信紙、把信紙裝入信封、密封封口、在信封正面寫上地址、貼上郵票、投遞。如果現在你有六個人來完成大量的信封裝填投遞任務,你會如何安排?很自然的反應是按照上述六個步驟,每個階段安排一人來完成它。如圖5所示:

 

圖5

參照前面所講的數據並行,你或許應該把這六個人單獨分開,每個人獨自來完成所有步驟。如圖6所示:

 

圖6

如果每個人在不同的位置工作,並且彼此相隔甚遠,那麼圖6很顯然是個正確的選擇。這就是所謂的“粗粒度並行”,因為彼此任務互動很少(他們只不過取走信封時會在一起,然後轉身就去做工作了,甚至包括投遞)。此外,如圖5所示的是“細粒度並行”,這是因為他們時常交互(每一個信封都會由上一個人傳過來,然後再傳給下一個人)。

程序不可能完全符合現實,但有時候足夠接近也很有用。在這個示例中,或許第四個步驟(在信封正面寫上地址)會讓三個人保持足夠忙碌,但前兩個步驟和後兩個步驟僅僅需要一個人就可以趕上了。圖7表明了每個步驟的工作量,而圖8則說明了一個真正的數據並行和任務並行的混合方案。

 

圖7

 

圖8

實現並行

上述示例可以用下面兩個步驟來簡單的表達:

分配任務(圍繞著工作量來自由支配)。

一開始每人做六個任務的其中一部分,但樂於分割既定任務以便兩個或多個人一塊工作。

那我們應該如何並行編程?首先,思考你的程序哪些地方可以並行。其次,根據實際情況進行並行分解。如果幸運的話,我們可能只碰到數據並行,這個就很簡單了。比如並行迭代。當碰到復雜的情況時,依據上述分類來逐一比對,最麻煩也不過是混合方案而已。請盡可能使用硬件並行,這會大大消除使用鎖機制同步的需要,而且也高效的多。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved