[C++并發(fā)編程實(shí)戰(zhàn)]準(zhǔn)備篇

術(shù)語

并發(fā)(concurrency):兩個(gè)或兩個(gè)以上的任務(wù)在一段時(shí)間內(nèi)被執(zhí)行。我們不必care這些任務(wù)在某一個(gè)時(shí)間點(diǎn)是否是同時(shí)執(zhí)行,可能同時(shí)執(zhí)行,也可能不是,我們只關(guān)心在一段時(shí)間內(nèi),哪怕是很短的時(shí)間(一秒或者兩秒)是否執(zhí)行解決了兩個(gè)或兩個(gè)以上任務(wù)。

并行(parallellism):兩個(gè)或兩個(gè)以上的任務(wù)在同一時(shí)刻被同時(shí)執(zhí)行。

并發(fā)說的是邏輯上的概念,而并行,強(qiáng)調(diào)的是物理運(yùn)行狀態(tài)。并發(fā)“包含”并行。

計(jì)算機(jī)中的并發(fā):計(jì)算機(jī)領(lǐng)域里,并發(fā)不是一個(gè)新事物:很多年前,一臺單核計(jì)算機(jī)就能通過多任務(wù)操作系統(tǒng)的切換功能,同時(shí)運(yùn)行多個(gè)應(yīng)用程序;高端多處理器服務(wù)器在很早就已經(jīng)實(shí)現(xiàn)了真正的并行計(jì)算。那“老東西”上有哪些“新東西”能讓它在計(jì)算機(jī)領(lǐng)域越來越流行呢?——真正任務(wù)并行,而非一種錯(cuò)覺。
圖1.1顯示了一個(gè)計(jì)算機(jī)處理恰好兩個(gè)任務(wù)時(shí)的理想情景,每個(gè)任務(wù)被分為10個(gè)相等大小的塊。在一個(gè)雙核機(jī)器(具有兩個(gè)處理核心)上,每個(gè)任務(wù)可以在各自的處理核心上執(zhí)行。在單核機(jī)器上做任務(wù)切換時(shí),每個(gè)任務(wù)的塊交織進(jìn)行。但它們中間有一小段分隔(圖中所示灰色分隔條的厚度大于雙核機(jī)器的分隔條);為了實(shí)現(xiàn)交織進(jìn)行,系統(tǒng)每次從一個(gè)任務(wù)切換到另一個(gè)時(shí)都需要切換一次上下文(context switch),任務(wù)切換也有時(shí)間開銷。進(jìn)行上下文的切換時(shí),操作系統(tǒng)必須為當(dāng)前運(yùn)行的任務(wù)保存CPU的狀態(tài)和指令指針,并計(jì)算出要切換到哪個(gè)任務(wù),并為即將切換到的任務(wù)重新加載處理器狀態(tài)。然后,CPU可能要將新任務(wù)的指令和數(shù)據(jù)的內(nèi)存載入到緩存中,這會阻止CPU執(zhí)行任何指令,從而造成的更多的延遲。

圖 1.1 并發(fā)的兩種方式:雙核機(jī)器的真正并行 Vs. 單核機(jī)器的任務(wù)切換

圖1.2顯示了四個(gè)任務(wù)在雙核處理器上的任務(wù)切換,仍然是將任務(wù)整齊地劃分為同等大小塊的理想情況。實(shí)際上,許多因素會使得分割不均和調(diào)度不規(guī)則。
圖 1.2 四個(gè)任務(wù)在兩個(gè)核心之間的切換

并發(fā)示例
試想當(dāng)兩個(gè)程序員在兩個(gè)獨(dú)立的辦公室一起做一個(gè)軟件項(xiàng)目,他們可以安靜地工作、不互相干擾,并且他們?nèi)耸忠惶讌⒖际謨?。但是,他們溝通起來就有些困難,比起可以直接互相交談,他們必須使用電話、電子郵件或到對方的辦公室進(jìn)行直接交流。并且,管理兩個(gè)辦公室需要有一定的經(jīng)費(fèi)支出,還需要購買多份參考手冊。
假設(shè),讓開發(fā)人員同在一間辦公室辦公,他們可以自由的對某個(gè)應(yīng)用程序設(shè)計(jì)進(jìn)行討論,也可以在紙或白板上輕易的繪制圖表,對設(shè)計(jì)觀點(diǎn)進(jìn)行輔助性闡釋?,F(xiàn)在,你只需要管理一個(gè)辦公室,只要有一套參考資料就夠了。遺憾的是,開發(fā)人員可能難以集中注意力,并且還可能存在資源共享的問題(比如,“參考手冊哪去了?”)
以上兩種方法,描繪了并發(fā)的兩種基本途徑。每個(gè)開發(fā)人員代表一個(gè)線程,每個(gè)辦公室代表一個(gè)處理器。第一種途徑是有多個(gè)單線程的進(jìn)程,這就類似讓每個(gè)開發(fā)人員擁有自己的辦公室,而第二種途徑是在單一進(jìn)程里有多個(gè)線程,如同一個(gè)辦公室里有兩個(gè)開發(fā)人員。讓我們在一個(gè)應(yīng)用程序中簡單的分析一下這兩種途徑。

