正文

基于任務(wù)的程序設(shè)計(jì)(14)

C#并行編程高級(jí)教程 作者:(美)Gastón C.Hillar


1.5  使用輕量級(jí)并發(fā)模型

Amdahl法則和Gustafson法則都沒有考慮引入并行所帶來的開銷。這兩個(gè)法則也沒有考慮到存在一些模式能夠?qū)⒋胁糠洲D(zhuǎn)換為能夠充分利用并行化的新算法。減少應(yīng)用程序中串行部分的代碼對(duì)于提高并行執(zhí)行單元的使用率而言非常重要。

在以前版本的.NET Framework中,如果想要在C#應(yīng)用程序(一個(gè)進(jìn)程)中并行地運(yùn)行代碼,那么您必須創(chuàng)建并管理多個(gè)線程(軟件線程)。因此,您必須編寫非常復(fù)雜的多線程代碼。將算法分解為多個(gè)線程、協(xié)調(diào)各個(gè)代碼單元、在代碼單元之間共享信息以及收集運(yùn)算結(jié)果等任務(wù)實(shí)在是非常復(fù)雜的程序設(shè)計(jì)工作。隨著邏輯內(nèi)核的增加,這個(gè)任務(wù)會(huì)變得更加復(fù)雜,因?yàn)槟枰ㄟ^更多線程來獲得更好的可擴(kuò)展性。

多線程編程模型的設(shè)計(jì)并不是為了幫助開發(fā)人員面對(duì)多核革命。事實(shí)上,創(chuàng)建新的線程需要執(zhí)行大量的處理器指令,而且可能會(huì)對(duì)已經(jīng)分解為并行化線程的代碼引入太大的開銷。很多有用的數(shù)據(jù)結(jié)構(gòu)和類在設(shè)計(jì)上并沒有考慮到被多線程訪問,因此,為了能夠?qū)崿F(xiàn)這一點(diǎn)還需要添加很多代碼。這些額外的代碼會(huì)使得開發(fā)人員的注意力偏離主要目標(biāo):通過并行執(zhí)行來提升性能。

由于這個(gè)多線程模型過于復(fù)雜,難以應(yīng)對(duì)多核革命,因此這個(gè)模型被稱為重量級(jí)并發(fā)(heavyweight concurrency)。這個(gè)模型加入了嚴(yán)重的開銷,需要編寫很多代碼來處理由于框架層次缺乏對(duì)多線程訪問的支持而帶來的問題,并且會(huì)導(dǎo)致代碼復(fù)雜難以理解。

由于以前版本的.NET Framework所提供的多線程模型和現(xiàn)代微處理器日益增長的邏輯內(nèi)核數(shù)引發(fā)的上述問題,促進(jìn)了允許創(chuàng)建并行化代碼的新模型的創(chuàng)建。這個(gè)新模型稱為輕量級(jí)并發(fā)(lightweight concurrency),這個(gè)模型減少了在不同邏輯內(nèi)核上創(chuàng)建和執(zhí)行代碼所需要的總開銷。這并不是說能夠完全消除并行化帶來的開銷,但是這個(gè)模型本身是為現(xiàn)代多核微處理器而設(shè)計(jì)的。重量級(jí)并發(fā)模型是在多處理器的時(shí)代出現(xiàn)的,在那個(gè)時(shí)代計(jì)算機(jī)可能有很多物理微處理器,每個(gè)微處理器只有一個(gè)內(nèi)核。輕量級(jí)的并發(fā)模型考慮了新的微架構(gòu),這個(gè)架構(gòu)中有很多由一些物理內(nèi)核支撐的邏輯內(nèi)核。

輕量級(jí)并發(fā)模型并不只是關(guān)注不同邏輯內(nèi)核之間的作業(yè)調(diào)度,它還在框架級(jí)別添加了對(duì)多線程訪問的支持,從而使得代碼更容易理解。

