intsumvec(int v[N]){int i, sum =0;for(i =0; i < N; i++)
sum += v[i];return sum;}// 行优先,步长为 1 的引用模式,具有良好的空间局部性intsumarraycols(int a[M][N]){int i, j, sum =0;for(i =0; i < M; i++)for(j =0; j < N; j++)
sum += a[i][j];return sum;}// 列优先,步长为 N 的引用模式,不具有良好的空间局部性intsumarraycols(int a[M][N]){int i, j, sum =0;for(j =0; j < N; j++)for(i =0; i < M; i++)
sum += a[i][j];return sum;}
时间局部性
对局部变量的反复引用是好的
空间局部性
重新排列循环以提高空间局部性
例一:两个
n
n
n 阶方阵相乘
C
n
×
n
=
A
n
×
n
B
n
×
n
C_{n\times n} = A_{n\times n}B_{n\times n}
Cn×n=An×nBn×n
// ijkfor(i =0; i < n; i++){for(j =0; j < n; j++){
sum =0.0;for(k =0; k < n; k++)
sum += A[i][k]* B[k][j];
C[i][j]+= sum;}}// ikj,步长为 1 的访问模式for(i =0; i < n; i++){for(k =0; k < n; k++){
r = A[i][k];// 局部变量for(j =0; j < n; j++)
C[i][j]+= r * B[k][j];}}// kij,步长为 1 的访问模式for(k =0; k < n; k++){for(i =0; i < n; i++){
r = A[i][k];// 局部变量for(j =0; j < n; j++)
C[i][j]+= r * B[k][j];}}
例二:遍历三维矩阵
当最右边的索引变化最快时,其引用模式步长为 1
intsumarray3d(int a[N][N][N]){int i, j, k, sum =0;for(i =0; i < N; i++)for(j =0; j < N; j++)for(k =0; k < N; k++)
sum += a[i][j][k];return sum;}
例三:遍历内含数组的结构的数组
结构体内各成员的排列方式
#define N 1000#define M 3typedefstruct{int vel[M];int acc[M];} point;
point p[N];// 步长为 1 的访问模式voidclear1(point* p){int i, j;for(i =0; i < N; i++){for(j =0; j < M; j++)
p[i].vel[j]=0;for(j =0; j < M; j++)
p[i].acc[j]=0;}}voidclear2(point* p){int i, j;for(i =0; i < N; i++){for(j =0; j < M; j++){
p[i].vel[j]=0;
p[i].acc[j]=0;}}}