国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

針對程序代碼語句級能耗優(yōu)化方法

2018-08-15 08:59:44黃天明錢德沛欒鐘治
關(guān)鍵詞:程序運(yùn)行程序代碼數(shù)組

黃天明,錢德沛,欒鐘治

北京航空航天大學(xué),北京 100191

引言

隨著計算機(jī)和互聯(lián)網(wǎng)的蓬勃發(fā)展,給人類提供越來越多便利的同時其消耗的巨大能源也引起關(guān)注。美國能源部門指出一個數(shù)據(jù)中心的能耗超過一個典型商業(yè)建筑的100 倍之多[3];同時研究機(jī)構(gòu)表明運(yùn)行一個300 瓦的微小型服務(wù)器一年的電費(fèi)以達(dá)到 338 美元,排出的二氧化碳多達(dá) 1300 千克[4];并且對于有著龐大集群的數(shù)據(jù)中心,其年均電量的消耗占了全球電量的1.3%,而這個比例在 2020 可能會達(dá)到 8%[5],數(shù)據(jù)中心消耗的電能已經(jīng)超過許多國家的對電能的消耗[6]。面向可持續(xù)發(fā)展的低成本、低能耗的新型計算系統(tǒng)、模型和應(yīng)用的研究, 或稱為綠色計算,已成為未來信息技術(shù)領(lǐng)域面臨的重大挑戰(zhàn)。

對綠色計算的研究主要分為硬件層面和軟件層面。電能由硬件層消耗,很多研究考慮開發(fā)出功耗更低的硬件,在保證系統(tǒng)運(yùn)行效率的同時降低能耗;然而,運(yùn)行在硬件之上的軟件,作為資源的消費(fèi)者,如果能夠進(jìn)行合理的管理減少資源的使用,或者提高資源的利用率節(jié)能效果更加顯著,尤其在集群環(huán)境下,合理的管理和調(diào)度能夠減少數(shù)據(jù)中心大量的能耗使用,如文獻(xiàn) [7] 所說,采用 Facebook 自主研發(fā)的調(diào)度技術(shù)能夠使得其數(shù)據(jù)中心每年減少大約 16% 的能耗消耗。

計算機(jī)系統(tǒng)除去在互聯(lián)網(wǎng)行業(yè)的應(yīng)用,在科學(xué)研究及工業(yè)設(shè)計制造領(lǐng)域也被廣泛用來進(jìn)行復(fù)雜的數(shù)值計算,也就是科學(xué)計算??茖W(xué)計算是計算機(jī)為解決科學(xué)研究和工程中的數(shù)學(xué)問題進(jìn)行的計算,具有能夠進(jìn)行無損傷模擬實(shí)驗(yàn),全過程全時空診斷實(shí)驗(yàn)以及短時間低成本大量重復(fù)實(shí)驗(yàn)等優(yōu)點(diǎn)廣泛被數(shù)學(xué)、物理和生物等領(lǐng)域研究人員采用[8]。這類計算往往特別復(fù)雜及持續(xù)較長時間,同時由于程序編寫人員往往是科研工作者或者非信息技術(shù)方向工程師,編寫程序只關(guān)注了其功能,而容易忽略效率,所以這類軟件的能耗有著很大的優(yōu)化空間。雖然科學(xué)計算所消耗的能源在所有計算機(jī)系統(tǒng)中所占比例不高,但如果能降低計算時的能耗對于科學(xué)研究及工程制造起到降低成本的作用,同時也能夠減少碳排放。

本文針對軟件能耗優(yōu)化中代碼優(yōu)化這一方向進(jìn)行研究,分析代碼中能耗低效代碼,提出改進(jìn)方案,最后使用基于多個硬件部件性能計數(shù)器建立的模型驗(yàn)證方法的有效。

1 軟件能耗優(yōu)化方法

軟件能耗優(yōu)化并非一個新的研究領(lǐng)域,對于嵌入式軟件的能耗優(yōu)化研究非常成熟,使得這些多是運(yùn)行在電池供電系統(tǒng)上的軟件能夠在能源受限的情況下有更長的運(yùn)行時間[9]。由于通用計算領(lǐng)域芯片指令集復(fù)雜,所以對于通用計算平臺軟件能耗優(yōu)化的研究還有較大發(fā)展空間。

圖1 代碼變換步驟圖Fig.1 Code transformation step diagram

