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

下載本文檔

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

文檔簡介

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

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

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論