《嵌入式系統(tǒng)原理與開發(fā)》課件-第6章_第1頁
《嵌入式系統(tǒng)原理與開發(fā)》課件-第6章_第2頁
《嵌入式系統(tǒng)原理與開發(fā)》課件-第6章_第3頁
《嵌入式系統(tǒng)原理與開發(fā)》課件-第6章_第4頁
《嵌入式系統(tǒng)原理與開發(fā)》課件-第6章_第5頁
已閱讀5頁,還剩64頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第6章嵌入式應(yīng)用程序設(shè)計6.1引言

6.2程序設(shè)計方法

6.3程序設(shè)計技術(shù)

6.4嵌入式程序優(yōu)化

思考與練習(xí)題

6.1引言

嵌入式程序的創(chuàng)建是嵌入式系統(tǒng)設(shè)計的核心。與編寫PC程序不同,編寫嵌入式代碼需要滿足多種約束條件。設(shè)計嵌入式代碼不僅需要提供豐富的功能,通常也必須滿足一定的運行速率、功耗和適應(yīng)內(nèi)存容量限制等。因此,在嵌入式程序的設(shè)計過程中需要用到一些特有的技術(shù)和方法。

隨著編譯技術(shù)、處理器和內(nèi)存的不斷發(fā)展,采用高級語言設(shè)計應(yīng)用程序已經(jīng)變得越來越通用。當(dāng)編譯程序不能產(chǎn)生理想的結(jié)果時,程序的部分內(nèi)容可能仍然需要用匯編語言編寫。但是,本章的重點是介紹高級語言(主要是C語言)程序設(shè)計,因為采用高級語言更容易理解和分析程序的功能。

6.2節(jié)為嵌入式程序設(shè)計方法,主要介紹嵌入式程序設(shè)計用到的設(shè)計范型和編程模型方法。6.3節(jié)為嵌入式程序設(shè)計技術(shù),主要介紹多任務(wù)環(huán)境下一些典型的程序設(shè)計范例。6.4節(jié)為嵌入式程序優(yōu)化,內(nèi)容包括程序執(zhí)行時間、能量以及程序長度的優(yōu)化。 6.2程序設(shè)計方法

6.2.1設(shè)計范型

設(shè)計范型是解決一類特定問題的方法的通用描述。嵌入式系統(tǒng)廣泛使用了兩種不同類型程序的設(shè)計范型:狀態(tài)機和循環(huán)緩沖區(qū)。狀態(tài)機非常適合于諸如用戶界面這樣的反應(yīng)系統(tǒng)。循環(huán)緩沖區(qū)在數(shù)字信號處理中非常有用。

1.狀態(tài)機

對于非周期性輸入的系統(tǒng),根據(jù)輸入和當(dāng)前系統(tǒng)狀態(tài),通過有限狀態(tài)機的方式能夠很方便地描述系統(tǒng)的響應(yīng)。通常,有限狀態(tài)機在硬件設(shè)計時會用到,而編程的狀態(tài)機類型也是嵌入式計算的一種有效實現(xiàn)。下面給出一個C狀態(tài)機的示例,如圖6-1所示。圖6-1C狀態(tài)機示例根據(jù)狀態(tài)機的描述,系統(tǒng)工作情況是:當(dāng)座位上無人時,Idle狀態(tài)被激活;當(dāng)有人坐下時進入Seated狀態(tài)并打開計時器;如果計時器在安全帶系牢之前關(guān)閉(即超時),則轉(zhuǎn)入Buzzer狀態(tài),反之進入Belted狀態(tài);當(dāng)人離開座位時,回到Idle狀態(tài)。

下面再用C語言編寫這些行為。假設(shè)已經(jīng)將三個輸入(seat,belt,timer)的當(dāng)前值載入變量,并臨時保持輸出到變量(timer_on,buzzer_on)中。變量state用來保持當(dāng)前狀態(tài)。使用switch語句來決定每個狀態(tài)所采取的行動。代碼如下:

2.循環(huán)緩沖區(qū)

在嵌入式系統(tǒng)中,程序不僅需要實時輸出結(jié)果,而且需要盡量少地使用內(nèi)存。因此使用循環(huán)緩沖區(qū)是處理流數(shù)據(jù)的有效方式。下面以一個FIR過濾器的實現(xiàn)來介紹循環(huán)緩沖區(qū)的使用。