本文針對軟件的具體代碼,研究其能耗優(yōu)化的方法,稱為面向代碼的能耗優(yōu)化。按照優(yōu)化的對象,面向代碼的能耗優(yōu)化又可以分為指令級、語句級和模塊級三類[10]。指令級優(yōu)化可采用編譯器提供的命令優(yōu)化代碼能耗,粒度??;語句級能耗優(yōu)化試圖采用更高效低能耗的代碼結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu)來降低能耗,這一層級貼近程序編寫和調(diào)試人員,能夠?qū)λ麄冞M(jìn)行能耗調(diào)試指導(dǎo),本文研究的層級就是語句級能耗優(yōu)化;模塊級能耗優(yōu)化是根據(jù)上下文選擇能耗更低的算法或模塊設(shè)計方法,來對能耗進(jìn)行優(yōu)化。

1.1 語句級能耗優(yōu)化

在程序設(shè)計中,程序變換(Program Transformation)是指由現(xiàn)有程序 P 生成新程序 P' 的過程,且 P 和 P'等價,語句級能耗優(yōu)化的變換,是在不改變代碼功能的前提下,通過改變語句,將能耗較高的代碼優(yōu)化為能耗較低的代碼。

對程序代碼語句進(jìn)行能耗優(yōu)化一般遵循以下三個原則:

(1) 化復(fù)雜計算為簡單計算,化復(fù)雜數(shù)據(jù)結(jié)構(gòu)為簡單數(shù)據(jù)結(jié)構(gòu),減少計算能夠減少對硬件部件的使用,降低能耗;

(2) 優(yōu)先使用高性能的存儲部件,如緩存優(yōu)先于內(nèi)存,內(nèi)存優(yōu)先于磁盤,減少數(shù)據(jù)交換時間,降低能耗

(3) 充分利用 CPU 資源減少等待時間,由于計算機(jī)硬件上計算部件和存儲部件的速度不匹配,經(jīng)常出現(xiàn)處理器等待數(shù)據(jù)的情況,同時由于任務(wù)調(diào)度問題也會讓 CPU 處于空閑狀態(tài),造成能源消耗。

本文針對代碼語句中數(shù)據(jù)存儲部分一種低效冗余情況進(jìn)行能耗優(yōu)化,也就是寫入之后沒有讀的無效寫入。

1.2 無效寫入

實(shí)際代碼運(yùn)行過程中,存在一種情況,當(dāng)對存儲器同一個位置連續(xù)兩次進(jìn)行成功的寫入操作,但中間沒有讀的時候,或者對某個位置進(jìn)行一次寫入后直到程序終止都沒有讀取該位置的值,那么第一次寫入就沒有意義,造成了冗余操作,也就是DeadSpy[11]。

列表1 中第19行和第二十行產(chǎn)生了一次無效寫入,因?yàn)榈?9行的Foo 函數(shù)給數(shù)組 a 賦值時對內(nèi)存進(jìn)行寫入,在沒有讀取它的值的情況下,第20行的Bar 函數(shù)再一次給數(shù)組a賦值,最后第21行的Foo1 函數(shù)才讀取了數(shù)組 a 的值,所以第19行的Foo 函數(shù)里面的對數(shù)組 a 的賦值語句便是無效寫入。

實(shí)際生產(chǎn)中,由于程序編寫人員的編寫習(xí)慣,在缺乏事先對程序整體用到的存取指令完全預(yù)測了解的情況下,容易寫一些冗余的存取代碼。例如在申請某個數(shù)組的時候會給其賦予初始值,但是在真正用到時會再一次賦值,這便造成了無效寫入?,F(xiàn)代編譯器在對代碼進(jìn)行優(yōu)化時針對這方面的冗余存取,顯得低效,但這種情況在實(shí)際生產(chǎn)代碼中并不少見,針對這方面冗余操作進(jìn)行優(yōu)化將能夠顯著提高代碼的能耗效率。

2 程序代碼無效寫入定位方法

