日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

浅谈代码的执行效率(3):缓存与局部性

發(fā)布時(shí)間:2025/3/21 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈代码的执行效率(3):缓存与局部性 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在前兩篇文章里,我們討論了程序性能的兩個(gè)方面,一是算法(廣義的算法,即解決問(wèn)題的方法),二是編譯器。通過(guò)這兩個(gè)方面,我想表達(dá)的意思是,一段程序的執(zhí)行效率,是很難從表面現(xiàn)象得出結(jié)論的,至少?gòu)囊恍┖?jiǎn)單的層面,如代碼的長(zhǎng)度是幾乎難以說(shuō)明任何問(wèn)題——因此一定要進(jìn)行Profiling才能做到有效的優(yōu)化。而現(xiàn)在,我們假設(shè)兩段程序算法基本相同,編譯器也只是進(jìn)行簡(jiǎn)單的“翻譯”,那么……我們能從“表面”看出性能高下嗎?

那么就從一個(gè)最簡(jiǎn)單的例子看起吧。假設(shè)DoSomethingA和DoSomethingB里做的事情是固定的,那么您認(rèn)為下面兩種寫(xiě)法的哪個(gè)性能更好?

for (int i = 0; i < 100; i++) {DoSomethingA();DoSomethingB(); } for (int i = 0; i < 100; i++)DoSomethingA();for (int i = 0; i < 100; i++)DoSomethingB();

這兩段邏輯的算法基本上完全相同,如果編譯器只是進(jìn)行直接“翻譯”而不進(jìn)行優(yōu)化,那么第一種做法對(duì)于i的累加和條件跳轉(zhuǎn)比較少,因此您可能會(huì)得出結(jié)論:“很明顯”第一段代碼的執(zhí)行效率比較高。只可惜事實(shí)并非那么簡(jiǎn)單,因?yàn)橛绊懗绦蛐阅艿牧硪粋€(gè)關(guān)鍵因素是:緩存。

“緩存”無(wú)處不在。在CPU中,性能最快的存儲(chǔ)設(shè)備當(dāng)屬“寄存器”,不過(guò)眾所周知寄存器的數(shù)量是極其有限的。因此,CPU都會(huì)有L1 Cache和L2 Cache的多級(jí)緩存機(jī)制。其中,L2 Cache的性能比L1 Cache和寄存器都要慢,但還是比內(nèi)存要快許多。當(dāng)某個(gè)Core需要從內(nèi)存中獲取數(shù)據(jù)的時(shí)候,便會(huì)從L1 Cache獲取數(shù)據(jù),如果L1 Cache沒(méi)有那么就會(huì)從多個(gè)核共用的L2 Cache拿,再?zèng)]有便會(huì)從內(nèi)存拿——由于操作系統(tǒng)的虛擬內(nèi)存機(jī)制,可能還要從磁盤(pán)的交換頁(yè)中獲取數(shù)據(jù),此時(shí)性能自然相當(dāng)差了。

雖然寄存器只使用一個(gè)字長(zhǎng)(如4字節(jié))的數(shù)據(jù),但是L1 Cache從L2 Cache拿數(shù)據(jù)時(shí)總是“一塊一塊”拿的——這么一塊往往就是連續(xù)的64個(gè)字節(jié)。換句話(huà)說(shuō),在CPU讀取的一個(gè)地址的數(shù)據(jù)之后,讀取其他一些地址上的數(shù)據(jù)便會(huì)比另一些特別快,因?yàn)樗鼈兌家呀?jīng)在L1 Cache中了。如果一個(gè)程序能夠利用起CPU的這個(gè)特性,那它的性能往往便可以更好一些(自然還有很多其他影響性能的因素)。

局部性(Locality),便是用來(lái)描述程序是否能利用好緩存的名詞。我們說(shuō)一個(gè)程序的局部性比較好,那么就表示它能夠較好地利用起CPU的緩存機(jī)制。局部性分“空間局部性”和“時(shí)間局部性”兩方面,前者是指“加載一個(gè)地址的數(shù)據(jù)之后,繼續(xù)加載它附近的數(shù)據(jù)”,后者表示“在加載一個(gè)地址的數(shù)據(jù)之后,短時(shí)間內(nèi)重新加載這塊數(shù)據(jù)”。無(wú)論是哪一方面,目的都是希望從較快的緩存中加載“熱”的數(shù)據(jù)。為什么冷啟動(dòng)總是很慢?為什么有人說(shuō)系統(tǒng)從開(kāi)機(jī)后會(huì)越跑越快?其實(shí)道理都差不多。