FIR過濾器要求對每一個樣本必須產(chǎn)生一個依賴于最后n個輸入值的輸出。使用循環(huán)緩沖區(qū)用來存儲數(shù)據(jù)流的子集。算法在每個時刻都形成一個到流窗口的數(shù)據(jù)流子集。當(dāng)拋棄舊值加入新值時,窗口將隨著時間滑動。由于窗口尺寸不變,因此可以使用固定尺寸的緩沖區(qū)來存儲當(dāng)前數(shù)據(jù)。緩沖區(qū)使用指針指向下一個樣本將要放置的位置;每增加一個樣本,就自動覆蓋需要移出的舊樣本。指針到達緩沖區(qū)尾部時會繞回到頂部。圖6-2解釋了循環(huán)緩沖區(qū)的工作原理。圖6-2存放流數(shù)據(jù)的循環(huán)緩沖區(qū)6.2.2編程模型

使用編程模型能夠比使用源代碼更容易地進行更有用的分析。在編程模型的基礎(chǔ)上可以更清晰地使用匯編語言或高級語言編寫程序。編程模型的基礎(chǔ)是控制/數(shù)據(jù)流圖(CDFG)。CDFG用來構(gòu)造模型的數(shù)據(jù)操作(計算)和控制操作(條件)。CDFG的特征是將控制和數(shù)據(jù)結(jié)構(gòu)進行結(jié)合。

CDFG使用數(shù)據(jù)流圖作為其元素,包含兩個基本的節(jié)點:判定節(jié)點和數(shù)據(jù)流節(jié)點。數(shù)據(jù)流節(jié)點封裝了一個完整的數(shù)據(jù)流圖,用來表示一個基本塊。在順序結(jié)構(gòu)的程序中使用一種類型的判定節(jié)點能夠描繪所有類型的控制(跳轉(zhuǎn)/分支)。以下是一點控制結(jié)構(gòu)的C代碼和控制/數(shù)據(jù)流圖(見圖6-3)。圖中的矩形節(jié)點表示基本塊,可通過簡單函數(shù)調(diào)用表示;菱形節(jié)點表示條件,可通過標(biāo)記賦給,同時用判斷條件的可能結(jié)果標(biāo)記邊。圖6-3一點控制結(jié)構(gòu)的控制/數(shù)據(jù)流圖以下是while循環(huán)的C代碼和控制/數(shù)據(jù)流圖(見圖6-4)。while循環(huán)由一個判斷和一個循環(huán)體組成,而for循環(huán)可以由while循環(huán)定義,因此該CDFG同樣能夠表示for循環(huán)。

while(a<b){

a=proc1(a,b);

b=proc2(a,b);

}圖6-4while循環(huán)的控制/數(shù)據(jù)流圖 6.3程序設(shè)計技術(shù)

6.3.1消息

在多任務(wù)系統(tǒng)中,消息是任務(wù)間相互通信的常用手段。在系統(tǒng)的主任務(wù)中可以使用以下代碼來實現(xiàn)消息循環(huán):在上述代碼中使用了幾個API函數(shù)。其中,WaitMessage()函數(shù)用來實現(xiàn)等待消息。參數(shù)0表示等待的超時時間為無窮,即除非主任務(wù)接收到消息,否則此函數(shù)不會返回。WaitMessage函數(shù)返回的是一個指向系統(tǒng)的消息結(jié)構(gòu)的指針。系統(tǒng)的消息結(jié)構(gòu)定義如下:

typedefstruct{

U32Message;

U32WParam;

U32LParam;

}OSMSG,*POSMSG;6.3.2任務(wù)和任務(wù)間同步

μC/OS-Ⅱ允許同時運行64個任務(wù),每個任務(wù)都要有獨立的??臻g和唯一的任務(wù)優(yōu)先級。在應(yīng)用程序中創(chuàng)建新任務(wù)時,必須先為任務(wù)定義自己的??臻g,選定一個系統(tǒng)唯一的任務(wù)優(yōu)先級。下面的代碼定義了一個Rtc_Disp_Task任務(wù),并為該任務(wù)分配了一個大小為STACKSIZE的棧空間,同時定義該任務(wù)的優(yōu)先級為14:

OS_STKRtc_Disp_Stack[STACKSIZE]={0,};

//Rtc_Disp_Task堆棧

voidRtc_Disp_Task(void*Id);

//Rtc_Disp_Task

#defineRtc_Disp_Task_Prio 14以下代碼用來創(chuàng)建Rtc_Disp_Task任務(wù):

OSTaskCreat(Rtc_Disp_Task,(void*)0,(OS_STK*)

&Rtc_Disp_Stack[STACKSIZE-1],Rtc_disp_Task_prio);

該任務(wù)創(chuàng)建成功后,系統(tǒng)會執(zhí)行Rtc_Disp_Task函數(shù)并運行其相應(yīng)的任務(wù)。

在多任務(wù)系統(tǒng)中,使用信號量是協(xié)調(diào)多個任務(wù)最簡單、有效的方法。以下的代碼定義了一個系統(tǒng)的信號量:

OS_EVENT*Rtc_Updata_Sem;//時鐘更新控制權(quán)

使用OSSemCreate函數(shù)創(chuàng)建一個系統(tǒng)的信號量。參數(shù)1表示此信號量有效。例如:

Rtc_Updata_Sem=OSSemCreate(1);在系統(tǒng)任務(wù)中,使用OSSemPend函數(shù)等待一個信號量有效,使用OSSemPost函數(shù)釋放一個信號量。例如:

voidRtc_Disp_Task(void*Id)//時鐘顯示更新任務(wù)

{

U16strtime[10];

INT8Uerr;

for(;;){

if(Rtc_IsTimeChange(RTC_SECOND_CHANGE)){//不需要更新顯示

OSSemPend(Rtc_Updata_Sem,0,&err);

Rtc_Format("%H:%I:%S",strtime);

SetTextCtrlText(pTextCtrl,strtime,TRUE);

OSSemPost(Rtc_Updata_Sem);

}

OSTimeDly(250);

}

}6.3.3繪圖函數(shù)

繪圖時通常使用繪圖設(shè)備上下文DC,這樣可保證不同任務(wù)繪圖的參數(shù)相互獨立,不會相互影響。繪圖設(shè)備上下文DC在系統(tǒng)中可定義為一個結(jié)構(gòu)體,其定義如下:

typedefstruct{

intDrawPointx;

intDrawPointy; //繪圖使用的坐標(biāo)點

intPenWidth; //畫筆寬度

U32PenMode; //畫筆模式

U32PenColor; //畫筆顏色可見,在DC中保存了每個繪圖對象的相關(guān)參數(shù)。系統(tǒng)啟動時,通過調(diào)用initOSDC()函數(shù)初始化DC,可以為以后創(chuàng)建DC分配存儲空間。

使用CreateDC()函數(shù)創(chuàng)建DC,并給DC賦予默認的初始值。以下代碼演示了如何創(chuàng)建一個DC。其中,原點坐標(biāo)設(shè)定在液晶屏設(shè)備坐標(biāo)的(170,50),繪圖的邏輯坐標(biāo)的水平值設(shè)置為800,垂直范圍按照液晶屏實際的縱橫比例縮放。

PDCpdc;

pdc=CreateDC();

SetDrawOrg(pdc,170,50,&oldx,&oldy);

SetDrawRange(pdc,800,-1,&oldxrange,&oldyrange);在創(chuàng)建好繪圖設(shè)備上下文DC并設(shè)定其參數(shù)后就可以使用DC指針在屏幕上繪圖了。以下代碼演示了如何在屏幕上繪制正弦曲線:

PDCpdc;

ClearScreen();

SetDrawOrg(pdc,0,LCDHEIGHT/2,&oldx,&oldy);//設(shè)置繪圖原點為屏幕左邊中點

MoveTo(pdc,0,0);

for(x=0;x<LCDWIDTH;x++)

{ y=(int)(50*sin(((double)x)/20.0+offset));

LineTo(pdc,x,y);

}6.3.4控件

使用控件可以加速GUI圖形界面的建立。一個通用的系統(tǒng)控件包含了以下數(shù)據(jù)結(jié)構(gòu):

typedefstruct

{ U32CtrlType; //控件的類型

U32CtrlID; //控件的ID

StructRECTListCtrlRect; //控件的位置和大小

U32FontSize; //控件的字符大小

U32style; //控件的邊框風(fēng)格

U8bVisible; //是否可見

}OS_Ctrl;其中,控件的ID(CtrlID)是系統(tǒng)唯一的,即每個控件的ID都不同。以下代碼演示了一個列表框控件,容量為100個列表項目,把系統(tǒng)中擴展名為?.bmp的文件顯示在列表框中:

CharFileExName[]={'B','M','P',0};

structRECTrect;

charfilename[9];

U32filepos=0;

U16Ufilename[9];

inti=0;

SetRect(&rect,0,18,80,107); //創(chuàng)建列表框控件

6.4嵌入式程序優(yōu)化

6.4.1編譯過程

理解一個高級語言如何被翻譯為機器指令對于實現(xiàn)嵌入式程序優(yōu)化是非常有幫助的。由于在實現(xiàn)一個嵌入式計算系統(tǒng)時經(jīng)常需要控制處理中斷的指令順序、內(nèi)存中的數(shù)據(jù)和指令的位置等,因此理解整個編譯過程如何工作能夠幫助程序員知道何時不能依賴編譯程序。因為很多應(yīng)用程序?qū)π阅芊浅C舾?,所以在理解代碼如何產(chǎn)生的基礎(chǔ)上,通過編寫能夠被編譯為所需指令的高級代碼或者在必要時編寫自己的匯編代碼,才能夠?qū)崿F(xiàn)性能目標(biāo)。通常,一個編譯命令往往做了產(chǎn)生一個可執(zhí)行程序所需做的一切。確切地講,編譯過程包括了編譯、匯編和鏈接等若干步驟,如圖6-5所示。圖6-5編譯和裝入的過程