前文所描述的程序代碼語句中無效寫入的數(shù)據(jù)存儲情況,使用基于 Intel Pin 的一個對程序運(yùn)行時上下文及數(shù)據(jù)屬性分析的一個庫 CCTlib[12]開發(fā)的客戶端工具對程序執(zhí)行時存取指令進(jìn)行分析,該庫使用C++ 語言編寫,運(yùn)行在 Linux 平臺,用戶能夠利用這個庫開發(fā)出自己的程序分析工具?;谠摴ぞ呓o出的API,結(jié)合前文描述的無效寫入的低效代碼情況,分析出代碼中這種語句的存在,進(jìn)行優(yōu)化改進(jìn),從而實(shí)現(xiàn)對程序代碼的能耗優(yōu)化。

列表1 無效寫入示例圖List1 The example of invalid write

2.1 Intel Pin

Pin 是一個動態(tài)二進(jìn)制指令插樁工具,它提供了一套豐富的接口給用戶使用,用戶能夠利用這些接口實(shí)現(xiàn)對程序不同粒度的分析,如模塊級、函數(shù)級、調(diào)用鏈和指令級等。其中,調(diào)用鏈 (trace) 是 Pin 使用的一個專用術(shù)語,表示一個調(diào)用的多個退出方式,例如一個調(diào)用鏈以一個分支處作為起點(diǎn),可以以函數(shù)調(diào)用、返回或者跳轉(zhuǎn)作為終點(diǎn)。

使用 Pin,可以對程序執(zhí)行中每條讀寫指令進(jìn)行插樁追蹤,為分析程序?qū)?nèi)存訪問情況提供依據(jù)。

2.2 CCTLib

CCTLib 是由 Milind Chabbi 等人開發(fā)的一款基于 Intel Pin 的庫,能夠分析出程序執(zhí)行過程中的調(diào)用上下文,并以此建立一棵調(diào)用關(guān)系樹 (calling context tree,CCT)[12],CCT 的每一個分支代表了一個指令調(diào)用序列,而每一個葉子結(jié)點(diǎn)代表了一條具體的指令。CCT 能為用戶提供對于程序指令插樁分析的API,如打印指令調(diào)用路徑、指令執(zhí)行情況等。利用這些API,用戶可開發(fā)客戶端工具用來追蹤分析程序執(zhí)行過程中上下文調(diào)用情況。以下是 CCTLib 主要幾個API 的介紹。

2.3 無效寫入判定

使用 Intel Pin 逐條插樁分析程序指令,將內(nèi)存地址的存取操作記錄情況構(gòu)建一個狀態(tài)機(jī)。狀態(tài)機(jī)狀態(tài)變換為對于每一個用到的內(nèi)存地址初始標(biāo)記為 V(Virgin),表示沒有對其進(jìn)行存取操作,當(dāng)進(jìn)行了存取操作時,根據(jù)操作的類型將狀態(tài)置為 R (Read) 或者W (Write)。根據(jù)對同一地址的存取操作,狀態(tài)機(jī)實(shí)現(xiàn)狀態(tài)轉(zhuǎn)移。出現(xiàn)以下兩種情況會判定為無效寫入:(1)當(dāng)出現(xiàn)連續(xù)兩次寫操作,中間沒有讀操作時;(2) 在程序結(jié)束時,處于W狀態(tài)的內(nèi)存地址,即是改地址進(jìn)行最后一次寫操作后,程序直到運(yùn)行結(jié)束也沒有對其進(jìn)行讀取。

狀態(tài)機(jī)中 Halt 指令代表該地址知道結(jié)束都沒有再進(jìn)行存取操作,Report Dead行為表示檢查出無效寫入,可以匯報。由于該狀態(tài)機(jī)從程序開始到結(jié)束記錄每一個內(nèi)存存取操作,可以避免出現(xiàn)假陽性或者假陰性的情況,判斷結(jié)果可靠。

2.4 無效寫入追蹤與記錄

文本使用基于 CCTLib 開發(fā)客戶端工具,該工具使用 Pin 分析追蹤每一條程序指令,建立指令調(diào)用上下文樹 CCT,此時的CCT 的每一個分支代表了一個指令調(diào)用序列,而每一個葉子結(jié)點(diǎn)代表了一條“寫”指令。程序執(zhí)行完以后,將每個無效寫入以一對 CCT分支的形式展示給用戶。