那么現(xiàn)在,您還能判斷上面兩種做法的效率孰高孰低?雖然第一種做法減少了i的累加次數(shù)和條件跳轉(zhuǎn)的次數(shù),但是它在一次循環(huán)中做了兩件事情,可能在執(zhí)行DoSomethingB方法的時(shí)候,DoSomethingA方法中剛剛進(jìn)入緩存的數(shù)據(jù)便冷卻了,于是在下次執(zhí)行DoSomethingA時(shí)又要重新從較慢的存儲(chǔ)設(shè)備中加載數(shù)據(jù)。而在第二種做法中,我們“密集”地執(zhí)行完100次DoSomethingA或DoSomethingB的調(diào)用,而此間大量的數(shù)據(jù)訪(fǎng)問(wèn)都是集中在L1 Cache上,性能優(yōu)勢(shì)不言而喻。

我以前的文章《計(jì)算機(jī)體系結(jié)構(gòu)與程序性能》在第一部分里也討論了局部性對(duì)程序性能的影響,講的更為具體一些,您也可以參考其中的內(nèi)容。

由于程序指令不是執(zhí)行效率的唯一因素,因此從代碼長(zhǎng)短上判斷程序性能也是非常不靠譜的事情。當(dāng)然,從任何獨(dú)立的角度來(lái)判斷性能可能都不合適。例如在那篇文章里提到,出于程序性能的考慮應(yīng)該使用全局變量——當(dāng)然作者也認(rèn)為這不是好的設(shè)計(jì),事實(shí)上在我們剛才的例子中,在一個(gè)循環(huán)中做多件事情可能也值得重構(gòu)。如果您使用全局變量,它的確省下了push,pop等指令的開(kāi)銷(xiāo),但是這么一個(gè)全局變量——例如是一個(gè)靜態(tài)變量,它存儲(chǔ)在堆的某一個(gè)地方,訪(fǎng)問(wèn)它并非是一個(gè)局部性方面的優(yōu)秀實(shí)踐。與之相反,由于L1 Cache的作用,在調(diào)用棧上訪(fǎng)問(wèn)“參數(shù)”或“局部變量”并不會(huì)比訪(fǎng)問(wèn)寄存器慢多少,此時(shí)push,pop幾個(gè)指令的開(kāi)銷(xiāo)可能就不算什么了。更何況,如果編譯器/運(yùn)行時(shí)內(nèi)聯(lián)了這個(gè)方法,這樣連push,pop等指令也不會(huì)出現(xiàn)了。

記得前一段時(shí)間在有某些朋友在我的博客上發(fā)布一些較為“激進(jìn)”的說(shuō)法,例如“學(xué)底層只是對(duì)寫(xiě).NET程序沒(méi)有幫助,因?yàn)榫退隳阒懒诉@些,C#也沒(méi)有辦法內(nèi)嵌匯編”。我不同意這個(gè)說(shuō)法,因?yàn)榧幢闶?NET程序,它也是在符合計(jì)算機(jī)體系結(jié)構(gòu)的規(guī)律下運(yùn)行的,我們完全可以在一定程度上了解一段代碼在執(zhí)行時(shí)的表現(xiàn)。

就拿目前談到的“局部性”來(lái)說(shuō),我們便可以把握很多東西。比如,我們知道每個(gè)線(xiàn)程的調(diào)用棧在默認(rèn)情況下是1兆大小,因此兩個(gè)線(xiàn)程調(diào)用棧上的數(shù)據(jù)幾乎不可能出現(xiàn)在同一個(gè)Cache條目中。再比如,由于“時(shí)間局部性”,最近使用的數(shù)據(jù)最有可能出現(xiàn)在緩存中,因此在.NET 4.0的并行庫(kù)在調(diào)度“私有隊(duì)列”的任務(wù)時(shí)會(huì)傾向于執(zhí)行最新創(chuàng)建的任務(wù)。再比如,您是使用兩個(gè)int數(shù)組來(lái)表示一系列坐標(biāo)的x值和y值,還是構(gòu)造一個(gè)struct Point數(shù)組來(lái)保存它們呢?雖然使用兩個(gè)int數(shù)組更節(jié)省內(nèi)存,但是從局部性考慮問(wèn)題的話(huà),您會(huì)發(fā)現(xiàn)同一個(gè)坐標(biāo)的x值和y值存放在一起可能更為合適。