1.編譯

大多數(shù)編譯程序并不直接產(chǎn)生機器碼,而是以匯編語言形式建立指令級程序。產(chǎn)生匯編語言而不是二進制指令的這一過程中,可以使程序員不用關(guān)心與編譯過程不相關(guān)的一些細節(jié),如指令形式以及指令和數(shù)據(jù)的確切地址。

事實上,編譯結(jié)合了翻譯和優(yōu)化的過程:

編譯?=?翻譯?+?優(yōu)化

翻譯是指將高級語言程序翻譯為低級指令形式,而優(yōu)化則注重于程序的更多方面,這是由于在某種情況下,編譯一條語句的結(jié)果可能會對程序的其他部分造成不良影響。如果使用獨立翻譯源代碼語句的技術(shù),則優(yōu)化將能產(chǎn)生更好的指令順序。圖6-6表示了編譯的過程。編譯開始于像C這樣的高級語言代碼并產(chǎn)生匯編代碼。高級語言被分析拆分成語句和表達式。此外,還產(chǎn)生了一個包含程序中所有命名對象的符號表。對于另外一些編譯程序,它可能還要完成一種程序輸入。這種程序輸入被看做是對高級語言的修改,而且它不會引用指令的高級優(yōu)化。圖6-6編譯過程

2.匯編

匯編程序的任務(wù)是將符號化的匯編語言語句翻譯成目標(biāo)代碼的指令位級表示。匯編程序關(guān)心指令形式并做了一部分將標(biāo)記翻譯為地址的工作。

如果匯編語言程序的起始地址已經(jīng)被指明,那么在這種程序中的地址被稱做絕對地址。但在許多情況下,特別是由若干個組成文件創(chuàng)建可執(zhí)行文件時,我們不想在匯編前為每一個模塊指明地址——如果那樣做了,在匯編前必須決定的不僅是每個程序在內(nèi)存中的長度,還有它們鏈接到程序的次序。因此大多數(shù)匯編程序使用相對地址——通過在文件開始處指明匯編語言模塊的起始地址,而模塊中的其他地址將相對于該地址來計算。最后,由鏈接程序負責(zé)將相對地址轉(zhuǎn)化為絕對地址。

將匯編代碼翻譯為目標(biāo)代碼時,匯編程序必須翻譯操作碼并格式化每條指令中的位,將標(biāo)記翻譯為地址。正是由于標(biāo)記,可以讓編譯程序不用關(guān)心指令和數(shù)據(jù)的絕對地址。標(biāo)記處理過程要求對匯編源碼進行以下兩步處理:

(1)掃描代碼以決定每個標(biāo)記的地址。

(2)用第(1)步中的標(biāo)記值匯編指令。

如圖6-7所示,每個符號的名字和它的地址被存儲在第(1)步處理生成的符號表中。圖6-7匯編過程中符號表的處理

3.鏈接

很多匯編語言程序用幾個小塊文件而不是一個單獨的大文件寫成。將一段大程序分割成小文件有助于描述出程序的模塊化。鏈接是指修改匯編代碼并將由匯編程序產(chǎn)生的目標(biāo)文件生成文件間的必要鏈接。

一些標(biāo)記在同一個文件中被定義并使用,其他一些標(biāo)記在一個單獨文件中被定義但在其他地方被引用,如圖6-8所示,標(biāo)記在文件中被定義的地方稱做入口點,標(biāo)記在文件中被引用的地方稱做外部引用。圖6-8外部引用和入口點6.4.2執(zhí)行時間優(yōu)化

嵌入式系統(tǒng)實時性的特點要求我們了解程序的執(zhí)行時間,并能做出優(yōu)化。分析程序執(zhí)行時間也有助于分析功耗的特性。

然而在實踐中,程序的執(zhí)行時間很難被精確地確定,原因包括:

(1)輸入的數(shù)據(jù)在程序中往往會選擇不同的執(zhí)行路徑,而程序的執(zhí)行時間也會隨之變化。

(2)高速緩存是影響程序性能的另一個主要因素,并重復(fù)影響。高速緩存的行為部分依賴于輸入程序的數(shù)據(jù)值。

(3)即使在指令水平上,執(zhí)行次數(shù)也可能改變。浮點運算對于數(shù)值來說是最為敏感的,但是正常的整數(shù)執(zhí)行流水線也能引入數(shù)據(jù)依賴型變體。通常,一條指令在流水線中的執(zhí)行時間不僅依賴于這條指令本身,而且還依賴于在流水線中的該指令周圍的指令。

雖然如此,我們最關(guān)心的還是以下三種類型的程序性能:

(1)平均執(zhí)行時間——對于典型數(shù)據(jù)所期望的典型執(zhí)行時間。顯然,首要的難點在于定義典型輸入。

(2)最壞執(zhí)行時間——顯然,這對于必須滿足期限的系統(tǒng)來說非常重要。

(3)最佳執(zhí)行時間——這對于多速率實時系統(tǒng)而言可能很重要。

1.程序性能分析

程序執(zhí)行時間可表示為

執(zhí)行時間=程序路徑+指令耗時

程序路徑是指程序執(zhí)行的指令序列。指令耗時基于被程序路徑跟蹤的指令序列,它需要考慮數(shù)據(jù)相關(guān)性、流水線行為和高速緩存。

1)程序路徑

程序性能的某些方面可以通過直接查看C程序來估計。例如,如果一個程序包含了一個大的固定的迭代范圍或如果一個條件分支比另一個分支更長,那么我們至少可以得到一個粗略的概念就是:這些程序段將消耗更多的時間。這里只有四個不同的情況:無賦值、賦值4、賦值2與賦值3、賦值1與賦值3,分別對應(yīng)于經(jīng)過嵌套if的可能路徑。由此,我們可以檢查每一個路徑來加入這些變量值。

下面通過前面FIR過濾器的例子來解釋如何通過固定迭代for循環(huán)來枚舉路徑。循環(huán)代碼重新編碼如下:

for(i=0,f=0;i<N;i++)

f=f+c[i]*x[i];

通過檢查代碼的CDFG(見圖6-9),可以更容易地確定變量語句被執(zhí)行的次數(shù)。圖6-9for循環(huán)的CDFG

2)指令耗時

一旦我們知道程序的執(zhí)行路徑,就必須測量沿著該路徑執(zhí)行指令的時間。最簡單的估計就是假定每一個指令消耗相同數(shù)目的時鐘周期,這意味著只要通過對指令計數(shù),并與每條指令執(zhí)行時間相乘,即可獲得程序的總執(zhí)行時間。然而,即使忽略高速緩存的影響,由于下列原因的存在,這種方法也顯得過于簡單。