具體在 CCTLib 上實(shí)現(xiàn)為在 Linux 平臺上使用影子內(nèi)存 (shadow memory)[13]將每個內(nèi)存位置的狀態(tài)保存。為了追蹤到無效寫入,對地址 M 的每條存取指令,都要根據(jù)圖2 的狀態(tài)機(jī)更新其狀態(tài) STATE (M),同時保存恢復(fù)其上下文調(diào)用的指針,在遇到需要報告無效寫入時返回句柄。客戶端工具維護(hù)一個隨著程序執(zhí)行展開的動態(tài)增長的調(diào)用關(guān)系樹,這個調(diào)用樹的每條分支代表一個調(diào)用棧。在每個調(diào)用 (call) 指令和返回 (return) 指令之前插樁,如果是調(diào)用指令,在調(diào)用新的節(jié)點(diǎn)時則創(chuàng)建新的分支;如果是返回指令,將全局的當(dāng)前節(jié)點(diǎn)作為父節(jié)點(diǎn)。

當(dāng)創(chuàng)建的調(diào)用關(guān)系樹中節(jié)點(diǎn)依據(jù)圖2狀態(tài)機(jī)轉(zhuǎn)移狀態(tài)時進(jìn)入到無效寫入狀態(tài)時,將該記錄的相關(guān)信息以一個三元組的形式記入一個表格 DeadTable,三元組的格式為 <dead context pointer, killing context pointer, frequency>。其中dead context pointer表示給一個地址寫入了值,但未讀取過的指令的句柄指針,這種指令可能成為無效寫入指令的第一次寫入;killing context pointer 表示寫入了一個 dead context 的地址的指令句柄指針,中間沒有讀取操作,表示當(dāng)前指令已經(jīng)產(chǎn)生無效寫入;frequency 表示無效寫入指令對的頻率。

表1 CCTLib 主要 API 介紹Table 1 Introduction of CCTLib main APIs

圖2 無效寫入狀態(tài)轉(zhuǎn)移圖Fig.2 Invalid write state transition diagram

當(dāng)程序運(yùn)行結(jié)束時,將寫入 DeadTable 的三元組按照頻率逆序排列,同時遍歷記錄的句柄指針在調(diào)用關(guān)系樹 CCT 中的父節(jié)點(diǎn)獲得完整的調(diào)用鏈,將該信息呈現(xiàn)給用戶,用戶根據(jù)這些調(diào)用鏈的信息反過來看程序源碼,對其進(jìn)行調(diào)試。

3 程序代碼無效寫入優(yōu)化

在獲取到用基于 CCTLib 編寫的客戶端工具分析出的無效寫入指令調(diào)用鏈后,需要這些指令的源代碼部分進(jìn)行調(diào)試改進(jìn),從而對程序運(yùn)行能耗起到優(yōu)化。

3.1 優(yōu)化方法

根據(jù)觀察分析一些典型的程序,例如 SPEC CPU2006[14]中 benchmark 發(fā)現(xiàn),產(chǎn)生無效寫入的原因可能不是簡單如列表1 所示那樣是程序編寫人員的編寫習(xí)慣不佳,有可能是數(shù)據(jù)結(jié)構(gòu)選取的不合理以及分支規(guī)劃的冗余,這些都能在接下來的例子中見到。

像列表1 所示那中編寫冗余,可以選擇在不影響程序正常功能的情況下直接刪除冗余部分代碼;對于編寫習(xí)慣更好質(zhì)量更高的工業(yè)生產(chǎn)程序代碼,產(chǎn)生無效寫入的原因更加隱晦,同時由于程序更加復(fù)雜,修改起來需要更多的分析。以下是 SPEC CPU2006 中一些 benchmark 的無效寫入情況分析和優(yōu)化方法。

3.2 403.gcc 優(yōu)化舉例

對于 403.gcc,經(jīng)過對各個輸入的測試,發(fā)現(xiàn)對于輸入 c-typeck.i,gcc的無效寫入非常多,占到了整個訪存量的73% ,針對于輸入 c-typeck.i,做以下分析和優(yōu)化。

在列表2 中,展示了在輸入為 c-typeck.i 時,gcc運(yùn)行時常用到的一個函數(shù) loop.c,函數(shù)在列表2部分的功能如下:

(1) 在第3行,將給數(shù)組 last_set 分配 132KB 的空間,共有 16937個元素,每個元素占位 8KB。

(2) 5-12行,遍歷傳入的參數(shù) loop 中每條指令。

(3) 7-8行,如果指令匹配一個模式,則調(diào)用count_one_set 函數(shù),該函數(shù)的功能是通過最后一條設(shè)置虛擬寄存器的指令更新 last_set。

