性能優(yōu)化相關(guān)_第1頁(yè)
性能優(yōu)化相關(guān)_第2頁(yè)
性能優(yōu)化相關(guān)_第3頁(yè)
性能優(yōu)化相關(guān)_第4頁(yè)
性能優(yōu)化相關(guān)_第5頁(yè)
已閱讀5頁(yè),還剩17頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

C程序優(yōu)化之路本文講述在編寫(xiě)C程序代碼的常用優(yōu)化辦法,分為I/O篇,內(nèi)存篇,算法篇,MMX匯編篇。一.I/O篇如果有文件讀寫(xiě)的話,那么對(duì)文件的訪問(wèn)將是影響程序運(yùn)行速度的一大因素。提高文件訪問(wèn)速度的主要辦法有兩個(gè):一是采用內(nèi)存映射文件,二是使用內(nèi)存緩沖。下面是一組測(cè)試數(shù)據(jù)(見(jiàn)《UNIX環(huán)境高級(jí)編程》3.9節(jié)),顯示了用18種不同的緩存長(zhǎng)度,讀1468802字節(jié)文件所得到的結(jié)果。緩沖大小用戶CPU(秒)系統(tǒng)CPU(秒)時(shí)鐘時(shí)間(秒)循環(huán)次數(shù)(秒)123.8397.9423.41468802212.3202.0215.273440146.1100.6107.236720183.050.754.0183601161.525.327.091801320.712.813.74590162295112114762557385120.01.01.1286910240.00.60.6143520480.00.40.471840960.00.40.435981920.00.30.3180163840.00.30.390327680.00.30.345655360.00.30.3231310720.00.30.312可見(jiàn),一般的當(dāng)內(nèi)存緩沖區(qū)大小為8192的時(shí)候,性能就已經(jīng)是最佳的了,這也就是為什么在H.263等圖像編碼程序中,緩沖區(qū)大小為8192的原因(有的時(shí)候也取2048大小)。使用內(nèi)存緩沖區(qū)方法的好處主要是便于移植,占用內(nèi)存少,便于硬件實(shí)現(xiàn)等。下面是讀取文件的C偽碼:intLen;BYTEbuffer[8192];ASSERT(buffer==NULL);Ifbufferisempty{Len=read(File,buffer,8192);If(len==0)Nodataandexit;}但是如果內(nèi)存比較大的時(shí)候,采用內(nèi)存映射文件可以達(dá)到更佳性能,并且編程實(shí)現(xiàn)簡(jiǎn)單。內(nèi)存映射的具體使用說(shuō)明見(jiàn)msdnOctober2001中的PlatformSDKDocumentation_BaseServices_FileStorage_FileMappingo下面是一點(diǎn)建議:內(nèi)存映射文件不能超過(guò)虛擬內(nèi)存的大小,最好也不要太大,如果內(nèi)存映射文件接近虛擬內(nèi)存大小的時(shí)候,反而會(huì)大大降低程序的速度(其實(shí)是因?yàn)樘摂M內(nèi)存不足導(dǎo)致系統(tǒng)運(yùn)行效率降低),這個(gè)時(shí)候,可以考慮分塊映射,但是我覺(jué)得如果這樣,還不如直接使用內(nèi)存緩沖來(lái)得直接一些??梢詫煞N方法統(tǒng)一使用,如我在編大圖像文件數(shù)據(jù)處理的時(shí)候(因?yàn)槭荱nix工作站,內(nèi)存很大GB單位)使用了內(nèi)存映射文件,但是為了最佳性能,也使用了一行圖像緩存,這樣在讀取文件中數(shù)據(jù)的時(shí)候,就保證了僅僅是順序讀寫(xiě)(內(nèi)存映射文件中,對(duì)順序讀寫(xiě)有專門(mén)的優(yōu)化)。在寫(xiě)文件的時(shí)候使用內(nèi)存映射文件要有一點(diǎn)小技巧:應(yīng)該先創(chuàng)建足夠大的文件,然后將這個(gè)文件映射,在處理完這個(gè)文件的時(shí)候,用函數(shù)SetFilePointer和SetEndOfFile來(lái)對(duì)文件進(jìn)行截尾。對(duì)內(nèi)存映射文件進(jìn)行操作與對(duì)內(nèi)存進(jìn)行操作類似(使用起來(lái)就象數(shù)組一樣),那么如果有大塊數(shù)據(jù)讀寫(xiě)的時(shí)候,切記使用memcpy()函數(shù)(或者CopyMemory()函數(shù))總之,如果要使用內(nèi)存映射文件,必須:1.處理的文件比較的小,2.處理的文件很大,但是運(yùn)行環(huán)境內(nèi)存也很大,并且一般在運(yùn)行該程序的時(shí)候不運(yùn)行其他消耗內(nèi)存大的程序,同時(shí)用戶對(duì)速度有特別的要求,而且對(duì)內(nèi)存占用沒(méi)有什么要求。如果以上兩個(gè)條件不滿足的時(shí)候,建議使用內(nèi)存緩沖區(qū)的辦法。本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:/liyuming1978/archive/2002/12/10/19069.aspxC程序優(yōu)化之路(二)收藏本文講述在編寫(xiě)C程序代碼的常用優(yōu)化辦法,分為I/O篇,內(nèi)存篇,算法篇,MMX匯編篇。二.內(nèi)存篇在上一篇中我們講述了如何優(yōu)化文件的讀寫(xiě),這一篇?jiǎng)t主要講述對(duì)內(nèi)存操作的優(yōu)化,主要有數(shù)組的尋址,指針鏈表等,還有一些實(shí)用技巧。I.優(yōu)化數(shù)組的尋址在編寫(xiě)程序時(shí),我們常常使用一個(gè)一維數(shù)組a[MxN]來(lái)模擬二維數(shù)組a[N][M],這個(gè)時(shí)候訪問(wèn)a[]—維數(shù)組的時(shí)候:我們經(jīng)常是這樣寫(xiě)a[jxM+i](對(duì)于a[j][i])。這樣寫(xiě)當(dāng)然是無(wú)可置疑的,但是顯然每個(gè)尋址語(yǔ)句jxM+i都要進(jìn)行一次乘法運(yùn)算。現(xiàn)在再讓我們看看二維數(shù)值的尋址,說(shuō)到這里我們不得不深入到C編譯器在申請(qǐng)二維數(shù)組和一維數(shù)組的內(nèi)部細(xì)節(jié)上一一實(shí)際在申請(qǐng)二位數(shù)組和一維數(shù)組,編譯器的處理是不一樣的,申請(qǐng)一個(gè)a[N][M]的數(shù)組要比申請(qǐng)一個(gè)a[MxN]的數(shù)組占用的空間大!二維數(shù)組的結(jié)構(gòu)是分為兩部分的:是一個(gè)指針數(shù)組,存儲(chǔ)的是每一行的起始地址,這也就是為什么在a[N][M]中,a[j]是一個(gè)指針而不是aj][0]數(shù)據(jù)的原因。是真正的MxN的連續(xù)數(shù)據(jù)塊,這解釋了為什么一個(gè)二維數(shù)組可以象一維數(shù)組那樣尋址的原因。(即a[j][i]等同于(a[0])[jxM+i])清楚了這些,我們就可以知道二維數(shù)組要比(模擬該二維數(shù)組的)一維數(shù)組尋址效率高。因?yàn)閍j][i]的尋址僅僅是訪問(wèn)指針數(shù)組得到j(luò)行的地址,然后再+i,是沒(méi)有乘法運(yùn)算的!所以,在處理一維數(shù)組的時(shí)候,我們常常采用下面的優(yōu)化辦法:(偽碼例子)inta[M*N];int*b=a;fbr(...){b[...]=...b[…]=…;b+=M;}這個(gè)是遍歷訪問(wèn)數(shù)組的一個(gè)優(yōu)化例子,每次b+=M就使得b更新為下一行的頭指針。當(dāng)然如果你愿意的話,可以自己定義一個(gè)數(shù)組指針來(lái)存儲(chǔ)每一行的起始地址。然后按照二維數(shù)組的尋址辦法來(lái)處理一維數(shù)組。不過(guò),在這里我建議你干脆就直接申請(qǐng)一個(gè)二維數(shù)組比較的好。下面是動(dòng)態(tài)申請(qǐng)和釋放一個(gè)二維數(shù)組的C代碼。intget_mem2Dint(int***array2D,introws,intcolumns) //h.263源代碼{inti;if((*array2D=(int**)calloc(rows,sizeof(int*)))==NULL)no_mem_exit(1);if(((*array2D)[0]=(int*)calloc(rows*columns,sizeof(int)))==NULL)no_mem_exit(1);for(i=1;i<rows;i++)(*array2D)[i]=(*array2D)[i-1]+columns;returnrows*columns*sizeof(int);}voidfree_mem2D(byte**array2D){if(array2D){if(array2D[0])free(array2D[0]);elseerror("free_mem2D:tryingtofreeunusedmemory",100);free(array2D);}else{error("free_mem2D:tryingtofreeunusedmemory",100);}}順便說(shuō)一下,如果你的數(shù)組尋址有一個(gè)偏移量的話,不要寫(xiě)為 a[x+offset],而應(yīng)該為b=a+offset,然后訪問(wèn)b[x]。不過(guò),如果你不是處理對(duì)速度有特別要求的程序的話,這樣的優(yōu)化也就不必要了。記住,如果編普通程序的話,可讀性和可移值性是第一位的。II.從負(fù)數(shù)開(kāi)始的數(shù)組在編程的時(shí)候,你是不是經(jīng)常要處理邊界問(wèn)題呢?在處理邊界問(wèn)題的時(shí)候,經(jīng)常下標(biāo)是從負(fù)數(shù)開(kāi)始的,通常我們的處理是將邊界處理分離出來(lái),單獨(dú)用額外的代碼寫(xiě)。那么當(dāng)你知道如何使用從負(fù)數(shù)開(kāi)始的數(shù)組的時(shí)候,邊界處理就方便多了。下面是靜態(tài)使用一個(gè)從一1開(kāi)始的數(shù)組:inta[M];int*pa=a+1;現(xiàn)在如果你使用pa訪問(wèn)a的時(shí)候就是從一1到M-2了,就是這么簡(jiǎn)單。(如果你動(dòng)態(tài)申請(qǐng)a的話,free(a)可不要free(pa)因?yàn)閜a不是數(shù)組的頭地址)我們需要鏈表嗎相信大家在學(xué)習(xí)《數(shù)據(jù)結(jié)構(gòu)》的時(shí)候,對(duì)鏈表是相當(dāng)熟悉了,所以我看有人在編寫(xiě)一些耗時(shí)算法的時(shí)候,也采用了鏈表的形式。這樣編寫(xiě)當(dāng)然對(duì)內(nèi)存的占用(似乎)少了,可是速度呢?如果你測(cè)試:申請(qǐng)并遍歷10000個(gè)元素鏈表的時(shí)間與遍歷相同元素的數(shù)組的時(shí)間,你就會(huì)發(fā)現(xiàn)時(shí)間相差了百倍!(以前測(cè)試過(guò)一個(gè)算法,用鏈表是1分鐘,用數(shù)組是4秒鐘)。所以這里我的建議是:在編寫(xiě)耗時(shí)大的代碼時(shí),盡可能不要采用鏈表!其實(shí)實(shí)際上采用鏈表并不能真正節(jié)省內(nèi)存,在編寫(xiě)很多算法的時(shí)候,我們是知道要占用多少內(nèi)存的(至少也知道個(gè)大概),那么與其用鏈表一點(diǎn)點(diǎn)的消耗內(nèi)存,不如用數(shù)組一步就把內(nèi)存占用。采用鏈表的形式一定是在元素比較少,或者該部分基本不耗時(shí)的情況下。(我估計(jì)鏈表主要慢是慢在它是一步步申請(qǐng)內(nèi)存的,如果能夠象數(shù)組一樣分配一個(gè)大內(nèi)存塊的話,應(yīng)該也不怎么耗時(shí),這個(gè)沒(méi)有具體測(cè)試過(guò)。僅僅是猜想:P)本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:/liyuming1978/archive/2002/12/09/19070.aspxC程序優(yōu)化之路(三) liyuming1978@163.com本文講述在編寫(xiě)C程序代碼的常用優(yōu)化辦法,分為I/O篇,內(nèi)存篇,算法篇。MMX本來(lái)我也想歸在這里的,但是由于內(nèi)容和標(biāo)題不太符和,決定換一個(gè)名字,叫MMX技術(shù)詳解,和H263視頻壓縮技術(shù)中的MMX應(yīng)用兩篇文章。三.算法篇在上一篇中我們講述了對(duì)內(nèi)存操作的優(yōu)化,這一篇?jiǎng)t主要講述一些常用的優(yōu)化算法。這個(gè)東東太多,內(nèi)容可能會(huì)有點(diǎn)凌亂,見(jiàn)諒。I.從小處說(shuō)起:先說(shuō)說(shuō)一些小地方先:比如n/2寫(xiě)為n>>1這個(gè)是常用的方法,不過(guò)要注意的是這兩個(gè)不是完全等價(jià)的!因?yàn)椋喝绻鹡=3的話,n/2=1;n>>1=1;但是,如果n=-3的話,n/2=-1;n>>1=-2所以說(shuō)在正數(shù)的時(shí)候,他們都是向下取整,但是負(fù)數(shù)的時(shí)候就不一樣了。(在JPG2000中的整數(shù)YUV到RGB變換一定要使用>>來(lái)代替除法就是這個(gè)道理)還有就是a=a+1要寫(xiě)為a++;a=a+b要寫(xiě)為a+=b(估計(jì)一般用VB的才會(huì)寫(xiě)a=a+1:P)將多種運(yùn)算融合:比如a[i++];就是先訪問(wèn)a[i],再令i加1;從匯編的角度上說(shuō),這個(gè)確實(shí)是優(yōu)化的,如果寫(xiě)為a[i],和i++的話,有可能就會(huì)有兩次的對(duì)i變量的讀,一次寫(xiě)(具體要看編譯器的優(yōu)化能力了),但是如果a[i++]的話,就一定只讀寫(xiě)i變量一次。不過(guò)這里有一個(gè)問(wèn)題要注意:在條件判斷內(nèi)的融合一定要小心,比如:(idct變換中的0塊判斷,陳王算法)if(!((x1=(blk[8*4]<<8))I(x2=blk[8*6])I(x3=blk[8*2])I(x4=blk[8*1])I(x5=blk[8*7])(x6=blk[8*5])I(x7=blk[8*3])))在條件判斷中融合了賦值語(yǔ)句,但是實(shí)際上如果條件為真的話,是不需要這些賦值語(yǔ)句的,也就是說(shuō)當(dāng)條件真的時(shí)候,多了一些垃圾語(yǔ)句,這些是在h263源碼上的問(wèn)題,雖然這些垃圾語(yǔ)句使得計(jì)算0塊的時(shí)候,時(shí)間增加了30%,但是由于idct僅僅占1%的時(shí)間,0塊又僅僅30%~70%的時(shí)間,所以這些性能損失是沒(méi)有什么關(guān)系的。(這是后來(lái)我用匯編改寫(xiě)源碼的時(shí)候得到的結(jié)論)。這里也說(shuō)明了,程序優(yōu)化一定重點(diǎn)在最耗時(shí)的地方。對(duì)于不耗時(shí)的代碼優(yōu)化是沒(méi)有太大的實(shí)用意義的。.以內(nèi)存換速度:天下總是難有雙得的事情,編程也是一樣,大多數(shù)情況,速度同內(nèi)存(或者是性能,比如說(shuō)壓縮性能什么的)是不可兼得的。目前程序加速的常用算法一個(gè)大方面就是利用查表來(lái)避免計(jì)算(比如在jpg有huffman碼表,在YUV到RGB變換也有變換表)這樣原來(lái)的復(fù)雜計(jì)算現(xiàn)在僅僅查表就可以了,雖然浪費(fèi)了內(nèi)存,不過(guò)速度顯著提升,還是很劃算的。在數(shù)據(jù)庫(kù)查詢里面也有這樣的思想,將熱點(diǎn)存儲(chǔ)起來(lái)以加速查詢?,F(xiàn)在介紹一個(gè)簡(jiǎn)單的例子,(臨時(shí)想的,呵呵):比如,在程序中要經(jīng)常(一定要是經(jīng)常!)計(jì)算1000到2000的階乘,那么我們可以使用一個(gè)數(shù)組a[1000]先把這些值算好,保留下來(lái),以后要計(jì)算1200!的時(shí)候,查表a[1200-1000]就可以了。化零為整由于零散的內(nèi)存分配,以及大量小對(duì)象建立耗時(shí)很大,所以對(duì)它們的優(yōu)化有時(shí)會(huì)很有效果,比如上一篇我說(shuō)的鏈表存在的問(wèn)題,就是因?yàn)榇罅康牧闵?nèi)存分配?,F(xiàn)在就從一個(gè)vb的程序說(shuō)起,以前我用vb給別人編小程序的時(shí)候,(呵呵,主要是用vb編程比vc快,半天就可以寫(xiě)一個(gè))在使用MSFlexGrid控件的時(shí)候(就是一個(gè)表格控件),發(fā)現(xiàn)如果一行一行的增加新行,刷新速度十分的慢,所以我就每次增加100行,等到數(shù)據(jù)多到再加新行的時(shí)候,再加100行,這樣就“化零為整”了,使用這樣的方法,刷新的速度比原來(lái)快了n倍!其實(shí)這樣的思想應(yīng)用很多,如:程序運(yùn)行的時(shí)候,其實(shí)就占用了一定的空間,后來(lái)的小塊內(nèi)存分配是先在這個(gè)空間上的,這就保證了內(nèi)存碎片盡可能的少,同時(shí)加快運(yùn)行速度。條件語(yǔ)句或者case語(yǔ)句將最有可能的放在前面優(yōu)化效果不明顯。想得到就用吧,想不到就算了。為了程序的可讀性,不去做那些編譯器可以做的或者優(yōu)化不明顯的處理:這個(gè)是很重要的,一個(gè)普通程序的好壞,主要是它的可讀性,可移植性,可重用性,然后才是它的性能。所以,如果編譯器本身可以幫助我們優(yōu)化的話,我們就沒(méi)有必要寫(xiě)那些大家都不怎么看得懂的東西。比如a=52(結(jié)束)一16(起始);這樣寫(xiě)可能是因?yàn)樵趧e人讀程序的時(shí)候,一下就明白了a的含義。我們不用寫(xiě)為a=36,因?yàn)榫幾g器是會(huì)幫我們算出來(lái)的。IV.具體情況具體分析:具體情況具體分析,這是放之四海而皆準(zhǔn)的真理。沒(méi)有具體的分析,就不能針對(duì)問(wèn)題靈活應(yīng)用解決的辦法。下面我就說(shuō)說(shuō)分析的方法。即如何找到程序的耗時(shí)點(diǎn):(從最簡(jiǎn)單的辦法說(shuō)起,先說(shuō)明一個(gè)函數(shù)GetTickCount()這個(gè)函數(shù)在頭尾各調(diào)用一次,返回值相減就是程序的耗時(shí),精確到1ms)對(duì)于認(rèn)為是比較耗時(shí)的函數(shù),運(yùn)行兩次,或者將函數(shù)內(nèi)部的語(yǔ)句注釋掉(要保證程序可以運(yùn)行),看看多(或者少了)多少時(shí)間。這個(gè)辦法簡(jiǎn)單不精確。每個(gè)地方都用GetTickCount(涵數(shù)測(cè)試時(shí)間,注意GetTickCount()只能精確到ms。一般的小于10ms就不太精確了。使用另外一個(gè)函數(shù)QueryPerformanceCounter(&Counter)和QueryPerformanceFrequency(&Frequency),前面計(jì)算cpu時(shí)鐘周期,后面是cpu頻率相除就是時(shí)間。不過(guò)如果你要精確到這一步的話,建議將進(jìn)程設(shè)置為最高級(jí)別,防止它被阻塞。最后講講我處理的一個(gè)程序:程序要求我忘了,反正里面有一個(gè)函數(shù),函數(shù)里面有一個(gè)大的循環(huán),循環(huán)內(nèi)部的處理比較耗時(shí)。結(jié)果最初程序表現(xiàn)出來(lái)的狀況是開(kāi)始還很快,越到后面越慢;我在跟蹤程序中變量的時(shí)候,發(fā)現(xiàn)最初的循環(huán)在循環(huán)幾次后就跳出了,而后面的循環(huán)次數(shù)越來(lái)越多。找到了為什么慢的原因,就可以對(duì)癥下藥了,我的處理是每次循環(huán)不是從頭開(kāi)始,而是從上一次循環(huán)跳出的地方開(kāi)始左右循環(huán)(因?yàn)榭赡芟乱淮窝h(huán)跳出的地方別上一次的小,所以也要遍歷前面的),這樣程序的速度在后面也很快了。我講這個(gè)的道理就是在實(shí)際運(yùn)用中,要具體的分析程序慢的真正原因,才能達(dá)到最佳的優(yōu)化效果。本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:/liyuming1978/archive/2002/12/11/19071.aspxMMX開(kāi)發(fā)文檔IMMX簡(jiǎn)介Intel的MMXT^術(shù)是對(duì)Intel體系結(jié)構(gòu)(ia)指令集的擴(kuò)展。該技術(shù)使用了單指令多數(shù)據(jù)技術(shù)(SIMD)技術(shù),以并行方式處理多個(gè)數(shù)據(jù)元素,從而提高了多媒體和通訊軟件的運(yùn)行速度。MMXtm指令集增加了57條新的操作碼和一個(gè)新的64位四字?jǐn)?shù)據(jù)類型。MMX?技術(shù)提高了很多應(yīng)用程序的執(zhí)行性能,例如活動(dòng)圖像、視頻會(huì)議、二維圖形和三維圖形。幾乎每一個(gè)具有重復(fù)性和順序性整數(shù)計(jì)算的應(yīng)用程序都可以從MMXT^術(shù)中受益。對(duì)于8位、16位和32位數(shù)據(jù)元素的處理,改善了程序的性能。一個(gè)MMXTM指令可一次操作8個(gè)字節(jié),且在一個(gè)時(shí)鐘周期內(nèi)完成兩條指令,也就是說(shuō),可在一個(gè)時(shí)鐘周期內(nèi)處理16個(gè)數(shù)據(jù)元素。另外,為增強(qiáng)性能,MMXT^術(shù)為其它功能釋放了額外的處理器周期。以前需要其它硬件支持的應(yīng)用程序,現(xiàn)在僅需軟件就能運(yùn)行。更小的處理器占用率給更高程度的并發(fā)技術(shù)提供了條件,在當(dāng)今眾多的操作系統(tǒng)中這些并發(fā)技術(shù)得到了利用。在基于Intel的分析系統(tǒng)中,某些功能的性能提高了50%到400%。這種數(shù)量級(jí)的性能擴(kuò)展可以在新一代處理器中得到體現(xiàn)。在軟件內(nèi)核中,其速度得到更大的提高,其幅度為原有速度的三至五倍。MMX的缺點(diǎn):由于MMX的運(yùn)算指令必須在數(shù)據(jù)配對(duì)整齊的時(shí)候才能使用,所以使用MMX指令要比普通的匯編指令多余許多分組配對(duì)的指令,如果運(yùn)算不是特別的整齊的話,就要浪費(fèi)大量的時(shí)間在數(shù)據(jù)的配對(duì)上,所以說(shuō)MMX指令也不是萬(wàn)能的,也有其很大的缺陷。同時(shí)MMX指令在處理16位數(shù)據(jù)的時(shí)候才能發(fā)揮最大的作用,處理8位數(shù)據(jù)要有一點(diǎn)技巧。而處理32位數(shù)據(jù),MMX指令幾乎沒(méi)有什么加速能力。(考慮分組耗時(shí)的話)IIMMX基本指令集具體細(xì)節(jié)請(qǐng)參閱《INTEL體系結(jié)構(gòu)MMX技術(shù)程序員參考手冊(cè)》第五章2.1拷貝指令movq:64位數(shù)據(jù)拷貝,如果內(nèi)存8位對(duì)齊的話,是一個(gè)64位寫(xiě),否則2個(gè)32位寫(xiě)。movd:32位數(shù)據(jù)拷貝,注意:如果從內(nèi)存向MMX寄存器拷貝,MMX高32位清零!2.2分組指令分組指令是MMX特有的,所以對(duì)于它我們要特別的關(guān)注。分組指令基本上可以分為2類,一類是不帶符號(hào)緊縮的,一類是帶符號(hào)緊縮的?,F(xiàn)在我們分別予以介紹:punpcklbw/punpcklwd/punpckldq(l表示低位分組,bw8位,wd16位,dq32位):它是簡(jiǎn)單的將兩個(gè)MMX寄存器的低32位交錯(cuò)組合為一個(gè)64位數(shù)據(jù)。所以它是不能將長(zhǎng)數(shù)據(jù)轉(zhuǎn)換為短數(shù)據(jù)的。packuswb將16位數(shù)據(jù)轉(zhuǎn)換為無(wú)符號(hào)的8位數(shù)據(jù)。所以可以將兩個(gè)MMX寄存器不交錯(cuò)的合為一個(gè)64位數(shù)據(jù)。packsswb/packssdw將32位一》16位,16位一》8位,都是有符號(hào)的數(shù)據(jù)。2.3運(yùn)算指令加法運(yùn)算指令:paddb(w)(d):沒(méi)有越界保護(hù)的加法,當(dāng)越界的時(shí)候僅僅丟棄超出范圍的高位比特,(b)(w)(d)分別為8,16,32位加法;paddsb(w):具有越界保護(hù)的有符號(hào)加法,當(dāng)上溢的時(shí)候?yàn)?x7fff,下溢的時(shí)候?yàn)?x8000;paddusb(w):具有越界保護(hù)的無(wú)符號(hào)加法,當(dāng)上溢的時(shí)候?yàn)?x7fff,下溢的時(shí)候?yàn)?x0。減法運(yùn)算指令同上;add改為sub。乘法指令:pmullw/pmulhw是4個(gè)16位數(shù)據(jù)的乘法,pmullw中是結(jié)果的低16位,pmulhw是結(jié)果的高16位。pmaddwd乘加指令。2.4邏輯指令,移位指令和EMMS指令細(xì)節(jié)參見(jiàn)《INTEL體系結(jié)構(gòu)MMX技術(shù)程序員參考手冊(cè)》。IIIMMX經(jīng)典處理策略數(shù)據(jù)輸入輸出:在輸入數(shù)據(jù)的時(shí)候,經(jīng)典的處理方法是將一個(gè)數(shù)組整個(gè)“Loadw到MMX寄存器中。這樣簡(jiǎn)單同時(shí)利用了MMX64位讀寫(xiě)數(shù)據(jù)的能力,提高了性能。同樣在輸出的時(shí)候,也是將一個(gè)64位MMX寄存器中的數(shù)據(jù)內(nèi)容整個(gè)“Store^a內(nèi)存中。如果實(shí)在是不能這樣處理的話,就要利用移位指令了。比如說(shuō)將一個(gè)MMX內(nèi)的4個(gè)16位數(shù)據(jù)分別拷貝到不同的內(nèi)存變量(或者16位通用寄存器中)x1,x2,x3,x4,那么可以這樣處理:movd eax,mm1psrlqmm1,32movd ebx,mm1TOC\o"1-5"\h\zmov x1,axmov x2,bxshr eax,16shr ebx,16mov x3,axmov x4,bx可見(jiàn)如果不采用數(shù)組形式的話,輸入輸出將十分的麻煩。數(shù)據(jù)分組以及求絕對(duì)值的方法等:細(xì)節(jié)請(qǐng)參閱《INTEL體系結(jié)構(gòu)MMX?技術(shù)開(kāi)發(fā)者手冊(cè)》第五章IV自定義組合指令①八位無(wú)符號(hào)數(shù)的移位:

在MMX指令集中是沒(méi)有8位數(shù)據(jù)的移位指令的,但是有的時(shí)候我們確實(shí)需要,所以可以用以下兩個(gè)指令來(lái)實(shí)現(xiàn):psrlqmm0,1pandmm0,0x7f7f7f7f7f7f7f7fpandmm0,0x7f7f7f7f7f7f7f7f②如何防止計(jì)算過(guò)程中越界:是可以使用的,但是如果結(jié)果差錯(cuò)1都不可容忍的話,就要進(jìn)行比如在計(jì)算的時(shí)候,我們有(x1+x2+1)>>1,這個(gè)時(shí)候x1+x2就會(huì)越界(8位數(shù)據(jù)),那么我們就不得不使用替代了辦法,比如(x1>>1+x2>>1是可以使用的,但是如果結(jié)果差錯(cuò)1都不可容忍的話,就要進(jìn)行pandmm0,0x01010101010101//保留數(shù)據(jù)的最后一位pandmm1,0x01010101010101//保留數(shù)據(jù)的最后一位pormm0,mm1paddusbpandmm0,0x01010101010101//保留數(shù)據(jù)的最后一位pandmm1,0x01010101010101//保留數(shù)據(jù)的最后一位pormm0,mm1paddusbmmx,mm0//修正數(shù)據(jù)(x1>>2+x2>>2):這個(gè)處理是通用的pandmm0,0x03030303030303//保留數(shù)據(jù)的最后兩位pandmm1,0x03030303030303//保留數(shù)據(jù)的最后兩位pandmm0,0x03030303030303//保留數(shù)據(jù)的最后兩位pandmm1,0x03030303030303//保留數(shù)據(jù)的最后兩位paddusbmm0,mm1psrlqmm0,2psrlqmm0,2pandmm0,0x3f3f3f3f3f3f3f3fpaddusbmmx,mm0pandmm0,0x3f3f3f3f3f3f3f3fpaddusbmmx,mm0符號(hào)擴(kuò)展指令:mm0:*,*A,B=>現(xiàn)在要符號(hào)擴(kuò)展為mm0:(A符號(hào))A,(A符號(hào))Bmovqmm1,mm0pcgtmmm1,0 II比較皿皿0,生成mml:(A符號(hào))(B符號(hào))()()punpcklwdmm0,mm1分組指令除了基本的分組指令以外,我們還可以利用移位指令和pandpor指令來(lái)實(shí)現(xiàn)分組的功能,移位主要是要產(chǎn)生0,這樣pormm0,mml就可以將mm0和mml合并了。比如:mm0(*,*,A,B)mm1(0,0,C,D)貝Upsllq mm0,32por mm0,mm1=>(A,B,C,D)當(dāng)然這個(gè)例子我們可以用普通的分組指令實(shí)現(xiàn),但是在某些復(fù)雜的處理中,這樣的處理是必須的??傊?,要靈活運(yùn)用MMX的現(xiàn)有指令來(lái)實(shí)現(xiàn)自己需要的功能。VMMX編程心得使用MMX技術(shù)進(jìn)行編程,目的就是要提高運(yùn)算速度,所以,對(duì)于如何盡可能的提高代碼的效率,我們是要特別關(guān)注的。這里,我介紹一些需要注意的事項(xiàng)。①盡可能的提高內(nèi)存訪問(wèn)的容量,我們可以看看下面的代碼:for(j=0;j<h;j++){d[0]=s[0];d[1]=s[1];d[2]=s[2];d[3]=s[3];d[4]=s[4];d[5]=s[5];d[6]=s[6];d[7]=s[7];d[8]=s[8];d[9]=s[9];d[10]=s[10];d[11]=s[11];d[12]=s[12];d[13]=s[13];d[14]=s[14];d[15]=s[15];s+=lx2;d+=lx;}_asm{pushfmovedx,dwordptrhxorecx,ecxmovesi,dwordptrsmovedi,dwordptrdmoveax,lx2movebx,lxAGAIN:movq mm0,byteptr[esi]movq mm1,byteptr[esi+8]movq byteptr[edi],mm0movq byteptr[edi+8],mm1add esi,eaxadd edi,ebxadd ecx,1cmp ecx,edxjl AGAINemmspopf}僅僅將幾個(gè)8位的寫(xiě),改為64位的寫(xiě),測(cè)試得到速度提升了25%,同樣的道理,我們要盡可能的將幾個(gè)movq寫(xiě)在一起,這樣可以提高5%左右的速度。原C代碼的效率也是很高的,它不用數(shù)組的【】【】來(lái)尋址,而是將s+=lx2;從而將二維數(shù)組的尋址改為一維數(shù)組的尋址。盡可能的減少尋址的復(fù)雜度,這也是一種高效的辦法。還有一點(diǎn)就是如果將原來(lái)的簡(jiǎn)單賦值改為memcpy()的話,可以提高大約10%的速度。這也是提高了數(shù)據(jù)流通容量的關(guān)系。②一些要注意的地方:盡可能的使用static變量,訪問(wèn)這樣的變量是很快的=訪問(wèn)立即數(shù)的速度由于只有一個(gè)mmx移位寄存器,(移位分組指令)是不能配對(duì)的3.不要在eax使用完,使用ax,不要使用完一個(gè)皿皿1,就立即使用它3.可以這樣立即使用mml,movqmm2,mm1movqmm1,mm3(Z順序是可以的)(4個(gè)以上)movq盡可能的在一起,前提是在一起的mov不要使用一樣的mmx寄存器moveax,[esi]([esi+2*eax])訪問(wèn)尋址的內(nèi)存是特別的慢的同上stow也是很慢的(movcx,n; loop是很慢的,如果可能,要展開(kāi)循環(huán))盡可能的在寄存器中完成操作,不要去訪問(wèn)內(nèi)存用變量名訪問(wèn)變量,尤其是static的,是很快.訪問(wèn)尋址的內(nèi)存的速度下降》數(shù)據(jù)不對(duì)齊8位的速度下降》指令不配對(duì)的速度下降所以在傳統(tǒng)的代碼優(yōu)化的方法中,構(gòu)造數(shù)組,然后將運(yùn)算變?yōu)椴楸淼姆椒?,有的時(shí)候在MMX技術(shù)內(nèi)反而會(huì)降低速度。(這個(gè)時(shí)候,如果真的用查表有提升速度的話,建議采用段地址+偏移量的辦法)本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:/liyuming1978/archive/2002/12/30/19072.aspxC程序優(yōu)化5年10月15日點(diǎn)擊次對(duì)程序進(jìn)行優(yōu)化,通常是指優(yōu)化程序代碼或程序執(zhí)行速度。優(yōu)化代碼和優(yōu)化速度實(shí)際上是一個(gè)予盾的統(tǒng)一,一般是優(yōu)化了代碼的尺寸,就會(huì)帶來(lái)執(zhí)行時(shí)間的增加,如果優(yōu)化了程序的執(zhí)行速度,通常會(huì)帶來(lái)代碼增加的副作用,很難魚(yú)與熊掌兼得,只能在設(shè)計(jì)時(shí)掌握一個(gè)平衡點(diǎn)。一、程序結(jié)構(gòu)的優(yōu)化1、程序的書(shū)寫(xiě)結(jié)構(gòu)雖然書(shū)寫(xiě)格式并不會(huì)影響生成的代碼質(zhì)量,但是在實(shí)際編寫(xiě)程序時(shí)還是應(yīng)該尊循一定的書(shū)寫(xiě)規(guī)則,一個(gè)書(shū)寫(xiě)清晰、利于以后的維護(hù)。在書(shū)寫(xiě)程序時(shí),特別是對(duì)于While、for、do...while、L..case等語(yǔ)句或這些語(yǔ)句嵌套組合時(shí),應(yīng)采用“縮格”的書(shū)寫(xiě)形式,日戶標(biāo)識(shí)符除要遵循標(biāo)識(shí)符的命名規(guī)則以外,一般不要用代數(shù)符號(hào)(如a、b、量名,應(yīng)選取具有相關(guān)含義的英文單詞(或縮寫(xiě))或漢語(yǔ)拼音作為標(biāo)識(shí)符,以增生,如:count、numberl、red、work等。m級(jí)程序設(shè)計(jì)語(yǔ)言,提供了十分完備的規(guī)范化流程控制結(jié)構(gòu)。因此在采用C語(yǔ)艾用系統(tǒng)程序時(shí),首先要注意盡可能采用結(jié)構(gòu)化的程序設(shè)計(jì)方法,這樣可使整蘆結(jié)構(gòu)清晰,便于調(diào)試和維護(hù)。于一個(gè)較大的應(yīng)用程序,通常將整個(gè)程序按功莫塊,不同模塊完成不同的功能。各個(gè)模塊可以分別編寫(xiě),甚至還可以由不同一般單個(gè)模塊完成的功能較為簡(jiǎn)單,設(shè)計(jì)和調(diào)試也相對(duì)容易一些。在C語(yǔ)言可以認(rèn)為是一個(gè)模塊。所謂程序模塊化,不僅是要將整個(gè)程序劃分成若干個(gè)要的是,還應(yīng)該注意保持各個(gè)模塊之間變量的相對(duì)獨(dú)立性,即保持模塊的獨(dú)立全局變量等。對(duì)于一些常用的功能模塊,還可以封裝為一個(gè)應(yīng)用程序庫(kù),以便妾調(diào)用。但是在使用模塊化時(shí),如果將模塊分成太細(xì)太小,又會(huì)導(dǎo)致程序的執(zhí)入和退出一個(gè)函數(shù)時(shí)保護(hù)和恢復(fù)寄存器占用了一些時(shí)間)。史程中,對(duì)于經(jīng)常使用的一些常數(shù),如果將它直接寫(xiě)到程序中去,一旦常數(shù)的數(shù)必、須逐個(gè)找出程序中所有的常數(shù),并逐一進(jìn)行修改,這樣必然會(huì)降低程序的可應(yīng)盡量當(dāng)采用預(yù)處理命令方式來(lái)定義常數(shù),而且還可以避免輸入錯(cuò)誤。句扁譯(ifdef)的地方就使用條件編譯而不使用if語(yǔ)句,有利于減少編譯生成的代弋中各種運(yùn)算執(zhí)行的優(yōu)先順序不太明確或容易混淆的地方應(yīng)當(dāng)采用圓括號(hào)勺優(yōu)先順序。一個(gè)表達(dá)式通常不能寫(xiě)得太復(fù)雜,如果表達(dá)式太復(fù)雜,時(shí)間久了容易看得懂,不利于以后的維護(hù)。Il數(shù),在使用之前,應(yīng)對(duì)函數(shù)的類型進(jìn)行說(shuō)明,對(duì)函數(shù)類型的說(shuō)明必須保證它與賁類型一致,對(duì)于沒(méi)有參數(shù)和沒(méi)有返回值類型的函數(shù)應(yīng)加上“void”明。如果馬的長(zhǎng)度,可以將程序中一些公共的程序段定義為函數(shù),在Keil中的高級(jí)別優(yōu)如果需要縮短程序的執(zhí)行時(shí)間,在程序調(diào)試結(jié)束后,將部分函數(shù)用宏定義來(lái)該在程序調(diào)試結(jié)束后再定義宏,因?yàn)榇蠖鄶?shù)編譯系統(tǒng)在宏展開(kāi)之后才會(huì)報(bào)錯(cuò),昔的難度。局變量,多用局部變量。因?yàn)槿肿兞渴欠旁跀?shù)據(jù)存儲(chǔ)器中,定義一個(gè)全局變-個(gè)可以利用的數(shù)據(jù)存儲(chǔ)器空間,如果定義了太多的全局變量,會(huì)導(dǎo)致編譯器0以分配。而局部變量大多定位于MCU內(nèi)部的寄存器中,在絕大多數(shù)MCU操作速度比數(shù)據(jù)存儲(chǔ)器快,指令也更多更靈活,有利于生成質(zhì)量更高的代碼,而勺占用的寄存器和數(shù)據(jù)存儲(chǔ)器在不同的模塊中可以重復(fù)利用。編譯程序選項(xiàng)孕幾種不同的優(yōu)化選項(xiàng),在使用前應(yīng)理解各優(yōu)化選項(xiàng)的含義,然后選用最合適弋。通常情況下一旦選用最高級(jí)優(yōu)化,編譯程序會(huì)近乎病態(tài)地追求代碼優(yōu)化,蘆的正確性,導(dǎo)致程序運(yùn)行出錯(cuò)。因此應(yīng)熟悉所使用的編譯器,應(yīng)知道哪些參芝到影響,哪些參數(shù)不會(huì)受到影響。有“?!甑昵焙汀癊nableCodeCompression”兩個(gè)優(yōu)化選項(xiàng)。VR中,“Tiny%fsmall”兩種內(nèi)存模式。7種不同的內(nèi)存模式選項(xiàng)。優(yōu)化選項(xiàng)更多,一不小心更容易選到不恰當(dāng)?shù)倪x項(xiàng)。匕算法和數(shù)據(jù)結(jié)構(gòu)普言,知道各種算法的優(yōu)缺點(diǎn),具體資料請(qǐng)參見(jiàn)相應(yīng)的參考資料,有很多計(jì)算機(jī)召。將比較慢的順序查找法用較快的二分查找或亂序查找法代替插入排序目快速排序、合并排序或根排序代替,都可以大

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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)論