天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

淺談代碼的執(zhí)行效率(4):匯編優(yōu)化

  終于談到這個話題了,首先聲明我不是匯編優(yōu)化的高手,甚至于我知道的所有關(guān)于匯編優(yōu)化的內(nèi)容,僅僅來自于學校的課程、書本及當年做過的一些簡單練習。換句話說,我了解的東西只能算是一些原則,甚至也有一些“陳舊”了——不過我想既然是一些原則性的東西,還是能夠用它來做一定程度的判斷。至少我認為,我在博客園里看到的許多關(guān)于“匯編優(yōu)化”也好,“內(nèi)嵌匯編”也罷的說法,經(jīng)常是有些問題的。

  說到匯編優(yōu)化,自然被人想到“高性能”。似乎用.NETJava平臺上的程序性能一定不佳,性能好的程序一定要用C++——不,至少一定要用C來寫。為什么呢?因為一個“常識”:便是“封裝”會損失性能。性能最高的是“機器碼”,因為CPU直接執(zhí)行機器嗎;“匯編”作為機器碼的直接對應產(chǎn)物性能自然是一致的;C語言對于匯編/機器碼幾乎沒有任何封裝,因此性能也很好;而到了C++語言時,性能就要比C慢一些了——不過,這個看法正確嗎?

  其實我最近這幾篇文章談的都是與程序性能,尤其是代碼執(zhí)行效率有關(guān)的話題。在上一篇文章里,我們可以知道即便是在使用匯編編寫代碼,同樣繞不開“CPU緩存”這部分與計算機體系結(jié)構(gòu)相關(guān)的內(nèi)容,而它對程序性能的影響甚至遠遠超過幾句指令本身。事實上這也只是一小個方面而已,我們平時在談性能相關(guān)問題時,總是在做很多假設,例如我們會假設不同指令的執(zhí)行速度是一樣的,各級別存儲的讀取性能也是相同的,但這都只是一個“理想環(huán)境”,和“事實”有很大差距。而進行匯編級別的優(yōu)化,往往也是在利用“事實”進行細枝末節(jié)的調(diào)整。

  例如,假設編譯器只是對代碼做“直接翻譯”的話,您認為以下兩種做法性能哪個比較好?

int sum = 0;for (int i = 0; i < 100; i++){    sum += array[i];}
int sum1 = 0, sum2 = 0;for (int i = 0; i < 100; i += 2){    sum1 += array[i];    sum2 += array[i + 1];}int sum = sum1 + sum2;

  從算法上看,兩者完全相同,但是對于CPU來說,后一種做法比前一種做法性能要高。首先,第二段代碼與前者相比,一個循環(huán)內(nèi)部有兩個完全不相關(guān)的加法運算,這樣CPU便有機會將他們并行地執(zhí)行,于是性能便會更好一些。其次,第二種做法的條件跳轉(zhuǎn)次數(shù)少,一般來說性能就會更好一些。因為條件跳轉(zhuǎn)直到最后一刻才知道要跳向何方,因此CPU流水線就很難對代碼的走向進行預測了。當然,現(xiàn)在CPU設計已經(jīng)引入了分支預測技術(shù),如果預測成功,效率自然較高,但如果預測失敗,那么便會有比較嚴重的損失了。因此,有時候“我們”會盡可能想辦法去減少條件跳轉(zhuǎn)的次數(shù)。

  例如,求一個有符號32位整數(shù)的絕對值,按照我們普通的邏輯,它應該是這樣的:

if (eax < 0) eax = -eax

  這顯然是一個條件跳轉(zhuǎn),但是它的匯編實現(xiàn)也完全可以是:

cdq           // 擴展eax的符號位到edx中,如果eax是正數(shù)則edx為0否則edx為0xffffffffxor eax, edx  // 如果eax為負數(shù),就把所有的位取反,否則不變sub eax, edx  // 如果最開始eax為負數(shù),則把這個數(shù)字取反加一

  這樣,原本的條件跳轉(zhuǎn)消失了,但是我們使用順序的匯編指令得到了正確的結(jié)果。

  這樣看來,內(nèi)嵌匯編對于性能多么關(guān)鍵啊。但是,我們真需要親自動手實現(xiàn)這些嗎?無論是前面的“循環(huán)展開”還是后面的“取絕對值”都是機械的匯編級別的優(yōu)化,這些正是編譯器最(包括運行時里的JIT)擅長的優(yōu)化手段了。如果我們想要代替編譯器去做這些事情,基本上唯一的結(jié)果只是“丑陋的代碼”而難以有性能的提高。

  編譯器其實是提高代碼執(zhí)行效率的重要工具,例如之前在談這個話題的時候,有人談到OCaml的性能比C/C++要高,這便是因為它的編譯器并不需要像C/C++編譯器那樣作出最壞的打算——例如C/C++很多時候無法檢測出兩個變量之間的關(guān)系,因此只能按部就班地執(zhí)行。同樣,我們?yōu)槭裁凑fC語言中strlen()不應該放在循環(huán)內(nèi)部,因為它會造成重復計算?因為C語言編譯器不能假設在循環(huán)過程中strlen的返回值永遠不變,因此它無法自動將其提取到循環(huán)外部,只能一遍遍地執(zhí)行。