(4) 10-11行,如果之前的模塊完成,那么通過調(diào)用 memset 函數(shù)來重置整個 last_set 數(shù)組,以便在下個循環(huán)中使用。

該段代碼會產(chǎn)生大量的無效寫入,經(jīng)過分析發(fā)現(xiàn)由于程序花費(fèi)大量時間對 last_set 數(shù)組進(jìn)行重置清零,但在之前用到它的模塊中,每次只使用了該數(shù)組極少量的元素,但一開始分配就給 last_set 可能用到的最大的數(shù)組大小,也就是會有大量的元素在沒有被訪問的情況下被重復(fù)重置清零,也就是重復(fù)對其寫入0,所以造成了大量的無效寫入。

顯然,該程序在該片段對于 last_set 數(shù)組的訪問很是少量,但是直接給其分配大量的元素單個循環(huán)中對其訪問的元素極少,在每個循環(huán)結(jié)束都需要初始化數(shù)組的情況下,會造成很多無效的寫入。經(jīng)過抽樣發(fā)現(xiàn),對于某個 last_set 數(shù)組的元素在連續(xù) 34個memset 函數(shù)調(diào)用周期中,被用到的中位數(shù)為 2;同時在 99.6% 的情況下每個周期只有 22個不同的元素會被寫入新的值。

于是,一個簡單的優(yōu)化方案為:維護(hù)一個大小為 22個元素的數(shù)組,記錄 last_set 數(shù)組修改過的元素的下標(biāo),下次重置清零時只重置數(shù)組保存的下標(biāo)的元素,而不去重置整個 132KB 的數(shù)組;如果遇到數(shù)組溢出,也就是一個周期中被修改的元素超過 22個,也就是需要清零的元素超過 22個,那么周期結(jié)束時調(diào)用 memset 重置整個數(shù)組。

同時,在 403.gcc 的另一個函數(shù) cselib.c 中也存在無效寫入的代碼,在列表3 中,該段代碼中宏VARRY_ELT_LIST_INIT 分配數(shù)組并初始化為0,之后函數(shù) clear_table 再一次將數(shù)組初始化為 0,顯然這產(chǎn)生了無效寫入。通過閱讀源碼發(fā)現(xiàn),clear_table 函數(shù)還有更輕量級的實(shí)現(xiàn),該實(shí)現(xiàn)并不會初始化數(shù)組reg_values,所以此處應(yīng)是調(diào)用了功能更加復(fù)雜的接口造成了無效寫入。

通過開發(fā)的工具對 403.gcc 分析還發(fā)現(xiàn)了一些無效寫入,不在此一一列舉。

3.3 Chombo 優(yōu)化舉例

本節(jié)將對一個科學(xué)計算程序 amrGodunov3d 其中的無效寫入進(jìn)行分析和優(yōu)化。其中,amrGodunov3d是 Chombo[15]中一個標(biāo)準(zhǔn)測試程序,Chombo 是一個使用塊結(jié)構(gòu)以及自適應(yīng)細(xì)化網(wǎng)絡(luò)求解偏微分方程的框架,但由于設(shè)計時細(xì)節(jié)欠考慮,出現(xiàn)了很多低級的無效寫入情況。下面將會舉 amrGodunov3d 中的無效寫入例子進(jìn)行分析,程序運(yùn)行時的輸入采用程序包提供的common.input。

列表2 gcc 無效寫入示例 1List2 The invalid write code in 403.gcc(1)

列表3 gcc 無效寫入示例 2List3 The invalid write code in 403.gcc(2)

列表4 所列出的代碼片段位于 Chombo-3.2 的示例程序 amrGodunov 下的PolytropicPhysicsF.ChF 文件中,該段代碼位于計算密集型的黎曼解算器內(nèi)核的三層嵌套循環(huán)中,該內(nèi)核工作在一個存儲著 8 字節(jié)實(shí)數(shù)的四維數(shù)組上。根據(jù)分析無效寫入的工具輸出顯示,第1-3行的賦值會被 6-8行的覆蓋,而 6-8行又會被12-14行的覆蓋,這顯然是對條件分支語句的使用不當(dāng)造成的。如果對該段代碼稍作修改,修改 if-else 的結(jié)構(gòu),賦值條件不變,順序從后往前顛倒,即賦值方式為原 12-14行、原 6-8 和原 1-3行依次根據(jù)條件判斷進(jìn)行賦值操作,通過條件分支跳過不必要的賦值操作,該部分的無效寫入即被消除,修改方式如列表5。