大多數(shù)現(xiàn)代程序設(shè)計(jì)語言都在向輕量級(jí)并發(fā)模型變革,幸運(yùn)的是,.NET Framework 4也加入了這一波變革。因此,所有能夠生成.NET應(yīng)用程序的托管語言都能夠充分利用這種新的模型并發(fā)揮其優(yōu)勢。

1.6  創(chuàng)建成功的基于任務(wù)的設(shè)計(jì)

有時(shí)候,必須對(duì)現(xiàn)有的解決方案進(jìn)行優(yōu)化才能夠充分利用并行化的優(yōu)勢。在這些情況下,您必須理解現(xiàn)有的串行設(shè)計(jì),或者理解提供了有限可擴(kuò)展性的并行化算法,然后再對(duì)現(xiàn)有設(shè)計(jì)進(jìn)行重構(gòu),從而使其獲得性能提升,而且不會(huì)引入問題或產(chǎn)生不同的結(jié)果。您既可以取問題的一小部分,或者也可以考慮整個(gè)問題,并創(chuàng)建出一個(gè)基于任務(wù)的設(shè)計(jì),然后就可以引入并行化了。在設(shè)計(jì)新解決方案的時(shí)候也可以采取同樣的技術(shù)。

遵循以下的步驟就可以創(chuàng)建出成功的基于任務(wù)的設(shè)計(jì):

(1) 將每個(gè)問題分解為很多子問題,完全不要去考慮順序執(zhí)行。

(2) 將每個(gè)子問題想象為下面三類中的一類:

● 能夠以并行的方式進(jìn)行處理的數(shù)據(jù)——對(duì)數(shù)據(jù)進(jìn)行分解以實(shí)現(xiàn)并行化。

● 需要很多任務(wù),而且能夠以某種復(fù)雜的并行化進(jìn)行處理的數(shù)據(jù)流——對(duì)數(shù)據(jù)和任務(wù)進(jìn)行分解以實(shí)現(xiàn)并行化。

● 可以并行運(yùn)行的任務(wù)——對(duì)任務(wù)進(jìn)行分解以實(shí)現(xiàn)并行化。

(3) 將設(shè)計(jì)組織為能夠表達(dá)并行化的形式。

(4) 考慮將不同子問題連接起來的任務(wù)的必要性。盡可能地避免依賴性。

(5) 在進(jìn)行設(shè)計(jì)的時(shí)候,心里要想著并發(fā)和潛在的并行化。

(6) 分析并行化的問題的執(zhí)行計(jì)劃,考慮當(dāng)前的多核微處理器和未來的架構(gòu)。在設(shè)計(jì)的時(shí)候要準(zhǔn)備好更高的可擴(kuò)展性。

(7) 盡可能減少臨界區(qū)。

(8) 盡可能通過基于任務(wù)的程序設(shè)計(jì)實(shí)現(xiàn)并行化。

(9) 調(diào)優(yōu)和迭代。

上述步驟并不是說所有的子問題都必須是運(yùn)行在不同線程中的并行化任務(wù)。設(shè)計(jì)的時(shí)候必須考慮并行化的可能性,然后在編寫代碼的時(shí)候,可以根據(jù)性能和可擴(kuò)展性的目標(biāo)選擇最佳的實(shí)現(xiàn)方式。重要的是要以并行方式進(jìn)行思考,將要解決的工作分解為任務(wù)。通過這種方式,您就能夠按照需要對(duì)代碼進(jìn)行并行化。如果您已經(jīng)擁有一個(gè)面向傳統(tǒng)串行執(zhí)行的設(shè)計(jì),那么您將需要努力通過基于任務(wù)的程序設(shè)計(jì)技術(shù)對(duì)現(xiàn)有設(shè)計(jì)進(jìn)行并行化。


上一章目錄下一章

Copyright ? 讀書網(wǎng) www.dappsexplained.com 2005-2020, All Rights Reserved.
鄂ICP備15019699號(hào) 鄂公網(wǎng)安備 42010302001612號(hào)