并發(fā)方式

  • 多進(jìn)程
  • 多線程

并發(fā)時(shí)機(jī)

  • 分離關(guān)注點(diǎn)
    通過將相關(guān)的代碼與無關(guān)的代碼分離,可以使程序更容易理解和測試,從而減少出錯(cuò)的可能性。
  • 為了性能兩種方式利用并發(fā)提高性能:第一,將一個(gè)單個(gè)任務(wù)分成幾部分,且各自并行運(yùn)行,從而降低總運(yùn)行時(shí)間。這就是任務(wù)并行(task parallelism)。雖然這聽起來很直觀,但它是一個(gè)相當(dāng)復(fù)雜的過程,因?yàn)樵诟鱾€(gè)部分之間可能存在著依賴。區(qū)別可能是在過程方面——一個(gè)線程執(zhí)行算法的一部分,而另一個(gè)線程執(zhí)行算法的另一個(gè)部分——或是在數(shù)據(jù)方面——每個(gè)線程在不同的數(shù)據(jù)部分上執(zhí)行相同的操作(第二種方式)。后一種方法被稱為數(shù)據(jù)并行(data parallelism)。

實(shí)現(xiàn)并發(fā)

線程

線程thread)是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度和分派的最小單位。它被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)作單位。一個(gè)線程指的是進(jìn)程中一個(gè)單一順序的控制流,一個(gè)進(jìn)程中可以并行多個(gè)線程,每條線程并行執(zhí)行不同的任務(wù)。

同一進(jìn)程中的多條線程將共享該進(jìn)程中的全部系統(tǒng)資源,如虛擬地址空間,文件描述符信號處理等等。但同一進(jìn)程中的多個(gè)線程有各自的調(diào)用棧(call stack),自己的寄存器環(huán)境(register context),自己的線程本地存儲(thread-local storage)。

一個(gè)進(jìn)程可以有很多線程,每個(gè)線程并行執(zhí)行不同的任務(wù),每個(gè)進(jìn)程至少有一個(gè)線程,在程序啟動(dòng)時(shí)由系統(tǒng)創(chuàng)建,此線程被稱為主線程,負(fù)責(zé)程序主流程;在GUI程序中,也叫做UI線程,負(fù)責(zé)主流程消息循環(huán),界面刷新和重繪動(dòng)作。

在多核或多CPU,或支持Hyper-threading的CPU上使用多線程程序設(shè)計(jì)的好處是顯而易見,即提高了程序的執(zhí)行吞吐率。在單CPU單核的計(jì)算機(jī)上,使用多線程技術(shù),也可以把進(jìn)程中負(fù)責(zé)IO處理、人機(jī)交互而常被阻塞的部分與密集計(jì)算的部分分開來執(zhí)行,編寫專門的workhorse線程執(zhí)行密集計(jì)算,從而提高了程序的執(zhí)行效率。

OpenMP

OpenMP(Open Multi-Processing)是一套支持跨平臺共享內(nèi)存方式的多線程并發(fā)的編程API,使用C,C++Fortran語言,可以在大多數(shù)的處理器體系和操作系統(tǒng)中運(yùn)行,包括Solaris, AIX, HP-UX, GNU/Linux, Mac OS X, 和Microsoft Windows。包括一套編譯器指令、庫和一些能夠影響運(yùn)行行為的環(huán)境變量。

MPI

消息傳遞界面/接口(Message Passing Interface,縮寫MPI)是一個(gè)并行計(jì)算應(yīng)用程序接口(API),常在超級電腦、電腦簇等非共享內(nèi)存環(huán)境程序設(shè)計(jì)。

PPL

PPL(Parallel Patterns Library, 并行模式庫) 提供命令式編程模型,以促進(jìn)開發(fā)并發(fā)應(yīng)用程序的可擴(kuò)展性和易用性。 PPL 構(gòu)建在并發(fā)運(yùn)行時(shí)的計(jì)劃和資源管理組件上。 通過提供并行作用于數(shù)據(jù)的泛型安全算法和容器,提高應(yīng)用程序代碼與基礎(chǔ)線程機(jī)制之間的抽象級別。 使用 PPL 還可以開發(fā)通過為共享狀態(tài)提供替代方案實(shí)現(xiàn)縮放的應(yīng)用程序。

PPL 提供以下功能:

  • 任務(wù)并行︰ 一種機(jī)制,在 threadpool Windows 來并行執(zhí)行多個(gè)工作項(xiàng) (任務(wù)) 的工作原理

  • 并行算法︰ 在并發(fā)運(yùn)行時(shí)執(zhí)行操作的基礎(chǔ)上從事并行中的數(shù)據(jù)集合的泛型算法

  • 并行容器和對象︰ 提供對其元素的安全并發(fā)訪問的泛型容器類型

【參考資料】
OpenMP 入門教程
【并行計(jì)算】用MPI進(jìn)行分布式內(nèi)存編程(一)
【下一篇】
[C++并發(fā)編程實(shí)戰(zhàn)]創(chuàng)建多線程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容