表4 中給出了在對 amrGodunov3d 進(jìn)行無效寫入優(yōu)化前后在單節(jié)點(diǎn)狀態(tài)下運(yùn)行時的能耗的變化。

列表4 amrGodunov3d 無效寫入示例List4 The invalid write code in amrGodunov3d

列表5 amrGodunov3d 無效寫入修改方案List5 The modification scheme of the invalid write in List4

4 實(shí)驗(yàn)驗(yàn)證

本章實(shí)驗(yàn)為了驗(yàn)證前文中提出的無效寫入對程序運(yùn)行能耗的影響,將同一個程序分別在優(yōu)化前和優(yōu)化后在相同環(huán)境中運(yùn)行,觀察結(jié)果,分析無效寫入優(yōu)化對于程序運(yùn)行能耗的影響。

4.1 實(shí)驗(yàn)環(huán)境

為了控制變量,對比程序?qū)⑦\(yùn)行在同一主機(jī)上,同時主機(jī)運(yùn)行的進(jìn)程兩次測試是保持一致,為了排除氣溫、主機(jī)散熱以及電網(wǎng)對于實(shí)驗(yàn)準(zhǔn)確性的影響,跑完一段程序 10 分鐘后跑第二段程序。表2 和表3 是對實(shí)驗(yàn)主機(jī)軟硬件的介紹。

4.2 實(shí)驗(yàn)?zāi)P?/h3>

本文實(shí)驗(yàn)部分采用了基于硬件性能計數(shù)器采樣數(shù)值回歸建立的模型。硬件性能計數(shù)器[16]是一組內(nèi)嵌在處理器上的專用寄存器,計數(shù)器統(tǒng)計的與計算機(jī)硬件相關(guān)的事件,稱為性能事件,例如:處理器周期、高速緩存的引用、 高速緩存不命中、分支不命中和總線周期等。

選取硬件性能計數(shù)器數(shù)值作為建模參數(shù)有以下兩個原因:一方面,由于程序運(yùn)行時要與硬件打交道, 性能事件能很好的刻畫程序行為特征,例如當(dāng)程序訪存時,通過諸如高速緩存不命中、 TLB 不命中、DMA 事件等性能事件就能了解程序在訪存過程中的具體行為;另一方面,性能事件與系統(tǒng)功耗是有直接關(guān)系的。性能事件反映了程序的行為特征,因此 通過性能事件就能建立應(yīng)用程序代碼與系統(tǒng)能耗的關(guān)系。

表2 實(shí)驗(yàn)主機(jī)硬件Table 2 Hardware of Experimental host

表3 實(shí)驗(yàn)主機(jī)軟件Table 3 Software of Experimental host

通過多元線性回歸對選取的工作集 SPEC_CINT2006 數(shù)據(jù)進(jìn)行擬合,在性能事件備選集合中添加和刪除性能事件,由測量的功耗數(shù)據(jù)與擬合功耗數(shù)據(jù)的誤差確定最終的模型。在最后確定的模型中,只有 3個性能事件: 處理器活躍的周期數(shù) (Active Cycles)、引退的指令 (Instruction Retired) 和最后一級緩存不命中 (LLC_Misses),模型的最終形式

Psystem= 23.834×Active Cycles+2.093×Instruction Retired+72.113 ×LLCMisses+47.675

其中三個性能事件的含義分別是:

(1) 處理器活躍的周期數(shù)(Active Cycles)——這個性能事件的值表示處理器活躍的周期數(shù)。當(dāng)處理器處于空閑狀態(tài)時,功耗保持一個較低的相對穩(wěn)定的值,但處于活躍狀態(tài)時,功耗就會增大很多,所以這個性能事件能夠反映處理器功耗的變化。

(2) 引退的指令(Instruction Retired)——離開了“引退單元”的指令(位操作)。引退單元將投機(jī)執(zhí)行的位操作寫入用戶可見的寄存器,然后不斷的檢查重排列緩沖區(qū)的狀態(tài),將已經(jīng)被執(zhí)行過并且和任何指令池中的位操作都無關(guān)的指令移出。這個性能事件反應(yīng)了到底有多少指令已經(jīng)被執(zhí)行。

