计算机术语局部性,【计算机基础】程序的局部性简介
什么是局部性?
局部性分類
局部性有什么作用?
局部性舉例數據引用的局部性
取指令的局部性
結論
完整代碼
什么是局部性?
程序傾向于使用它們最近使用的地址接近或相等的數據和指令。
局部性分類
局部性主要分為時間局部性和空間局部性。
時間局部性:最近使用過的數據和指令在不久的將來可能再次被使用。具體如下圖所示。
時間局部性
空間局部性:某個地址或者某個地址附近的數據和指令可能在不久的將來再次被引用。具體如下圖所示。
空間局部性
局部性有什么作用?
在現代計算機的軟硬件中,處處體現著局部性原理。在硬件上,計算機通過引入稱為高速緩存來保存最近被使用的指令和數據。在軟件上,操作系統用主存來緩存磁盤文件系統中最近被使用的磁盤塊。在應用程序的設計中,Web瀏覽器將最近被引用的文檔放在本地磁盤上,利用的就是時間局部性。作為程序員應該理解局部性原理,一般來說,有良好局部性的程序比局部性差的程序運行得更快。
局部性舉例
數據引用的局部性
看下下面兩個函數。都是計算數組a的和。唯一的區別在于行列的訪問先后順序不同。那么這兩個程序運行起來會有什么差別呢?我們測試下。/**
*?@Description:?行優先方式求二維數組a的和
*?@Param:???????整型數組a
*?@Return:??????數組a的和sum
*?@Author:??????嵌入式與Linux那些事
*/
int?SumArrRow(int?aarr[ROW][COL]){
//1393.166487us
int?i,j,sum?=?0;
for(i?=?0;i?
for(j?=?0;j?
sum?+=a[i][j];
printf("%d\r\n",sum);
return?sum;
}/**
*?@Description:?列優先方式求二維數組a的和
*?@Param:???????整型數組a
*?@Return:??????數組a的和sum
*?@Author:??????嵌入式與Linux那些事
*/
int?SumArrCol(int?a[ROW][COL]){
//2083.776579us
int?i,j,sum?=?0;
for(j?=?0;j?
for(i?=?0;i?
sum?+=a[i][j];
printf("%d\r\n",sum);
return?sum;
}
運算的數組為2 * 3大小。測試結果如下。15
SumArrRow?run_time:1039.612803us15
SumArrCol?run_time:2011.529889us
SumArrCol函數的運行時間是SumArrRow運行時間的將近2倍。原因是什么呢?
首先我們要知道數組在內存中是以行優先的方式存儲的。SumArrRow函數在for循環中訪問a的順序如下。地址???????0?????4??????8??????12????16????20
內容???????a00???a01????a02????a10???a11???a12
訪問順序????1?????2??????3?????4??????5??????6
而SumArrRow函數中,雙重嵌套循環按照行優先順序讀數組的元素。也就是,內層循環讀第一行的元素,然后讀第二行,依此類推。元素被訪問的步長為1。和數組在內存中的存儲方式是一樣的,因此具有很好的空間局部性。
SumArrCol函數和SumArrRow函數,唯一的區別是我們交換了i和j的循環。這樣交換循環對它的局部性有何影響?因為它按照列順序來掃描數組,而不是按照行順序。因為C數組在內存中是按照行順序來存放的,元素被訪問的步長為COL。所以其空間局部性較差。
SumArrCol函數在內存中的存放方式如下所示。地址???????0?????4??????8??????12????16????20
內容???????a00???a01????a02????a10???a11???a12
訪問順序????1?????3??????5??????2?????4??????6
下面再看一個時間局部性的例子。/**
*?@Description:?求一維數組a的和
*?@Param:???????整型數組a
*?@Return:??????數組a的和sum
*?@Author:??????嵌入式與Linux那些事
*/
int?SumArr(int?a[MAX]){
int?i,sum?=?0;
for(i?=?0;i?
sum?+=a[MAX];
printf("%d\r\n",sum);
return?sum;
}
SumArr單函數,它對一個向量的元素求和。這個程序有良好的局部性嗎?要回答這個問題,我們來看看每個變量的引用模式。地址???????0?????4??????8??????12????16????20
內容???????a0????a1?????a2?????a3????a4????a5
訪問順序????1?????2??????3??????4?????5??????6
在這個例子中,變量sum在每次循環迭代中被引用一次,因此,對于sum來說,有好的時間局部性。另一方面,因為sum是標量,對于sum來說,沒有空間局部性。
數組a的元素是被順序讀取的,一個接一個,按照它們存儲在內存中的順序(為了方便,我們假設數組是從地址0開始的)。因此,對于數組a,函數有很好的空間局部性,但是時間局部性很差,因為每個數組元素只被訪問一次。對于循壞體中的每個變量,這個函數要么有好的空間局部性,要么有好的時間局部性,所以我們可以斷定 SumArr函數有良好的局部性。
取指令的局部性
因為程序的指令是放在內存中的,程序運行時,CPU必須取出這些指令。SumArr中for循環體中的指令是按照連續的內存順序執行的。因此具有很好的空間局部性。而且,循環體又被執行很多次,所以也有很好的時間局部性。取指令的局部性和數據引用的局部性的區別在于,在程序運行時,指令是不可修改的。程序只能對指令讀。
結論
上面我們介紹了局部性的概念,并給出了程序示例。現將以上內容總結如下。重復引用相同變量的程序有良好的時間局部性。
對于具有步長為k的引用模式的程序,步長越小,空間局部性越好。在內存中以大步長跳來跳去的程序空間局部性會很差。
對于取指令來說,循環有好的時間和空間局部性。循環體越小,循環迭代次數越多,局部性越好。
完整代碼/*
*?@Description:?【計算機基礎】程序的局部性簡介
*?@Version:?V1.0
*?@Autor:?嵌入式與Linux那些事
*?@Date:?2020-12-21?21:40:12
*?@LastEditors:?嵌入式與Linux那些事
*?@LastEditTime:?2020-12-23?23:11:58
*/
#include?
#include?
#include?
#define?ROW??2
#define?COL??3
/**
*?@Description:?行優先方式求數組a的和
*?@Param:???????整型數組a
*?@Return:??????數組a的和sum
*?@Author:??????嵌入式與Linux那些事
*/
int?SumArrRow(int?aarr[ROW][COL]){
//1393.166487us
int?i,j,sum?=?0;
for(i?=?0;i?
for(j?=?0;j?
sum?+=a[i][j];
printf("%d\r\n",sum);
return?sum;
}
/**
*?@Description:?列優先方式求數組a的和
*?@Param:???????整型數組a
*?@Return:??????數組a的和sum
*?@Author:??????嵌入式與Linux那些事
*/
int?SumArrCol(int?a[ROW][COL]){
//2083.776579us
int?i,j,sum?=?0;
for(j?=?0;j?
for(i?=?0;i?
sum?+=a[i][j];
printf("%d\r\n",sum);
return?sum;
}
/**
*?@Description:?求一維數組a的和
*?@Param:???????整型數組a
*?@Return:??????數組a的和sum
*?@Author:??????嵌入式與Linux那些事
*/
int?SumArr(int?arr[MAX]){
int?i,sum?=?0;
for(i?=?0;i?
sum?+=a[MAX];
printf("%d\r\n",sum);
return?sum;
}
int?main(){
int?a[ROW][COL]?=?{0,1,2,3,4,5};
double?run_time;
LARGE_INTEGER?time_start;?//開始時間
LARGE_INTEGER?time_over;?//結束時間
double?dqFreq;??//計時器頻率
LARGE_INTEGER?f;?//計時器頻率
QueryPerformanceFrequency(&f);
dqFreq=(double)f.QuadPart;
QueryPerformanceCounter(&time_start);?//計時開始
SumArrRow(a);
QueryPerformanceCounter(&time_over);?//計時結束
run_time=1000000*(time_over.QuadPart-time_start.QuadPart)/dqFreq;//乘以1000000把單位由秒化為微秒,精度為1000?000/(cpu主頻)微秒
printf("\nSumArrRow run_time:%fus\n",run_time);
return?0;
}
總結
以上是生活随笔為你收集整理的计算机术语局部性,【计算机基础】程序的局部性简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Guava入门~Splitter
- 下一篇: html盒子嵌套居中,css在盒子中垂直