(1)不是所有的指令均消耗相同的時間。盡管RISC體系結(jié)構(gòu)趨向于提供統(tǒng)一指令執(zhí)行次數(shù)以保持CPU的流水線是滿的,但仍然有許多RISC體系結(jié)構(gòu)需要使用不同的時間去執(zhí)行相同的指令。多裝載/存儲指令就是ARM體系結(jié)構(gòu)中執(zhí)行時間較長的例子。浮點指令在執(zhí)行時間上也存在很大差異。基本乘法與加法運算是快速的,但一些超常的函數(shù)可能要花費上千個周期去執(zhí)行。

(2)指令的執(zhí)行次數(shù)不是獨立的。一條指令的執(zhí)行時間依賴于它周圍的指令。

(3)一條指令的執(zhí)行時間可能依賴于操作數(shù)的值。

2.優(yōu)化執(zhí)行速度

我們可以通過解決以下幾個方面的問題來提高程序執(zhí)行的速度:

首先,確信你的代碼確實需要提高執(zhí)行效率。

其次,可以重新設(shè)計算法來提高執(zhí)行效率。

最后,可以檢查程序的實現(xiàn)。以下是一些關(guān)于程序?qū)崿F(xiàn)的要點總結(jié):

(1)盡可能有效地使用寄存器。成組訪問一個值以便使該值可被寫入寄存器保存起來。

(2)在任何可能的情況下,使用分頁模式訪問內(nèi)存系統(tǒng)。分頁模式讀/寫能夠減少訪問內(nèi)存時的步驟??梢酝ㄟ^組織變量使更多的變量被連續(xù)引用,從而提高分頁模式的使用率。

(3)分析高速緩存的行為來發(fā)現(xiàn)主要的高速緩存沖突。以下面的方式重新構(gòu)建代碼,盡可能消除以下沖突:

①指令沖突。如果沖突的代碼段較小,試著重寫代碼段,使之盡可能小以便更好地適用于高速緩存,此時使用匯編語言也許很有必要。如果沖突的代碼段跨度很大,應(yīng)盡量移動指令或用NOP填充。

②標(biāo)量數(shù)據(jù)沖突??砂褦?shù)據(jù)值移到不同的位置以盡量減少沖突。

③數(shù)組數(shù)據(jù)沖突??梢钥紤]移動數(shù)組或者改變數(shù)組訪問模式來減少沖突。6.4.3能量優(yōu)化

對于電池供電的計算機系統(tǒng)而言,功耗是一個非常重要的設(shè)計指標(biāo)。而對于電網(wǎng)供電的系統(tǒng)而言,功耗也變得越來越重要,這主要是由于控制系統(tǒng)的功耗可以減少快速芯片運行的發(fā)熱量、提高系統(tǒng)穩(wěn)定性并降低系統(tǒng)成本。

我們可以通過多種途徑來降低功耗,例如:

(1)使用工作效率高而且省電的算法來取代現(xiàn)有的算法。

(2)優(yōu)化內(nèi)存訪問。

(3)在不需要時關(guān)閉系統(tǒng)的一部分,如CPU的子系統(tǒng)、外圍芯片等。

1.程序能量優(yōu)化

程序的能量消耗取決于以下幾方面因素:

(1)程序能量消耗隨指令的不同而不同。

(2)指令次序?qū)δ芰肯挠杏绊憽?/p>

(3)操作碼以及操作數(shù)的位置對能量消耗也有影響。

對大多數(shù)CPU來說,著力于優(yōu)化指令級的能量消耗只能獲得有限的回報,程序必須進行一定數(shù)量的計算來完成它的功能。當(dāng)有更好的算法來完成該運算時,基本運算消耗的能量只能改變系統(tǒng)能量消耗總量的相當(dāng)小的一部分,通常還要為此付出極大的努力。

2.存儲器效果

在許多應(yīng)用程序中,致力于內(nèi)存系統(tǒng)的優(yōu)化會帶來最大的節(jié)能效益。如圖6-10所示,內(nèi)存?zhèn)鬏斒瞧駷橹笴PU完成的操作中能量消耗最大的操作。一次內(nèi)存?zhèn)鬏敳僮骱馁M的能量是一次加法運算的33倍多。因此,優(yōu)化能量消耗的最好方法是合理組織內(nèi)存中的數(shù)據(jù)和指令。訪問寄存器是節(jié)能效益最高的;緩存訪問比大多數(shù)的主存訪問效率要高。圖6-10不同操作的相對能量消耗

