《嵌入式系統(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ù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

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

6.2程序設(shè)計(jì)方法

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

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

思考與練習(xí)題

6.1引言

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

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

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

6.2.1設(shè)計(jì)范型

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

1.狀態(tài)機(jī)

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

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

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

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

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

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

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

6.3.1消息

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

typedefstruct{

U32Message;

U32WParam;

U32LParam;

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

μC/OS-Ⅱ允許同時(shí)運(yùn)行64個(gè)任務(wù),每個(gè)任務(wù)都要有獨(dú)立的棧空間和唯一的任務(wù)優(yōu)先級(jí)。在應(yīng)用程序中創(chuàng)建新任務(wù)時(shí),必須先為任務(wù)定義自己的??臻g,選定一個(gè)系統(tǒng)唯一的任務(wù)優(yōu)先級(jí)。下面的代碼定義了一個(gè)Rtc_Disp_Task任務(wù),并為該任務(wù)分配了一個(gè)大小為STACKSIZE的棧空間,同時(shí)定義該任務(wù)的優(yōu)先級(jí)為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)會(huì)執(zhí)行Rtc_Disp_Task函數(shù)并運(yùn)行其相應(yīng)的任務(wù)。

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

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

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

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

voidRtc_Disp_Task(void*Id)//時(shí)鐘顯示更新任務(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í)通常使用繪圖設(shè)備上下文DC,這樣可保證不同任務(wù)繪圖的參數(shù)相互獨(dú)立,不會(huì)相互影響。繪圖設(shè)備上下文DC在系統(tǒng)中可定義為一個(gè)結(jié)構(gòu)體,其定義如下:

typedefstruct{

intDrawPointx;

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

intPenWidth; //畫筆寬度

U32PenMode; //畫筆模式

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

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

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è)置繪圖原點(diǎn)為屏幕左邊中點(diǎn)

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圖形界面的建立。一個(gè)通用的系統(tǒng)控件包含了以下數(shù)據(jù)結(jié)構(gòu):

typedefstruct

{ U32CtrlType; //控件的類型

U32CtrlID; //控件的ID

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

U32FontSize; //控件的字符大小

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

U8bVisible; //是否可見

}OS_Ctrl;其中,控件的ID(CtrlID)是系統(tǒng)唯一的,即每個(gè)控件的ID都不同。以下代碼演示了一個(gè)列表框控件,容量為100個(gè)列表項(xiàng)目,把系統(tǒng)中擴(kuò)展名為?.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編譯過程

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

1.編譯

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

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

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

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

2.匯編

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

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

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

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

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

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

3.鏈接

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

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

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

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

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

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

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

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

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

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

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

1.程序性能分析

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

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

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

1)程序路徑

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

下面通過前面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)指令耗時(shí)

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

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

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

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

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

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

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

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

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

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

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

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

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

②標(biāo)量數(shù)據(jù)沖突。可把數(shù)據(jù)值移到不同的位置以盡量減少?zèng)_突。

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

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

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

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

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

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

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

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

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

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

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

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

2.存儲(chǔ)器效果

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

3.能量優(yōu)化

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

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

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

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

②標(biāo)量數(shù)據(jù)沖突。可以把數(shù)據(jù)值移到不同的位置以盡量減少?zèng)_突。

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

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

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

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

溫馨提示

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

評(píng)論

0/150

提交評(píng)論