摘要:這一章節(jié)主要講述了以提高程序的運(yùn)行速率進(jìn)行程序優(yōu)化的三個(gè)層次(也就是優(yōu)化時(shí)間,而暫時(shí)不考慮空間性能的問題),并且主要介紹了如何做到指令級的優(yōu)化。
關(guān)鍵詞:指令流水線
目錄:
??1. 程序的指令級優(yōu)化
??2. 程序的代碼級優(yōu)化
??3. 程序的算法級優(yōu)化
1. 程序的指令級優(yōu)化
我們知道,對一個(gè)單核的機(jī)器進(jìn)行密集型計(jì)算的時(shí)候,使用多線程是不會有效率的提高的。但使用單個(gè)線程,不同的代碼也會很大的性能差異,如何單核的計(jì)算效率達(dá)到最大,就需要使用指令級的優(yōu)化。
在計(jì)算機(jī)中有時(shí)鐘周期的概念,也就是進(jìn)行一次操作需要的時(shí)間。我們說CPU的主頻是多少GHz的時(shí)候,表明CPU一秒可以處理多少個(gè)操作。實(shí)際上CPU中有好幾個(gè)功能單元,每個(gè)功能單元實(shí)現(xiàn)不同的功能,這些功能單元加在一起的頻率才是主頻,而CPU指令的處理又是流水線化的。也就是一個(gè)指令的幾個(gè)操作就像流水線一樣會通過不同的功能單元進(jìn)行處理。
假設(shè)你的程序是順序運(yùn)行的指令,也就是一個(gè)指令結(jié)束以后,才能執(zhí)行一下個(gè)指令,這樣每個(gè)時(shí)刻都只有一個(gè)功能單元在運(yùn)行,這樣的代碼就不能利用流水線化的執(zhí)行方式了。最大壓榨CPU性能的方法應(yīng)該是使指令填滿流水線。而這取決你的代碼實(shí)現(xiàn)的功能能否做到指令級的并行,以及你是否能寫出指令級并行的代碼。前者需要你判斷你的算法能否并行,比如實(shí)現(xiàn)兩個(gè)向量元素的相乘或者相加,很顯然不同元素之間的計(jì)算相互獨(dú)立,這是可以并行的,那么就可以寫出對應(yīng)的完全流水線化的代碼。至于如何寫,一般則是通過循環(huán)展開,比如張開兩次,每次循環(huán)做兩個(gè)元素的相加,這兩個(gè)相加操作在代碼中的特點(diǎn)就是,即使第一次相加操作不執(zhí)行,也不會影響第二次相加操作代碼的執(zhí)行。也就是代碼之間是互不影響的,而不是非得執(zhí)行前面的代碼,才能執(zhí)行后面的,這樣的代碼是不能利用流水線功能的。
2. 程序的代碼級優(yōu)化
代碼級別優(yōu)化主要針對的時(shí)候代碼本身一些不合理進(jìn)行優(yōu)化,比如反復(fù)重復(fù)的計(jì)算,if判斷語句,循環(huán)語句,以及不斷的調(diào)用函數(shù),不斷的訪問存儲器等等。本來一個(gè)變量可以放入寄存器的,你的代碼非要把他放到存儲器中。雖然減少過程調(diào)用會破壞面向?qū)ο缶幊?,因?yàn)槠渲鲝堃粋€(gè)函數(shù)只做一件事,必然充斥著大量的過程調(diào)用,以保證其可擴(kuò)展性和可讀性,所以至于要不要減少過程調(diào)用這個(gè)依賴與你的應(yīng)用場景,需要自己做個(gè)權(quán)衡。
總之代碼級別的優(yōu)化,主要是從代碼級就能看到的效果,而無需對底層處理器有所認(rèn)識。
3. 程序算法級優(yōu)化
程序算法級優(yōu)化就更容易懂了。實(shí)現(xiàn)同一個(gè)功能,不同的算法性能是不一樣的,適用的情況也是不同的,可謂是各有優(yōu)劣,就比如說排序算法這么多,他們都有自己的優(yōu)點(diǎn)和缺點(diǎn),或者有的時(shí)間復(fù)雜度高,有的空間復(fù)雜度高,有的依賴于特定的數(shù)據(jù)結(jié)構(gòu)能表現(xiàn)更好。
所以你需要對數(shù)據(jù)結(jié)構(gòu)和算法有扎實(shí)的理解。對于一個(gè)程序而言,這三個(gè)級別的優(yōu)化都起著非常重要的作用。希望你不要只關(guān)注于算法級的。尤其是做底層應(yīng)用的人。