咱們描述許多提升代碼性能的技術。理想的狀況是編譯器可以接受咱們編寫的任何代碼併產生儘量高效的、具備指定行爲的機器級程序現代編譯器採用了複雜的分析和優化方式並且變得愈來愈好,然而即便是最好的編譯器也受到了妨礙優化因素的阻礙。程序員必須編寫容易優化的代碼,幫助編譯器。html
兩個指針可能指向一個內存位置稱爲 內存別名使用git
void twiddle1(long *xp,long *yp){ *xp += *yp; *xp += *yp; }
當考慮指針 xp 和 yp 指向相同內存地址時,該函數可能產生二義性,及xp值翻了4倍程序員
當函數修改全局變量等 反作用 時,可能會妨礙優化。
那麼算法
long counter = 0; long func1opt(){ long t = 4 * counter + 6; counter += 4; return t; } 經過內聯替換函數調用 顯然優於 long func1in(){ long t = counter++; t += counter++; t += counter++; t += counter++; return t; }
void psum2(float a[],float p[],long n) { long i; p[0] = a[0]; for(i = 1;i < n-1;i += 2){ float mid_val =p[i-1] + a[i]; p[i] = mid_val; p[i+1] = mid_val + a[i+1]; } if(i < n) p[i] = p[i-1] + a[i]; }
當使用for循環迭代計算前置和。每次調用函數都會執行創建棧幀和恢復棧幀,這一段代碼的耗時是一個定值S。隨着循環次數n的變化,總的耗時T=S + n*L,其中L爲for循環的單位循環執行時間,在本書中又稱做每元素週期數CPE。數組
上述代碼的運行時間近似於 368+6.0n ,所以psum2的CPE爲6.0。安全
void combine4(vec_ptr v,data_t *dest){ long i; long length = vec_length(v); data_t *data = get_vec_start(v); data_t acc = IDENT; for(i = 0;i < length;i++){ acc = acc + data[i]; } *dest = acc; } 經過將循環中的累計結果放在臨時的局部變量中,能夠消除每次循環迭代沒必要要的內存讀寫
若是計算循環索引和測試循環條件的循環開銷部分所佔比重過大,這時就能夠考慮使用一種被稱做"循環展開"的方式來優化代碼。所謂循環展開就是經過在每次迭代中執行更多的數據操做來減少循環開銷的影響。其基本思想是設法把操做對象線性化,而且在一次迭代中訪問線性數據中的一小組而非單獨的某個。這樣獲得的程序將執行更少的迭代次數,因而循環開銷就被有效地下降了。數據結構
循環展開技術的好處在於它能減少循環開銷的影響。但它也不是沒有缺點的,天下沒有免費的午飯!首先,循環展開增長了生成的目標代碼的數量,這很容易理解,由於循環體在源代碼級別就已經變得龐大。讀者能夠試想它們被翻譯成目標代碼時的狀況。爲了驗證這一點,讀者可使用Visual C++來對比使用循環展開先後循環體的彙編代碼的長度,驗證結果將代表循環展開對目標代碼的長度的確有很大的影響。固然,在咱們所舉的例子中,循環展開所要付出的代價都是比較小的。固然這並不能歸納其餘全部的狀況,所以這個空間換時間的折中最優位置還須要針對具體問題來作具體的分析。 使用循環展開時一方面要考慮實際待處理數組的長度,並由此選擇一個較好的展開度;另外一方面要綜合考慮這個展開度對時空開銷比例的影響,在儘可能不會使目標代碼空間消耗激增的前提下得到最高的時間收益。另外,也可讓編譯器爲咱們完成這些工做。一般,編譯器能夠很容易地執行循環展開,但這須要設定其優化級別足夠高,因此程序員也能夠選擇讓編譯器來完成這個工做。固然,咱們曾經提醒過讀者,在開發階段並不適合將優化級別設置得太高,所以若是你但願讓編譯器執行循環展開,那麼最好等到軟件開發完成以後。併發
for(i=0;i<limit;i+=2){ acc = (acc OP data[i]) OP data[i+1]; } 經過減小循環次數,減小關鍵路徑上的操做數量。
for(i=0;i<limit;i+=2){ acc = acc OP (data[i] OP data[i+1]); } 經過從新結合變換,提升程序並行性。
想要大幅提升整個系統的速度,必須提升整個系統很大一部分的速度。取決於這個部分有多麼重要和速度提升了多少。函數
博客園連接:http://www.cnblogs.com/LeeX1997/性能
經過本週的再次學習,讓我對於如何編寫高效代碼有了進一步理解。
更重要的是,對於 高級語言-編譯器-處理器 之間的關係更明確了。