中對程式區域性性有了乙個簡單的介紹。基本上已經知道了如何編寫有良好區域性性的**。但是為什麼有良好區域性性的**就能有良好的執行效率,這個問題將在這篇博文中給出解答。至於儲存器內部的組織實現,將在下篇文章中敘述。
儲存器層次結構
我們知道,計算機裡的儲存器有:硬碟、主存、快取記憶體(其中又有一級快取記憶體、二級快取記憶體等等)、在往上就是暫存器。
儲存器在計算機內部的組織方式如下圖所示:
相信上圖大家並不陌生。wiki對the memory hierarchy 的介紹的時候也有此圖。
我們發現,越往上,儲存器的容量越小、成本越高、速度越快。
為什麼會出現這樣的結構呢?早起的儲存器層次結構只有三層:cpu暫存器、dram主存以及磁碟儲存。
由於cpu和主存之間巨大的速度差異,系統設計者被迫在cpu暫存器和主存之間插入了乙個小的sram快取記憶體儲存器稱為l1快取,大約可以在2--4個時鐘週期內訪問。再後來發現l1快取記憶體和主存之間還是有較大差距,又在l1快取記憶體和主存之間插入了速度更快的l2快取,大約可以在10個時鐘週期內訪問。於是,在這樣的模式下,在不斷的演變中形成了現在的儲存體系。
現在可以知道整個儲存器體系被分為了很多層,那麼他們之間是如何協調工作以提高執行效率的呢?
何為快取
暫時你可以這樣理解:速度快的儲存器快取了速度慢儲存器的資料。準確的描述:對於每個k ,位於k層的更快更小的儲存器裝置作為第k+1層的更大更慢儲存裝置的快取。就是說,k層儲存了k+1層中經常被訪問的資料。在快取之間,資料是以塊為單位傳輸的。當然不同層次的快取,塊的大小會不同。一般來說是越往上,塊越小。
請看下圖示例
k是k+1的快取,他們之間的資料傳輸是以塊大小為單位的。如上圖中,k中快取了k+1中塊編號為 4、9、14、3的資料。
當程式需要這些塊中的資料時,可直接衝快取k中得到。這比從k+1層讀資料要快
快取命中
當程式需要第k+1層中的某個資料時d,會首先在它的快取k層中尋找。如果資料剛好在k層中,就稱為快取命中(cache hit)。
快取不命中
當需要的資料物件d不再快取k中時,稱為快取不命中。當發生快取不命中時,第k層的快取會從k+1層取出包含資料物件d的那個塊,如果k層的快取已經放滿的話,就會覆蓋其中的乙個塊。至於要覆蓋哪乙個塊,這是有快取中的替換策略決定的,比如說可以覆蓋使用頻率最小的塊,或者最先進入快取的塊。。這裡不再討論。在k層從k+1層中取出資料物件d後,程式就能在快取中讀取資料物件d了。
快取命中和區域性性
這裡先簡單的說說為什麼區域性性好的程式能有更好的效能
利用時間區域性性:由於時間區域性性,同乙個資料物件會多次被使用。一旦乙個資料物件從k+1層進入到k層的快取中,就希望它多次被引用。這樣能節省很多訪問造成的時間開支。
利用空間區域性性:假設快取k能存n個資料塊。在對陣列訪問的時候,由於陣列是連續存放的,對第乙個元素訪問的時候,會把第乙個元素後面的一共n個元素(快取k有n個資料塊)拷貝到快取k中,這樣在對第二個元素到第n個元素的訪問時就可以直接從快取裡獲取,從而提高效能。
同理,訪問第n個元素的時候 ,n不在快取中,快取管理器會把從n到2n的元素拷貝到快取中,對它們的訪問就可以直接在快取中進行。
通過空間區域性性,我們希望對後面對快取中其他物件的訪問能補償不命中後拷貝這些塊的時間花費。
小結
這篇文章主要介紹了計算機儲存器內部的組織結構以及他們之間的關係,並簡單說了下快取實現機制,以及快取和區域性性之間的關係。
提高程式效能 何為快取 從儲存器結構說起
開篇 中對程式區域性性有了乙個簡單的介紹。基本上已經知道了如何編寫有良好區域性性的 但是為什麼有良好區域性性的 就能有良好的執行效率,這個問題將在這篇博文中給出解答。至於儲存器內部的組織實現,將在下篇文章中敘述。儲存器層次結構 我們知道,計算機裡的儲存器有 硬碟 主存 快取記憶體 其中又有一級快取記...
提高程式效能 何為快取 從儲存器結構說起
開篇 中對程式區域性性有了乙個簡單的介紹。基本上已經知道了如何編寫有良好區域性性的 但是為什麼有良好區域性性的 就能有良好的執行效率,這個問題將在這篇博文中給出解答。至於儲存器內部的組織實現,將在下篇文章中敘述。儲存器層次結構 我們知道,計算機裡的儲存器有 硬碟 主存 快取記憶體 其中又有一級快取記...
利用多執行緒提高程式效能(for Android)
首先我們建立了乙個http客戶端和http請求。如果請求成功,就把響應中包含的內容解碼成位圖格式並返回,以備後續使用。另外補充一句,為了讓程式可以訪問網路,必須在程式的manifest檔案中宣告使用internet。注意 舊版的bitmapfactory.decodestream有個bug,可能使得...