因此很多時候,我們在這方面必須為編譯器做點什么。例如,一個關(guān)于處理器的“常識”便是,不管是整數(shù)還是浮點數(shù),除法操作都比乘法要慢上許多,因此我們需要盡可能消除一些除法,例如在進行圖片縮放的時候,我們需要確定縮放的依據(jù)是“寬”還是“高”,因此我們可能就會寫這樣的代碼:

if (desiredWidth / originalWidth < desiredHeight / originalHeight)

  事實上,如果您要在性能上作精細地追求,則這樣是更好的做法:

if (desiredWidth * originalHeight < desiredHeight * originalWidth)

  可惜的是,編譯器可能無法為我們自動作這樣的優(yōu)化:我們的這些變量都是32為“有符號”整數(shù),因此originalWidth可能會是負數(shù)。雖然我們知道圖片的尺寸一定大于零,但是我們卻沒有辦法把這些信息告訴編譯器,因此編譯器只能做最保守的計算了。

  看到這里您可能會說,這些是在談匯編優(yōu)化嗎?好像還是一直再說高級代碼啊。沒錯,因為正向剛才所說那樣,我不其實并不了解多少匯編優(yōu)化的內(nèi)容,我也只能說一些“大道理”。如果您對這方面有些“興趣”的話,云風的《游戲之旅——我的編程感悟》一書似乎值得您一看(其實這篇文章的許多說法,都和這本書有密切關(guān)系)。在這本書里,云風總結(jié)他在多年游戲開發(fā)中總結(jié)到的經(jīng)驗,其中有相當部分便是匯編優(yōu)化方面的內(nèi)容。其中也討論了許多其他方面的問題,如文章開始我提到的C++和C語言的性能高低,他認為C++的性能其實與C語言相比有過之而無不及,如果您在C語言里實現(xiàn)C++的特性(如多態(tài))則幾乎無法作的如C++一樣好,而反過來,如果在C++中做C語言寫過程式的代碼,其性能往往會比C語言來的好。為什么?語言特性與編譯器的威力唄。

  如今的處理器,它的的優(yōu)化手段已經(jīng)非常高級,遠不是在加快時鐘頻率上那么簡單。這給了程序員手動進行匯編優(yōu)化的動力,因為此時可能只要交換兩條指令的順序便可以有很明顯的性能提高,而編譯器的力量已經(jīng)不足以作更細致的優(yōu)化了。同時,CPU設計上的進步也在敦促程序員要不斷更新自己的知識,因為可能在舊CPU上常用的優(yōu)化方式,到了新的CPU上就不是那么明顯了。例如《游戲之旅》就用了“不小”的篇幅“簡單”描述了從Pentium到Pentium IV上漸進的優(yōu)化方式。

  當然,我并不贊同以性能為尊的程序編寫方式,事實上匯編優(yōu)化遠比編寫高級代碼更可能遇到麻煩。云風在書上也強調(diào),不要過于信任自己的匯編書寫能力,即便像他這樣有豐富經(jīng)驗的高手也遇到過不少令人大跌眼鏡的事情。

it知識庫淺談代碼的執(zhí)行效率(4):匯編優(yōu)化,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 国产 亚洲 中文字幕 在线 | 在线观看免费精品国产 | av在线观看网站免费 | 日本精品在线观看视频 | 岳打开双腿开始配合日韩视频 | 边摸边吃奶玩乳尖视频 | 一个人的视频在线观看免费观看 | 亚洲天堂一区二区三区 | 久久一级视频 | 年轻的朋友4在线看中文字幕 | 狠狠色综合久久丁香婷婷 | 九九久久国产精品免费热6 九九久久国产精品大片 | 亚洲日韩国产成网站在线 | 在线视频 日韩视频二区 | 久久久国产精品免费A片蜜芽广 | qvod在线电影 | 嫩草影院地址一二三 | 亚洲精品久久久久一区二区三 | 亚洲精品久久久无码一区二区 | 色婷婷综合激情中文在线 | 日韩视频中文字幕精品偷拍 | 漂亮的保姆5电影免费观看完整版中文 | 5G年龄确认我已满18免费 | 98国产精品人妻无码免费 | PORN白嫩内射合集 | X8X8拨牐拨牐X8免费视频8午夜 | 精品一区二区三区色花堂 | 男人被绑着强行摸j | 做i爱视频30分钟免费 | 国产伦精品一区二区三区免费 | 亚洲精品无码不卡 | 无码一区二区在线欧洲 | 国产精品爽爽久久久久久蜜桃网站 | 欧美多毛的大隂道 | a级成人免费毛片完整版 | 久久精品久久久久 | 亚洲精品国产字幕久久vr | 九九精彩视频在线观看视频 | 国产一区内射最近更新 | 免费人成网站在线观看10分钟 | av无码在线日本天堂 |