李劭卓
(河北農(nóng)業(yè)大學(xué)渤海校區(qū),黃驊 061000)
在計算機(jī)發(fā)展史上,計算機(jī)從單線程發(fā)展到了多線程,多線程的出現(xiàn)很大程度上提升了計算機(jī)的性能,但是在人類科技發(fā)展的需求以及摩爾定理的限制下,單核處理機(jī)系統(tǒng)已經(jīng)到達(dá)極限。為了響應(yīng)更多計算機(jī)性能方面的需求,適應(yīng)計算機(jī)發(fā)展的需要,計算機(jī)已開始從單處理器系統(tǒng)向多處理器系統(tǒng)發(fā)展。
在多核處理機(jī)系統(tǒng)的快速發(fā)展中,多核系統(tǒng)編程(任務(wù)識別、平衡、數(shù)據(jù)分割、數(shù)據(jù)依賴、測試與調(diào)試)和程序正確性(同步與死鎖)的兩個方面難題越發(fā)突出。為了解決這些難題并設(shè)計出更好的多線程程序,人們開始通過編譯器與運行時庫來創(chuàng)建和管理多線程,即隱式線程(implicit threading),基于隱式線程與多線程的主要設(shè)計方法有三種:線程池(Thread pool)、OpenMP、大中央調(diào)度(Grand Central Dispatch,GCD)。
當(dāng)多線程服務(wù)器接收到一個請求時,如果采用創(chuàng)建一個新的線程去處理請求會出現(xiàn)兩種問題。第一種:創(chuàng)建新的線程需要時間并且在處理后會被丟失,第二種:沒有限制系統(tǒng)內(nèi)部并發(fā)執(zhí)行線程的數(shù)量。這兩個問題會導(dǎo)致系統(tǒng)響應(yīng)速度以及性能的降低。
而線程池的出現(xiàn)為線程的創(chuàng)建、銷毀以及資源不足的問題提供了解決方案。在進(jìn)程開始的時候,系統(tǒng)就創(chuàng)建一定數(shù)量的線程,并將這些線程加入池中等待喚醒,當(dāng)服務(wù)器收到請求時,服務(wù)器就喚醒一個可用的線程,然后將需要服務(wù)的請求傳遞給該線程,待線程完成服務(wù)之后,再重新返回到線程池中等待下一次喚醒,若沒有可用的線程,則服務(wù)器就會開始等待,直到有空線程為止。
優(yōu)點:
(1)提高了系統(tǒng)的響應(yīng)速度。系統(tǒng)已經(jīng)創(chuàng)建好了一定數(shù)量的線程,當(dāng)有請求到來時,可直接使用預(yù)先建立好的線程,不需要重新創(chuàng)建線程,這消除了系統(tǒng)創(chuàng)建線程時的時間延遲。
(2)線程池限制了任何時刻的可用線程的數(shù)量。系統(tǒng)預(yù)先創(chuàng)建一定數(shù)量的線程,并且限制它們的數(shù)量,這能夠控制線程對象在內(nèi)存中的消耗。十分有利于有大量并發(fā)式訪問,而其任務(wù)短小的服務(wù)器。
(3)將待執(zhí)行任務(wù)從創(chuàng)建任務(wù)的機(jī)制中分離出來。允許使用延遲或定期執(zhí)行的策略運行任務(wù)。
(4)降低系統(tǒng)的開銷與資源的消耗。線程池中的線程被重復(fù)利用,使用后的線程會重新返回到線程池中,不會被銷毀,降低了虛擬機(jī)垃圾回收方面的開銷。
缺點:
(1)需要考慮線程池的大小。線程池中的線程并非越多越好,需要結(jié)合軟硬件的具體環(huán)境以及應(yīng)用程序自身的特點來考慮。
(2)線程泄露。當(dāng)線程執(zhí)行完任務(wù)后,沒有返回到線程池中。需要采取異常捕捉的方法防止線程泄露。
(3)并發(fā)錯誤。要從邏輯上考慮線程的并發(fā)狀況,防止死鎖的出現(xiàn)。
OpenMP是一種支持共享內(nèi)存環(huán)境的多處理器多線程并行編譯語言,它由一組編譯指令和API組成,其通過向C、C++、Fortran語言提供一組和平臺無關(guān)的編譯指令、函數(shù)調(diào)用、指導(dǎo)函數(shù)以及環(huán)境變量,來指示OpenMP運行時庫在何時何處才能進(jìn)行并行處理。
并行處理的指示指令為#pragma omp parallel,當(dāng)程序進(jìn)行到指示指令時,系統(tǒng)就會創(chuàng)建一個與系統(tǒng)處理器數(shù)量一樣多的線程。原線程(主線程)與新派生出來的線程(組的從屬線程)組成線程組,即從單個線程執(zhí)行轉(zhuǎn)換為多線程并行執(zhí)行,待程序執(zhí)行完并行區(qū)域(parallel fegion)的所有內(nèi)容后,系統(tǒng)將會把并行線程的所得結(jié)果連接在一起,并重新開始單個線程執(zhí)行,此通常用于循環(huán)結(jié)構(gòu)的并行化處理。
除提供并行化指令外,OpenMP還允許手動設(shè)置線程數(shù)量、指定哪個數(shù)據(jù)可在線程間共享、哪個數(shù)據(jù)只屬于某個線程,其支持的操作系統(tǒng)有Windows、Linux、Mac OS X,并可用于多種開源編譯器和商用編譯器。
優(yōu)點:
(1)有利于多核升級后的程序性能。多核編程需要考慮到今后硬件核數(shù)升級之后的程序性能問題,如果將程序設(shè)計為隨CPU核數(shù)增長,就無法固定線程的數(shù)量;如果固定線程數(shù)量并且要求CPU核數(shù)增加時,程序性能也要增加,則需要在每次硬件核數(shù)升級后,程序進(jìn)行相對應(yīng)的更改。OpenMP可直接根據(jù)CPU的核數(shù)創(chuàng)建線程,這十分方便。
(2)并行區(qū)域執(zhí)行方便。多核編程中,需要將并行部分均分到各個CPU核心中,這對計算的負(fù)載均衡要求很高,但OpenMP可直接將并行區(qū)域的代碼分解為多個線程執(zhí)行。
(3)方便移植。OpenMP是標(biāo)準(zhǔn)規(guī)范,所有支持OpenMP的編譯器執(zhí)行標(biāo)準(zhǔn)一致。
缺點:
(1)使用范圍有限。OpenMP是一種支持共享內(nèi)存環(huán)境的多處理器多線程并行編譯語言,在非共享內(nèi)存系統(tǒng)中無法使用。
(2)高層抽象的局限性。OpenMP在需要復(fù)雜線程同步與互斥場合中不適用。
大中央調(diào)度是Apple Mac OS X和iOS的一種技術(shù),它能為C語言、API和運行時庫提供一組擴(kuò)展,允許多個代碼區(qū)域并行運行。
GCD在C與C++中增加了塊(block)的擴(kuò)展,用字符加{ }的形式將塊括起來,同時以一個塊為獨立單位,然后將各個塊放入調(diào)度隊列(dispatchqueue)中,在執(zhí)行程序時
,每次從調(diào)度隊列中取出一個塊,并將它分配給線程池中的一個可用線程。
調(diào)度隊列有兩種形式:串行(serial)和并行(concurrent)。
串行:
串行隊列以先進(jìn)先出的形式進(jìn)行塊的執(zhí)行,每次只能執(zhí)行一個塊,每當(dāng)一個塊執(zhí)行完后,才會從調(diào)度隊列中調(diào)度下一個塊。在進(jìn)程中可以有多個串行隊列,但是只能有一個主隊列,其用于保證任務(wù)的順序的正確性。
并行:
并發(fā)隊列也以先進(jìn)先出的進(jìn)行塊的執(zhí)行,但是每次可以執(zhí)行多個塊,進(jìn)行多個塊的并行運行。
在大中央調(diào)度中的線程池由POSIX線程組成,GCD會根據(jù)應(yīng)用需求以及系統(tǒng)的容量動態(tài)地調(diào)節(jié)線程的數(shù)量,以此實現(xiàn)對內(nèi)部線程池的管理。
優(yōu)點:
(1)GCD更加接近底層。GCD提供底層函數(shù),在追求性能的底層操作中,速度很快,并提供更強大的控制力。
(2)系統(tǒng)資源利用率高??梢院唵蔚卦诓煌a中傳遞上下文,減少上下文之間的切換,提高資源的利用率,減輕系統(tǒng)的負(fù)荷。
缺點:
操作實現(xiàn)復(fù)雜。GCD需要許多代碼來實現(xiàn)異步操作之間的事務(wù)性、順序行和依賴關(guān)系。
線程構(gòu)造模塊(Treading Building Block,TBB):
一種由Intel開發(fā)用于并行編程的C++線程庫,它不需要線程編程,允許運行時庫自動地將邏輯并行映射到線程中,有效地利用了CPU資源,而且可以與其他線程兼容,實現(xiàn)無縫共存。
Java.util.concurrent:
一種Java語言用于并行編程的實用工具類,它包括了幾個已經(jīng)標(biāo)準(zhǔn)化的可擴(kuò)展框架和一些提供有用功能的類。
多核多線程已成為處理器發(fā)展的一個大方向,它能提升計算機(jī)的性能,但面臨著多核系統(tǒng)編程和程序正確性上的兩個方面難題,隱式多線程可以有效地解決與緩解這兩方面問題。
雖然隱式多線程實現(xiàn)技術(shù)很多,但其核心思想是控制系統(tǒng)中線程的數(shù)量,利用已有線程執(zhí)行任務(wù)、創(chuàng)建線程數(shù)量要與計算機(jī)處理核心相匹配以及動態(tài)地調(diào)用線程數(shù)量。