我的這幾篇文章,其實(shí)也都在強(qiáng)調(diào)從代碼表面判斷程序性能的“不確定性”。同樣道理,即便是把它們的匯編代碼(片斷)放在您面前,您也可能很難“看出”性能區(qū)別。這也從側(cè)面說(shuō)明了Profiling的重要性:閱讀代碼是靜態(tài)的,而程序執(zhí)行和Profiling都是動(dòng)態(tài)的。之前有朋友對(duì)我說(shuō)“你最近迷上Profiler啦?”其實(shí)我這里的Profiling泛指“一種探索程序性能的方式”,并不是指某個(gè)特定的手段,更不是某個(gè)具體的工具——不過(guò)無(wú)論是使用VS的Profiler也好,還是自己搞一個(gè)CodeTimer,都比“讀代碼”來(lái)的可靠。

from:?http://blog.zhaojie.me/2010/01/talk-about-code-performance-3-locality.html

總結(jié)

以上是生活随笔為你收集整理的浅谈代码的执行效率(3):缓存与局部性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 成人图片小说 | 精品日本一区二区 | 久久久久久久久久久久久久久 | 天天插天天干 | 久久综合伊人77777蜜臀 | 97超视频在线观看 | 黄色成人在线免费观看 | 91国视频| 日本在线第一页 | 久久日本精品字幕区二区 | 黄色性视频 | 黄色肉肉视频 | 丝袜脚交国产在线观看 | 天天撸在线视频 | 日本黄色性视频 | 一级黄色裸体片 | 爱福利视频网 | 性激烈视频在线观看 | 国产99久久九九精品无码免费 | 色屁屁在线 | 原来神马电影免费高清完整版动漫 | 国产乱淫av片 | 免费看毛片网站 | 人人干人人插 | 国产视频在线观看一区二区 | 久久久天天 | 激情伊人网 | 欧美大奶在线 | 欧美久久久| 精品一区二区三区成人免费视频 | 久久久久久久久免费看无码 | 天天插天天摸 | 欧美天天射 | 激情五月开心婷婷 | 国产欧美在线精品日韩 | 最新欧美大片 | 波多野久久 | 亚洲清纯国产 | 海量av资源| 亚洲老女人 | 制服丝袜先锋影音 | 特大黑人娇小亚洲女 | 亚洲乱码国产乱码精品 | 好吊妞视频一区二区三区 | 小柔的裸露日记h | 在线麻豆av| 天天躁日日躁狠狠很躁 | 日本一道本在线 | 国内自拍欧美 | 亚洲AV无码国产精品国产剧情 | 嫩草影院在线视频 | 午夜视频网站在线观看 | 老女人做爰全过程免费的视频 | 亚洲欧美一区二区三区久久 | 午夜动态图 | 中文乱码人妻一区二区三区视频 | 日韩av无码一区二区三区 | 一区二区 中文字幕 | 国产成人精品一区二区三区免费 | 丰满的女人性猛交 | 欧美鲁| 国产在线播放一区二区三区 | 精品视频站长推荐 | 欧洲一区二区视频 | 在线不卡国产 | 97精品熟女少妇一区二区三区 | 成人网页在线观看 | 91一区二区在线观看 | 成人午夜电影网站 | 最新最全av网站 | 日韩精品免费一区 | www嫩草| 日日碰碰| 久久久久久久中文字幕 | 美女100%视频免费观看 | 极品探花在线播放 | 色屁屁草草影院ccyycom | 久久99精品久久久久子伦 | 欧洲一区二区 | 日韩精品免费一区二区三区 | 欧美激情一二区 | 一级a性色生活片久久无 | 国产毛片在线视频 | 丰满少妇熟乱xxxxx视频 | 台湾佬美性中文网 | 青青自拍视频 | 麻豆视频免费入口 | 欧美老熟妇又粗又大 | 乌克兰黄色片 | 亚洲大片精品 | 中文无码精品一区二区三区 | 黄色网页免费 | 91好色先生 | 97夜夜操| 日韩高清精品免费观看 | 神马久久春色 | 欧美一区二区影院 | 桃色视频在线 | 性感av在线|