(3) 最后一級緩存不命中(LLC_Misses)——記錄最后一級高速緩存不命中次數(shù)。由于最后一級高速緩存不命中次數(shù)和內(nèi)存的訪問次數(shù)成比例。因此如果當(dāng)運(yùn)行的是 非 I/O 密集型的應(yīng)用程序時,就可以用這個度量值去估算內(nèi)存的訪問次數(shù)。

4.3 實(shí)驗(yàn)方法

開始實(shí)驗(yàn)前,將測試程序備份一份。對一份程序源代碼使用無效寫入分析工具對其進(jìn)行分析,使用獲取的無效寫入信息對源碼進(jìn)行修改,然后分別測試修改前和修改后程序的能耗。

圖3 展示了無效寫入分析工具在分析 403.gcc 把c-typeck.i 作為輸入時的分析結(jié)果,圖中第一行展示了該無效寫入的頻率以及在整個程序中所占比例,后面兩段分別是無效寫入的dead context 和 killing context即在源碼中對應(yīng)的兩處位置的上下文調(diào)用鏈,根據(jù)提供的源碼位置就可以對其無效寫入原因進(jìn)行分析,繼而優(yōu)化。

在測試程序運(yùn)行時,使用硬件性能計數(shù)器的值作為模型輸入,輸出計算出的系統(tǒng)功率。獲取硬件性能計數(shù)器的值的方法是使用性能分析工具 PAPI[17],將獲取到的目標(biāo)寄存器的值輸入到上一節(jié)所描述的模型中,計算功率,然后使用貝塞爾 (Bezier) 曲線連接各個采樣點(diǎn),積分求出能耗值。

4.4 實(shí)驗(yàn)結(jié)果

圖3 無效寫入分析工具輸出Fig.3 The output of invalid write analysis tool

圖4 SPEC CPU2006-INT 部分 benchmark 無效寫入分析結(jié)果Fig.4 The result of invalid write in SPEC CPU2006-INT partial benchmarks

圖4 展示了 SPEC CPU2006-INT 中部分 benchmark經(jīng)過無效寫入分析工具分析得出的無效寫入比例。其中,無效寫入比例是無效寫入的數(shù)據(jù)量占程序執(zhí)行過程中整個寫入量的比例??梢钥吹?403.gcc 這個benchmark 的無效寫入比例高達(dá) 60.3%,401.bzip2 相對低一些,但也有 9.8%,幾個 benchmark 的無效寫入比例平均值也達(dá)到了 27%。下文將展示針對無效寫入進(jìn)行優(yōu)化前后程序運(yùn)行能耗結(jié)果對比。

主機(jī)在不運(yùn)行測試程序時也是有后臺程序在運(yùn)行,部件也在消耗電能,所以應(yīng)當(dāng)將主機(jī)未運(yùn)行測試程序時消耗的電能剔除,才能看到明顯的結(jié)果對比。表4 是將主機(jī)未運(yùn)行測試程序時消耗的電能剔除后的結(jié)果,剔除方法時將未運(yùn)行測試程序時主機(jī)硬件性能計數(shù)器數(shù)值讀出,使用模型算出長時間的功率平均值,將該平均值作為主機(jī)未運(yùn)行測試程序時的功率,后續(xù)根據(jù)運(yùn)行時間將計算電能結(jié)果減去該功率下主機(jī)的消耗。計算測試程序能耗,可以用以下公式表示:

其中,Eresult表示要求的測試程序能耗,Tstart和Tend是測試程序運(yùn)行的起止時間,P1表示模型計算出的整體功率,P2之前測得主機(jī)未運(yùn)行測試程序時的功率,公式中取用其平均值。

由于同一個 benchmark 在運(yùn)行不同輸入時,調(diào)用的函數(shù)也不一樣,所以針對不同的輸入,分別進(jìn)行優(yōu)化測試。有些 benchmark,例如 bzip2,由于程序執(zhí)行時間太短,采樣采集硬件計數(shù)器數(shù)值時間密度相對比較大導(dǎo)致結(jié)果誤差較大,不作為實(shí)驗(yàn)測試對象;而 403.gcc 執(zhí)行時間較長,比較符合實(shí)驗(yàn)條件,針對不同輸入對其進(jìn)行了詳細(xì)的能耗測量,結(jié)果如表4 所示。

