代碼優化的藝術

1.整數求餘.我萬萬沒有想到過,求餘運算符%也會成爲被優化的對象,從前寫下循環鏈表的例子:

int a[N];
void append(int m)
{
 i = (i+1) % N;
 a[i] = m;
}


看哪,多麼簡潔的代碼,多麼美妙,你幾乎看不出什麼破綻.然而,你聽他說要把%給優化掉時,你會不會大跌眼睛?至少我是這樣."儘管大多數算術運算需要花費大約10納秒的時間,但%卻要接近100納秒,%的開銷是及其昂貴的!"這樣優化的建議是讓你用便宜的邏輯判斷取代%運算:

++i;
if(i==N) i=0;
這樣如果這段代碼是你的程序的核心的話,估計他能讓你的程序快兩倍.
2.對於循環的優化.這一點我同樣感到驚訝,並非他有多麼的神祕,其實很好懂,但是由於定向思維的影響,我們從來沒有考慮過問題還可以這樣優化:
第一,你可以通過避免循環的條件判斷.
例如在一個數組中查找某個值,在a[N]找b,很明顯順序查找我們寫的最多的代碼是:
 
search(int a[],int b)
{
 for(int i=0;i<N;++i)
  if(a[i] == b) 
	return i;
 return -1;
}

同樣你會多麼的讚美,多麼的滿足,好像在沒有比這個更完美的了,但是美神並不如此認爲,他想下面的優化可以帶來大約5%的提速:(多加一個空間使得數組長度爲N+1)

search(int a[],int b)
{
 a[N] = b;
 for(int i=0;;++i)
  if(a[i] == b) 
	break;
 if(i==N)
	 return -1;
 return i;
}

看哪,他確實比原來更好,因爲每次循環從原來的執行兩次判斷(a[i]==b和i<N)變成現在的一次判斷(a[i]==b),你可以理解,但是你未必能想到可以這樣優化.
第二你可以減少循環所執行的次數.
這一點你也許不可理解,和我一樣,他的策略是循環展開,我在想既然展開爲什麼要成爲循環?但是你接着往下看的時候,你就會發現,這是二分查找最具優化性能的必要條件.上面循環優化的結果可能象這樣:

search(int a[],int b)
{
 a[N] = b;
 for(int i=0;;++i)
  if(a[i] == b)
 break;
 if(i==N)
  return -1;
 return i;
}

對於現代流水線技術的計算機,他可以避免流水線阻塞,減少分支,增加指令級並行.
3.向二分查找進發.
不必在回味我們的經典寫法了,因爲我們都很熟悉,何況他馬上就要面臨被優化的命運,呵呵.下面直解給出做法:
假設已排好序的數組a[N],其中N=1000,也就是我們常說的問題的規模爲1000,首先我們取小於1000的但是2的最大冪值,很顯然他是512,我們知道二分查找法的優良性能在於他每次讓下一次問題規模減辦,這是2的冪次的速度.
第一步的優化是放棄我們的上界下屆標識變量,使用下屆和距離來表示我們問題的空間:

i=512;p=-1;
if(a[511]<b) 
	p = 488;
while(i != 1)
{
 i = i/2;
 if(a[p+i]<b)
	 p = p+i;
 q = p+1;
 if(q>1000 || a[q] != b)
	 q = -1;
 return q;
}

對於,這個問題我們知道i的取值,是一定的,因爲2的若干次冪是一定,可以取值的範圍就是{512,256,128,64,32,16,8,4,2,1}
因此我們有理由不使用循環,即使代碼量增加一些,但是性能卻提高不少,何樂不爲?看:

p = -1;
if(a[p+512]<b) p += 512;
if(a[p+512]<b) p += 256;
if(a[p+512]<b) p += 128;
if(a[p+512]<b) p += 64;
if(a[p+512]<b) p += 32;
if(a[p+512]<b) p += 16;
if(a[p+512]<b) p += 8;
if(a[p+512]<b) p += 4;
if(a[p+512]<b) p += 2;
if(a[p+512]<b) p += 1;
q = p+1;
if(q>1000 || a[q] != b)
	 q=-1;
return q; 

你知道這有多妙,我只要增加一個語句便可以處理規模規模爲2000的問題,再增加一條語句,你就可以處理規模爲4000的語句,天哪,不僅如此你僅僅用到的只是一些簡單判斷,性能上已經是無可挑剔,如果你在處理一個很複雜的矩陣問題,我希望你能這樣作.

備註:
看了本文,才知道代碼的優化可以做到這麼細節化,實在不讓人感概作者的厲害之處。

本文轉自:http://blog.csdn.net/niushuai666/article/details/6401258

發佈了32 篇原創文章 · 獲贊 5 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章