局部性原理淺析——良好代碼的基本素質

本文轉自博客園,原文地址:http://www.cnblogs.com/yanlingyin/archive/2012/02/11/2347116.html



開篇

 一個優秀的程序、優美的代碼,一般都具有良好的局部性。簡潔、高效是每個程序員的追求。瞭解程序的局部性,能編寫出更高效的代碼。

因爲有良好局部性的程序能更好的利用緩存。不過這方面的只是將在以後的文章中介紹。

這篇文章就簡單的介紹以下程序的局部性原理。

什麼是局部性

局部性通常有兩種形式:

時間局部性(temporal locality)

時間局部性指的是:被引用過一次的存儲器位置在未來會被多次引用(通常在循環中)。

空間局部性(spatial locality)

如果一個存儲器的位置被引用,那麼將來他附近的位置也會被引用。

(這樣說過於理論了些,在下面的論述中會有例子說明)

數據引用局部性




例子是最好說明問題的途徑~

看圖a)中的 for 循環,可以判斷:循環中的 sum 有良好的時間局部性。因爲在for循環結束之前,每次執行循環體都有對 sum 的訪問。

而 sum 沒有空間局部性。因爲sum 是標量(也就是說通過 sum 這個地址(可認爲是基址,只能得到一個值)

對於循環體中的 v 則有良好的空間局部性。可以看到 圖 b) 中,向量 v 是按順序存儲的(在實際中多數情況也按順序存儲)。

每次訪問 v[i]總是在 v[i-1] 的下一個位置。而 v 沒有時間局部性。因爲每個元素只被訪問一次。

步長

向上面例子中按順序、連續的對 v 的引用,我們稱爲步長爲1的引用模式。同理,在一個連續的向量中,每隔k個元素對向量進行訪問,稱爲步長爲k的引用。一般來說,隨着步長的增加,空間局部性會下降。

對於多維數組而言,步長對空間局部性的影響顯得尤爲重要。


可以看出,相對於上面的例子,該例的for 循環中交換了 索引 i j 的位置。

也就是說在對a[][]進行遍歷的時候,以列序爲主序。即先訪問第一列,在訪問第二列。。。

而b)中,對a[][]的存儲仍是行序爲主序。這意味着沒訪問一個元素,就要跳過k個存儲器才能訪問下一個。於是得到一個簡單的結論:該例中對a[][]的訪問是以步長爲k 的模式(k 爲每行的元素個數)沒有良好的時間局部性。

通過上面的例子我們知道:在對向量的訪問中,如果訪問數序和存儲順序一致,並且是連續訪問,那麼這種訪問具有良好的空間局部性。

取指令的局部性

 指令存在於存儲器中,cpu 要讀指令就必須取出指令。所以也能評價對於取指令的局部性。

在for 循環中,循環體內的指令多次被執行,所以有良好的時間局部性。

循環體中的指令是桉順序執行的,有良好的空間局部性(指令在存儲器中是順序存放的)。

局部性小結

 評價局部性的簡單原則:

1、重複引用同一個變量有良好的時間局部性

2、對於步長爲k 的引用的程序,步長越小,空間局部性越小。步長爲1 的引用具有良好的空間局部性。k越大,空間局部性越差。

3、對於取指令來說、循環有較好的時間和空間局部性。

後記

這篇文章只是簡單的介紹了什麼是局部性,局部性原理的應有,即爲什麼有良好局部性的程序有更好的性能,局部性和告訴緩存的關係是如何的,將在後面的文章中介紹。這篇文章且當作後文的鋪墊吧。

本人認知有限,如上述文章有不足之處歡迎指正交流。

 

參看資料:computer systems

如有轉載請註明出處:http://www.cnblogs.com/yanlingyin/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章