表4 實(shí)驗(yàn)結(jié)果Table 4 The result of experiment

其中 gcc 的平均能耗減少達(dá)到 13.46%,效果顯著,同時,amrGodunov3d 能耗減少達(dá)到 4.2%,說明對程序代碼中的無效寫入進(jìn)行優(yōu)化改進(jìn)能夠起到顯著的減少程序運(yùn)行能耗的效果,實(shí)現(xiàn)對程序代碼能耗的優(yōu)化。

5 結(jié)論及未來研究方向

本文介紹了不同粒度下對程序能耗進(jìn)行優(yōu)化的方法,重點(diǎn)闡述了程序語句級能耗優(yōu)化的方法,對程序代碼中一種存取冗余情況——無效寫入進(jìn)行了詳細(xì)的描述和分析得出以下結(jié)論:

(1) 程序中無效寫入較為常見,出現(xiàn)的原因有多種,例如程序編寫人員編寫習(xí)慣不佳,代碼中在循環(huán)訪問元素個數(shù)少、訪問元素分布隨機(jī)的情況下使用大數(shù)組,每次重置清零產(chǎn)生大量冗余寫入等。

(2) 在使用工具對于目標(biāo)代碼進(jìn)行分析以后,得到該程序中無效寫入的源代碼位置,在對于這些無效寫入進(jìn)行優(yōu)化后,經(jīng)過測試,發(fā)現(xiàn)能夠?qū)Τ绦蜻\(yùn)行所消耗的能耗起到顯著的減少。

如前文所說,對于程序能耗優(yōu)化研究意義重大。本文對于程序代碼能耗的優(yōu)化只是針對于無效寫入這一具體存取冗余情景,在未來的研究中應(yīng)該發(fā)現(xiàn)并研究更多程序代碼能耗可優(yōu)化的方向;同時對程序運(yùn)行時的存取情況分析的復(fù)雜性以及對程序代碼進(jìn)行能耗優(yōu)化時應(yīng)當(dāng)保證其正確性,決定了對無效寫入這一情況的分析過程的復(fù)雜,不利于用戶直接使用,后續(xù)研究中應(yīng)當(dāng)將這一方案向工具化發(fā)展。將這一工具作為插件集成到現(xiàn)有的一些集成開發(fā)環(huán)境中去,使得程序編寫人員特別是進(jìn)行科學(xué)計算程序編寫的科研人員能夠使用簡單的操作對編寫的程序代碼進(jìn)行能耗優(yōu)化,起到降低科研及工業(yè)成本和減少碳排放的目的。

猜你喜歡
程序運(yùn)行程序代碼數(shù)組
JAVA稀疏矩陣算法
電腦報(2022年13期)2022-04-12 00:32:38
JAVA玩轉(zhuǎn)數(shù)學(xué)之二維數(shù)組排序
電腦報(2020年24期)2020-07-15 06:12:41
行政公益訴訟訴前程序運(yùn)行檢視
法大研究生(2020年2期)2020-01-19 01:43:04
計算機(jī)網(wǎng)絡(luò)信息安全未來發(fā)展趨勢
基于圖元裝接模式由程序流程圖自動生成源代碼
軟件工程(2016年11期)2017-01-17 16:56:57
尋找勾股數(shù)組的歷程
論刑事錯案的成因
《刑事訴訟法》修改背景下刑事和解制度淺析
VB數(shù)組在for循環(huán)中的應(yīng)用
考試周刊(2012年88期)2012-04-29 04:36:47
嵌入式系統(tǒng)中程序的優(yōu)化策略
新媒體研究(2009年4期)2009-03-14 06:59:48
旌德县| 峡江县| 东方市| 旺苍县| 阿城市| 贺州市| 承德县| 洞头县| 璧山县| 祥云县| 五峰| 双鸭山市| 汝州市| 郸城县| 怀化市| 廉江市| 牟定县| 五指山市| 德江县| 临桂县| 腾冲县| 登封市| 辽源市| 精河县| 江口县| 弋阳县| 新营市| 汨罗市| 道真| 仙桃市| 东乌| 无锡市| 潮州市| 建水县| 贵南县| 抚远县| 建瓯市| 珠海市| 荆州市| 济宁市| 瑞昌市|