CSAPP-存储体系实验
实验目的
1. 观察cache对程序数据访问的加速作用;
2. 掌握编程中利用cache的基本方法;
实验内容
观察代码访存模式对性能的影响、编写代码测试cache层次结构和容量等
实验环境
1. 硬件:PC或任何一款具有cache的功能的计算机
2. 软件:Windows/Linux操作系统、C语言编译器
实验步骤
1. 二维数组访问顺序
设计如图1、2所示的代码,对二维数组按行访问和列访问分别进行访问,并计算各自所用时间。
图 1 代码部分1
图 2 代码部分2
如图3所示,进行多组实验,分别按规模为10000、15000、20000、25000、30000、350000,得到运行结果。
图 3 实验运行结果
将结果转化成图表,如图4所示,可以明显看出列访问比行访问要耗时得多,因此可以证实数组的存储是按行存储,当按行访问时空间局部性高,因此访问时间少。
图 4 结果转化成的图表
2. 矩阵乘法
1. 用C语言实现矩阵(方阵)乘积一般算法(程序A),填写下表:
矩阵大小 | 100 | 500 | 1000 | 1500 | 2000 | 2500 | 3000 |
---|---|---|---|---|---|---|---|
一般算法执行时间 | 0.010374 | 0.73934 | 7.55010 | 28.111937 | 53.701337 | 143.709244 | 257.994514 |
分析:
为了减少实验误差,我做了两次实验,实验结果如图5、6所示,并将结果取平均值,可以明显看出随着输入规模的增大,程序运行时间的增长非常快。
图5 程序A实验结果1
图6 程序A实验结果2
程序的运行时间在time1和time2之间,由图7可以看出,在内层循环中数组a[]的访问顺序是按照存储顺序的,空间局部性很高;而数组b[]的访问顺序则是跳转的,每执行一次循环的跳跃补偿为size*4个字节,当规模比较大时空间局部性很低。因此随着规模的增大,程序的cache命中率会降低许多。
图 7 程序A的关键部分代码
2. 程序B是基于Cache的矩阵(方阵)乘积优化算法,填写下表:
矩阵大小 | 100 | 500 | 1000 | 1500 | 2000 | 2500 | 3000 |
---|---|---|---|---|---|---|---|
优化算法执行时间 | 0.0084575 | 0.6019215 | 4.788213 | 16.4042305 | 38.291184 | 75.3040035 | 129.439939 |
分析:
对于程序B我也做了两次实验,实验结果如图8、9所示,并将结果取平均值,可以明显看出随着输入规模的增大,程序运行时间的增长也非常看,但运行时间明显比程序A要少。
图8 程序B运行结果
图 9 程序B运行结果2
为了更好地体现两个程序运行时间的差距,我做了如图10所示的图表,图中可以明显的看出当规模比较大时,两个程序运行时间的差距是比较大的。当规模很小时,两者的差距并不明显,而且还有可能误差的影响。
图 10 运行时间的比较
为了解释两者运行时间的不同,就对程序B的代码进行分析,如图11所示。从图中可以看出,程序A跟B的不同之处在于,程序B是先将数组存在a[]和c[]中,然后通过拷贝的方式将c[]的转置存到b[]中,这样就使得在下面的运算中数组a[]和b[]的访问顺序都是与其存储顺序是一致的,因此空间局部性得到提高。
图 11 程序B的关键部分代码
3. 优化后的加速比(speedup)
矩阵大小 | 100 | 500 | 1000 | 1500 | 2000 | 2500 | 3000 |
---|---|---|---|---|---|---|---|
加速比 | 1.226603 | 1.228299 | 1.576809 | 1.7137 | 1.402446 | 1.908387 | 1.99316 |
加速比定义:加速比=优化前系统耗时/优化后系统耗时;
所谓加速比,就是优化前的耗时与优化后耗时的比值。加速比越高,表明优化效果越明显。
分析:
我将加速比也做了图表,如图12所示,从图中可以看出,除了规模为2000的这个点之外(可能是实验次数不足导致),总体上随着规模的增大,加速比也在增大。而当规模小于500时两者的加速比接近1,也即两者运行时间相差无几,优化效果不明显。这点可以由上面的解释中推出:当规模很小时,跳跃的步长不大,因此cache的命中率比较高,优化效果不明显;而且程序B多了个数组拷贝的过程,这也可以解释在某次实验中,程序A的运行时间反而比B的运行时间还要小。
图 12 加速比的比较