3.能量優(yōu)化

一般而言,使程序運行得更快同樣也能降低能量消耗。其中,能夠被編程人員合理控制的最大因素是內(nèi)存訪問模式。

前面提到的性能優(yōu)化方法對改進能量消耗也很有用處,這些方法包括:

(1)盡量有效地使用寄存器。成組訪問一個變量值以便使這個值被寫入寄存器并保存起來。

(2)分析高速緩存行為來發(fā)現(xiàn)主要的高速緩存沖突。重構(gòu)該代碼,盡可能消除以下沖突:①指令沖突。如果沖突的代碼段較小,試著重寫代碼段,使之盡可能小,以便更好地適用于高速緩存,此時使用匯編語言也許很有必要。如果沖突的代碼段跨度很大,則盡量移走指令或用NOP填充。

②標(biāo)量數(shù)據(jù)沖突??梢园褦?shù)據(jù)值移到不同的位置以盡量減少沖突。

③數(shù)組數(shù)據(jù)沖突??梢钥紤]移動數(shù)組或修改數(shù)組訪問模式以減少沖突。

(3)在任何可能的情況下,使用分頁模式訪問內(nèi)存系統(tǒng)。原因前面已介紹過,這里不再贅述。6.4.4長度優(yōu)化

一個程序的內(nèi)存覆蓋區(qū)是由程序的數(shù)據(jù)和指令的大小決定的。在最小化程序長度時,這兩方面都需予以考慮。

數(shù)據(jù)為程序長度最小化提供了一個很好的機會,因為數(shù)據(jù)高度依賴于編程風(fēng)格。低效率的程序經(jīng)常保存著好幾份數(shù)據(jù)副本,確認并消除數(shù)據(jù)副本有助于顯著地節(jié)省內(nèi)存,而這只需付出很小的性能上的代價。應(yīng)該小心地確定緩沖區(qū)的大小,而不是定義一個程序永遠用不到的大的數(shù)據(jù)數(shù)組,確定保存在緩沖區(qū)中數(shù)據(jù)的最大數(shù)量,并相應(yīng)地分配數(shù)組。數(shù)據(jù)有時候可以被壓縮,例如可以在一個字中設(shè)置幾個標(biāo)志并通過使用位級操作來提取它們。一個相當(dāng)?shù)图壍淖钚』瘮?shù)據(jù)的技術(shù)是數(shù)值復(fù)用。例如,如果幾個常數(shù)恰好有相同的值,則它們可以被映射到同一個位置。數(shù)據(jù)緩沖區(qū)在程序的幾個不同地方可以被復(fù)用。使用這種技術(shù)時必須非常小心,因為程序的后續(xù)版本可能不讓常數(shù)使用同一個值。一個更一般的技巧是在運行時產(chǎn)生數(shù)據(jù)而不是存儲數(shù)據(jù)。當(dāng)然,產(chǎn)生數(shù)據(jù)所需的代碼會占用程序的空間,但是,當(dāng)涉及到復(fù)雜的數(shù)據(jù)結(jié)構(gòu)時,使用程序來產(chǎn)生數(shù)據(jù)可以節(jié)省空間。最小化程序指令的大小要求混合高級程序變換并精心選擇指令。仔細封裝函數(shù)在子例程中可以減少程序的長度。因為子例程有參數(shù)傳遞的開銷,而從高級語言代碼來看不明顯,子例程起作用的函數(shù)體較小。有變長指令長度的體系結(jié)構(gòu)很適合通過精心編程來減少程序長度,其中關(guān)鍵程序段可能需要使用匯編語言編碼。在一些情況下,一個指令或指令序列可能比另一種替代實現(xiàn)要小得多。例如,一個多重累加比單獨的算術(shù)操作小而且執(zhí)行速度快。當(dāng)減少程序中的指令數(shù)時,一個重要的技巧是適當(dāng)使用子例程。如果程序重復(fù)執(zhí)行同一操作,這些操作自然適合作為子例程處理

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論