cpu进行运算之前会有一个步骤,就是把内存的数据把拿到高速缓存区(L1,L2,...)。
一般说来,当访问内存的某个位置时,会把这个位置附近的数据也搬过去,跟硬盘到内存的pagecache相似。
如果频繁命中这个高速缓存区,可以大大提高程序的运行速度。
所以如果用一个二元对表示一次运算(运行时刻,数据位置),
将此二元序列关于时间排序,那么我们就应该让相邻二元对的数据位置尽可能接近。
见两个程序:
const int N = 1 << 12; typedef double Type; Type a[N][N], b[N][N], c[N][N]; int main() { for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { a[j][i] = b[j][i] + c[j][i]; } } return 0; }
运行时间为:
real 0m1.218s
user 0m1.139s
sys 0m0.079s
const int N = 1 << 12; typedef double Type; Type a[N][N], b[N][N], c[N][N]; int main() { for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { a[i][j] = b[i][j] + c[i][j];//注意i,j的位置 } } return 0; }
运行时间为:
real 0m0.184s
user 0m0.107s
sys 0m0.078s
可以看到,当数据量一大这个内存到高速缓存的搬运时间也是挺吓人的。