本文摘要:多線程編程面臨巨大挑戰(zhàn),本篇 計(jì)算機(jī)論文 分析傳統(tǒng)的基于加鎖以及信號(hào)量做線程同步的方法已經(jīng)越來(lái)越不適應(yīng)性能要求;最新的基于無(wú)鎖算法的編程技術(shù)雖然能夠提升性能,但是實(shí)現(xiàn)的過(guò)程非常復(fù)雜,使得軟件開(kāi)發(fā)充滿了挑戰(zhàn)性! 電腦編程技巧與維護(hù) 》計(jì)算機(jī)科技
多線程編程面臨巨大挑戰(zhàn),本篇計(jì)算機(jī)論文分析傳統(tǒng)的基于加鎖以及信號(hào)量做線程同步的方法已經(jīng)越來(lái)越不適應(yīng)性能要求;最新的基于無(wú)鎖算法的編程技術(shù)雖然能夠提升性能,但是實(shí)現(xiàn)的過(guò)程非常復(fù)雜,使得軟件開(kāi)發(fā)充滿了挑戰(zhàn)性!電腦編程技巧與維護(hù)》計(jì)算機(jī)科技論文發(fā)表期刊,雜志1994年在北京市創(chuàng)刊,所刊內(nèi)容多以電腦編程實(shí)例解析為主題,展示項(xiàng)目開(kāi)發(fā)和應(yīng)用編程新思路、新方法及其編程的經(jīng)驗(yàn)和技巧,還有計(jì)算機(jī)領(lǐng)域科學(xué)研究、工程技術(shù)與應(yīng)用學(xué)術(shù)的論文和研究報(bào)告等。
摘要:隨著硬件性能的提高,多線程編程技術(shù)已經(jīng)成為軟件業(yè)的主流。文章首先介紹多線程編程所面臨的挑戰(zhàn),其次介紹ZeroMQ消息中間件可以如何應(yīng)對(duì)該問(wèn)題,并對(duì)其中的兩項(xiàng)關(guān)鍵技術(shù)做了分析,最后對(duì)采用ZeroMQ與傳統(tǒng)方法下多線程編程的性能進(jìn)行對(duì)比。
關(guān)鍵詞:ZeroMQ;多線程編程;阻塞;無(wú)鎖編程
1、多線程編程的挑戰(zhàn)
自摩爾定律提出以來(lái),CPU主頻一直以指數(shù)級(jí)的速度在增長(zhǎng)。為了充分利用硬件性能,改善程序體驗(yàn),軟件業(yè)廣泛采用了多線程編程技術(shù)。但是由于多個(gè)線程是動(dòng)態(tài)運(yùn)行的,使得這類程序的編寫(xiě)和調(diào)試異常困難[1-2]。與單線程程序相比,軟件開(kāi)發(fā)人員往往需要付出數(shù)十倍的精力。近幾年,隨著CPU主頻逐漸逼近物理極限,芯片工業(yè)逐步向多核發(fā)展,但新增加的CPU性能無(wú)法全面發(fā)揮出來(lái)。除了像Erlang[3]這樣的少數(shù)語(yǔ)言外,絕大多數(shù)編程語(yǔ)言,包括C和C++,并沒(méi)有提供對(duì)于并發(fā)編程的支持。在傳統(tǒng)多線程編程技術(shù)中,采用加鎖以及信號(hào)量的方式來(lái)實(shí)現(xiàn)線程同步。這樣的方式存在如下一些問(wèn)題:(1)編寫(xiě)以及維護(hù)這類代碼代價(jià)非常高昂。根據(jù)經(jīng)驗(yàn)估算,編寫(xiě)多線程代碼的成本是編寫(xiě)單線程代碼成本的10~100倍;(2)這類方法很難擴(kuò)展到更多線程。大多數(shù)多線程應(yīng)用使用2個(gè)線程(例如典型的生產(chǎn)者消費(fèi)者線程),有一些會(huì)用到3個(gè)或者4個(gè)。
這表明對(duì)于一個(gè)有著16個(gè)或者更多核心的CPU,其硬件性能沒(méi)有充分利用起來(lái);(3)即便代碼是多線程的,它往往也不能受益于多核CPU,因?yàn)椴煌木程間經(jīng)常彼此阻塞。開(kāi)發(fā)者很難發(fā)現(xiàn)精巧的多線程程序?qū)嶋H上已經(jīng)退化成了一個(gè)單線程;(4)即便在最理想的情況下,應(yīng)用程序被設(shè)計(jì)成避免大范圍使用加鎖操作,還是很難擴(kuò)展到超過(guò)10個(gè)核心的CPU上。隨著線程數(shù)以及CPU核數(shù)的增加,硬件資源的利用率會(huì)急劇下降;(5)線程被換入CPU中會(huì)引發(fā)程序的上下文切換,以及CPU緩沖區(qū)中的內(nèi)容失效,這也將極大地影響整個(gè)程序的執(zhí)行效率。為了避免加鎖導(dǎo)致的阻塞,最新的編程理論提出了無(wú)鎖算法來(lái)實(shí)現(xiàn)數(shù)據(jù)共享。該算法需要用到硬件指令集中的“比較以及交換原子操作”[4]來(lái)避免加鎖。為了達(dá)到無(wú)鎖編程的準(zhǔn)確性以及安全性,程序員需要具備硬件以及編譯器方面的知識(shí)背景。無(wú)鎖編程技術(shù)雖然提高了軟件性能,但是其高度復(fù)雜性使得軟件開(kāi)發(fā)過(guò)程充滿了挑戰(zhàn),所以這樣的技術(shù)目前并沒(méi)有獲得廣泛的使用。
2、ZeroMQ消息中間件技術(shù)
ZeroMQ是由iMatix公司開(kāi)發(fā)的一款開(kāi)源的消息中間件。最初的設(shè)計(jì)目標(biāo)是在股票交易系統(tǒng)中實(shí)現(xiàn)極快的數(shù)據(jù)交換,所以性能是設(shè)計(jì)的首要考慮因素。ZeroMQ看起來(lái)像是一套嵌入式的網(wǎng)絡(luò)鏈接庫(kù),但工作起來(lái)更像是一個(gè)并發(fā)式的框架。它可以在多種協(xié)議中傳輸消息,如線程間、進(jìn)程間、TCP、廣播等。開(kāi)發(fā)人員可以據(jù)此構(gòu)建多種連接模式,如:發(fā)布-訂閱、任務(wù)分發(fā)、請(qǐng)求-應(yīng)答等。它對(duì)幾乎所有主流語(yǔ)言均可支持,并能在幾乎所有的操作系統(tǒng)上運(yùn)行。ZeroMQ目前已經(jīng)在很廣泛的范圍內(nèi)獲得使用,包括:金融服務(wù)、游戲開(kāi)發(fā)、嵌入式系統(tǒng)、科學(xué)研究,以及航天系統(tǒng)中。為了達(dá)到高性能,ZeroMQ采用了兩項(xiàng)核心技術(shù)來(lái)實(shí)現(xiàn)高效的消息傳輸,分別為并發(fā)模型和無(wú)鎖隊(duì)列。
2.1ZeroMQ的并發(fā)模型
為了充分利用CPU的多核特性,ZeroMQ被設(shè)計(jì)成完全避免使用鎖,從而使得每個(gè)線程能夠全速運(yùn)行。線程之間的通信采用基于事件的異步消息發(fā)送模式,即經(jīng)典的參與者模式。它為每一個(gè)CPU核啟動(dòng)一個(gè)工作線程,從而避免了當(dāng)兩個(gè)線程共享一個(gè)核時(shí)所做的線程上下文切換操作(見(jiàn)圖1)。ZeroMQ的內(nèi)部對(duì)象緊密地與特定工作線程綁定到一起。這樣就不需要使用任何臨界區(qū)、鎖,以及信號(hào)量等同步操作。并且每個(gè)ZeroMQ內(nèi)部對(duì)象與特定的CPU核也是關(guān)聯(lián)的,這樣也避免了上下文切換,有效利用CPU緩存區(qū)機(jī)制。這種設(shè)計(jì)避免了傳統(tǒng)多線程開(kāi)發(fā)所面臨的諸多問(wèn)題,因?yàn)榫程之間不再需要共享對(duì)象。不過(guò)在該設(shè)計(jì)中,需要提供一個(gè)調(diào)度器。調(diào)度器采用基于事件驅(qū)動(dòng)的方式管理ZeroMQ內(nèi)部對(duì)象,從而避免了在整個(gè)循環(huán)中去檢測(cè)對(duì)象,也避免了對(duì)象長(zhǎng)時(shí)間地占用CPU這種情況。這樣,整個(gè)系統(tǒng)工作在異步模式下,所有的對(duì)象以狀態(tài)機(jī)的方式運(yùn)行。
2.2ZeroMQ的無(wú)鎖隊(duì)列
為了保證并發(fā)操作,ZeroMQ使用了無(wú)鎖隊(duì)列在用戶線程以及ZeroMQ工作線程之間交換數(shù)據(jù)。無(wú)鎖隊(duì)列中用到無(wú)鎖算法,該算法不依賴操作系統(tǒng)所提供的鎖以及信號(hào)量等機(jī)制實(shí)現(xiàn)數(shù)據(jù)共享,但是需要依賴CPU提供的原子操作。無(wú)鎖算法本質(zhì)上并不是“無(wú)鎖”的,只是它的鎖是在硬件層面上實(shí)現(xiàn)。此外,無(wú)鎖隊(duì)列的兩個(gè)特別設(shè)計(jì)使得其擁有很高的性能。第一個(gè)特點(diǎn)是:每個(gè)隊(duì)列對(duì)應(yīng)一個(gè)寫(xiě)線程和一個(gè)讀線程(見(jiàn)圖2)。在一個(gè)寫(xiě)線程對(duì)應(yīng)多個(gè)讀線程的通信環(huán)境下,ZeroMQ將創(chuàng)建多個(gè)隊(duì)列。這種讀寫(xiě)之間一一對(duì)應(yīng)的模式,加上無(wú)鎖操作,使得無(wú)鎖隊(duì)列的實(shí)現(xiàn)非常高效。第二個(gè)特點(diǎn)是:采用批處理的方法來(lái)寫(xiě)入或者讀取消息。雖然無(wú)鎖編程算法比傳統(tǒng)的基于信號(hào)量的算法更高效,但是CPU的原子操作很費(fèi)時(shí),特別是當(dāng)CPU的多個(gè)核之間存在競(jìng)爭(zhēng)時(shí)。為了解決這個(gè)問(wèn)題,ZeroMQ采用了批處理的方法來(lái)應(yīng)對(duì)。假設(shè)從網(wǎng)絡(luò)上收到了一個(gè)數(shù)據(jù)包,其中包含了10個(gè)小消息。為了將這些消息寫(xiě)入無(wú)鎖隊(duì)列中去,需要使用10次原子操作。ZeroMQ采用的方式是,先將單個(gè)消息保存到一個(gè)預(yù)寫(xiě)區(qū)域中,累積到一定數(shù)目后,使用一次原子操作,一起寫(xiě)入隊(duì)列中;類似地,在讀取時(shí)也應(yīng)用了預(yù)讀取緩沖區(qū)。
3、ZeroMQ性能驗(yàn)證
3.1測(cè)試方法
通過(guò)對(duì)ZeroMQ工作原理的分析,知道其性能無(wú)疑會(huì)超過(guò)傳統(tǒng)多線程方法的。但是這樣的性能差距到底有多大,需要通過(guò)實(shí)驗(yàn)來(lái)分析。ZeroMQ作為消息中間件可以在多種應(yīng)用場(chǎng)合傳遞消息。其中的線程間通信模式,使得其可以很好地用于多線程應(yīng)用程序。在其多種消息傳遞模型中,任務(wù)分發(fā)的消息模式特別適合典型的生產(chǎn)者-消費(fèi)者這種應(yīng)用形式。傳統(tǒng)多線程編程方法采用了互斥鎖以及信號(hào)量來(lái)實(shí)現(xiàn)生產(chǎn)者-消費(fèi)者線程之間的數(shù)據(jù)共享。每一個(gè)生產(chǎn)者線程與一個(gè)消費(fèi)者線程作為一個(gè)線程對(duì)。線程的執(zhí)行時(shí)間以生產(chǎn)者線程開(kāi)始工作,到消費(fèi)者線程處理完最后一個(gè)數(shù)據(jù)之間的時(shí)間間隔作為該線程對(duì)的執(zhí)行時(shí)間。多線程情況下,將各個(gè)線程對(duì)的執(zhí)行時(shí)間做相加處理。在每次測(cè)試期間,指定采用ZeroMQ的方法與采用傳統(tǒng)多線程的方法這兩種程序所處理的消息數(shù)是相等的。對(duì)不同條件下的執(zhí)行時(shí)間進(jìn)行統(tǒng)計(jì),從而比較哪種方法性能更優(yōu)。
3.2性能分析
通過(guò)測(cè)試,分別采用兩種方法的多線程程序所用的時(shí)間如表1所示。表1中的數(shù)據(jù)是在一個(gè)采用了超線程技術(shù)的2核i5CPU上執(zhí)行結(jié)果。從表1中可以看出,采用ZeroMQ的多線程編程方法比采用傳統(tǒng)的方法在各種情況下性能均占優(yōu)勢(shì),這表明其對(duì)于并發(fā)編程有更好的支持。此外,在與其他主流消息隊(duì)列,比如:RabitMQ、ActiveMQ以及MSMQ的性能比較中,ZeroMQ也大幅勝出?紤]到ZeroMQ在軟件開(kāi)發(fā)以及調(diào)試上的便利性,采用其進(jìn)行多線程軟件開(kāi)發(fā)將帶來(lái)巨大的成本優(yōu)勢(shì)。
4、結(jié)語(yǔ)
隨著CPU內(nèi)核數(shù)越來(lái)越多,如何有效地發(fā)揮硬件運(yùn)算能力成為越來(lái)越重要的任務(wù)。ZeroMQ這一消息中間件很好地彌補(bǔ)了性能與易用性之間的鴻溝,使得普通開(kāi)發(fā)人員也可以編寫(xiě)出高性能、可靠的軟件產(chǎn)品。
轉(zhuǎn)載請(qǐng)注明來(lái)自發(fā)表學(xué)術(shù)論文網(wǎng):http:///dzlw/14707.html