目录
2. 测量分析出Cache 的层次结构、容量以及L1 Cache行有多少?
写在前面:
上交的实验报告需要包含账户的姓名全拼以及学号,本报告的相应部分已经打码处理,请在自己的环境中完成实验!
一、实验目的:
1. 加强对Cache工作原理的理解;
2. 体验程序中访存模式变化是如何影响cahce效率进而影响程序性能的过程;
3. 学习在X86真实机器上通过调整程序访存模式来探测多级cache结构以及TLB的大小。
二、实验环境:
X86真实机器
三、实验内容与步骤:
1. 分析Cache访存模式对系统性能的影响
(1)给出一个矩阵乘法的普通代码A,设法优化该代码,从而提高性能。
(2)改变矩阵大小,记录相关数据,并分析原因。
2. 编写代码来测量x86机器上(非虚拟机)的Cache 层次结构和容量
(1)设计一个方案,用于测量x86机器上的Cache层次结构,并设计出相应的代码;
(2)运行你的代码获得相应的测试数据;
(3)根据测试数据来详细分析你所用的x86机器有几级Cache,各自容量是多大?
(4)根据测试数据来详细分析L1 Cache行有多少?
3. 尝试测量你的x86机器TLB有多大?(选作)
四、实验过程及内容:
准备工作:
首先在虚拟机桌面上新建一个实验五的文件夹experiment_5用于保存本实验所用的所有文件。下载main_a.c文件后使用指令gcc -o main_a main_a.c 进行编译,发现没有错误。
图:编译main_a.c
图中,第一次编译错误是由于“-o”的命令出错,具体原因是ppt中给出的指令使用的符号并不是标准的“-”,而是“–”,导致机器无法识别。修改后即可正确编译并生成可运行文件。
接下来即可开始实验:
1. 分析Cache访存模式对系统性能的影响:
使用指令./main_a x,以x*x为矩阵的大小运行程序./main_a,并记录运行时间,填入表中(单位为秒)。
接下来阅读源代码,并尝试优化:
阅读代码可以得知,程序的主要功能是实现两个矩阵的相乘运算,将大小为x*x的矩阵a,b相乘的结果保存在矩阵c中。但此代码的空间局部性较差,常常访问距离当前访问地址较远的地址,具体而言,在对c某个位置的计算时,对矩阵b的访问中,程序每次访问的地址将会增加size,此时如果size较大,访问的空间将会距离较大,因此空间局部性差。
优化方法:将原始的整块矩阵相乘拆分为一个个小矩阵块相乘,从而提高了空间局部性,提高运行效率。计算部分的代码如图:
图:核心代码
其中,BLOCK_SIZE即为矩阵块的大小。
接下来,由于我们并不能直接确定块的合适大小,因此我尝试将此参数进行多次调整,找到一个较优的值:
图:参数调整过程
图中第二个参数即为BLOCK_SIZE的值,如图可以发现,512为一个较优的参数值。
接下来固定参数,进行实验,并统计实验结果:
图:实验过程
最终实验结果如表:
如表,代码的优化带来了显著的效果。
2. 测量分析出Cache 的层次结构、容量以及L1 Cache行有多少?
首先需要对mountain文件进行解压:tar-xvf mountain.tar
图:解压成功
接着使用make生成可执行文件,并将其运行:
图:运行结果
将运行结果保存到本地,并使用matlab画图:
图:数据山
图中能明显地观察到读取速度的分层现象。
根据上述的实验结果可以分析出:随着读取内容的增多,读取速度三次下降分别出现在:512KB~1024KB、4MB~8MB、8MB~16MB,说明本电脑共存在三级缓存,且这三段速度下降分别对应了这三段缓存的切换过程。其中L1缓存的容量可能约为768KB、L2缓存为6MB、L3缓存为12MB。
而随着步长的变化,读取速度也会出现对应的突变:这样的突变是由于数据是按块加载到缓存中的,较大的步长可能会导致两次连续的访问必然不可能出现在同一块中,从而降低了读取速度。本实验中,测得步长达到40步左右时会出现突变,L1缓存的行约为512KB/40*8B=1638行
打开任务管理器验证实验结果:
图:三个缓存真实大小
如图所示,三个缓存的真实容量与实验结果相吻合。
3. 尝试测量你的x86机器TLB有多大?(选作)
TLB的定义:TLB(Translation Lookaside Buffer)是位于CPU内部的一种专用缓存,用于加速虚拟地址到物理地址转换的硬件缓存。
当CPU执行程序时,会生成虚拟地址来访问内存,CPU首先会调用TLB,如果TLB中存在该虚拟地址对应的物理地址,则直接使用TLB中的物理地址进行内存访问。反之需要通过页表来进行地址转换。
因此我编写了一个程序:首先创建一个相当大的数组(此处为256MB),此数组的大小会远超TLB的大小。接着使用不同步长进行数组的遍历:首先为1,然后每次乘以2。并统计每种步长对应的访问时间。如果步长*单位长度(此处取的是4KB)小于TLB,则地址可能可以直接在TLB中找到,从而访问较快;反之访问较慢。这样一来,只需要找到访问时间突变对应的步长,即可计算出TLB的大小。
接下来运行程序,结果如图。将总访问时间乘以对应的步长可以得到访问相同空间所需的时间,可以看到,在步长为8~16的实验中,相对时间出现了较大的突变。因此,计算出来的TLB大小为32KB~64KB。
图:运行结果
五、实验总结与体会
实验总结:
本次实验我利用程序的局部性的知识,优化了矩阵乘法的代码,将矩阵乘法的运行效率显著提高,最大加速比约为173%。接下来运行了mountain程序,得到了不同访问大小、不同步长时的读取速度,并将其绘图展示。根据此实验的结果,我测得了CPU具有三级缓存,以及它们对应的大小分别为:768KB、6MB、12MB。我在任务管理器中直接查看了三级缓存对应的大小,验证了上述实验结果的正确性。最后,我学习了TLB的相关知识,编写代码测量了程序以不同步长访问同一数组所需要的时间,以此估算出TLB的大小约为48KB。
实验体会:
本次实验中数据山的画图部分最为困难,需要学习matlab绘图函数,将实验结果可视化。除此之外,TLB的测量部分也较为困难,要完成此任务,需要首先查阅资料,学习TLB的相关知识,再利用其特性,使用不同步长访问数组的方式,完成TLB大小的估算。
尾注
如有疑问欢迎讨论,如有好的建议与意见欢迎提出,如有发现错误则恳请指正!
附录:
实验代码:
1. 矩阵运算代码:
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
float* a, * b, * c, temp;
long int i, j, k, size, m;
struct timeval time1, time2;
if (argc < 2) {
printf("\n\tUsage:%s <Row of square matrix>\n", argv[0]);
exit(-1);
} //if
size = atoi(argv[1]);
int BLOCK_SIZE = atoi(argv[2]);
m = size * size;
a = (float*)malloc(sizeof(float) * m);
b = (float*)malloc(sizeof(float) * m);
c = (float*)malloc(sizeof(float) * m);
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
a[i * size + j] = (float)(rand() % 1000 / 100.0);
b[i * size + j] = (float)(rand() % 1000 / 100.0);
c[i * size + j] = 0;
}
}
gettimeofday(&time1, NULL);
long int ii, jj, kk;
for (ii = 0; ii < size; ii += BLOCK_SIZE)
for (jj = 0; jj < size; jj += BLOCK_SIZE)
for (kk = 0; kk < size; kk += BLOCK_SIZE)
for (i = ii; i < ii + BLOCK_SIZE && i < size; i++)
for (j = jj; j < jj + BLOCK_SIZE && j < size; j++)
for (k = kk; k < kk + BLOCK_SIZE && k < size; k++)
c[i * size + j] += a[i * size + k] * b[k * size + j];
gettimeofday(&time2, NULL);
time2.tv_sec -= time1.tv_sec;
time2.tv_usec -= time1.tv_usec;
if (time2.tv_usec < 0L) {
time2.tv_usec += 1000000L;
time2.tv_sec -= 1;
}
printf("Executiontime=%ld.%06ld seconds\n", time2.tv_sec, time2.tv_usec);
return(0);
}//main
2. mountain绘图代码(matlab):
% 数据准备
sizes = [2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768]
strides = 1:64; % 列对应的stride
% 吞吐量数据
data = [
8519.7 8519.7 9727.3 10223.7 10208.7 8511.4 7288.4 8519.7 11331.9 20367.5 18570.3 16972.9 15675.0 14576.7 13578.3 12779.6 11980.9 11282.0 10682.9 10183.7 9684.5 9285.2 8885.8 8486.4 8087.1 7787.6 7488.0 7288.4 6988.8 6789.2 6589.5 6389.8 6190.1 5990.4 5790.8 5591.1 5491.2 5291.6 5191.7 5091.9 4892.2 4792.3 4692.5 4592.7 4492.8 4393.0 4293.1 4193.3 4093.5 3993.6 3993.6 3893.8 3793.9 3694.1 3694.1 3594.3 3494.4 3494.4 3394.6 3394.6 3294.7 3294.7 3194.9 3194.9;
8345.9 8519.7 9734.5 10223.7 11681.3 11348.5 11681.3 12779.6 11356.9 10208.7 9285.2 11348.5 10483.3 9717.8 13628.2 12779.6 11980.9 11331.9 21465.7 20367.5 9734.5 18570.3 17771.6 8486.4 16274.0 7837.5 7538.0 14576.7 14077.5 6789.2 13179.0 12779.6 12380.2 11980.9 11681.3 11282.0 5491.2 10682.9 10483.3 5091.9 9884.2 9684.5 9484.9 9285.2 9085.5 8885.8 8686.1 8486.4 8286.8 8087.1 7987.2 7787.6 7687.7 7488.0 7388.2 7288.4 7088.7 6988.8 6889.0 6789.2 6689.3 6589.5 6489.6 6389.8;
8431.9 8701.0 8792.4 9294.2 9085.5 9734.5 9734.5 10223.7 10095.0 11681.3 12380.2 11348.5 12579.9 9734.5 10902.6 12779.6 12005.8 11356.9 10757.8 10208.7 9734.5 9285.2 11847.7 11348.5 10882.6 10483.3 15125.8 14576.7 14077.5 13628.2 13179.0 12779.6 12380.2 11980.9 23362.7 11331.9 11032.4 21465.7 10483.3 10183.7 9934.1 9734.5 9484.9 18570.3 18171.0 17771.6 8686.1 16972.9 8336.7 16274.0 7987.2 15675.0 15375.4 7538.0 14776.4 14576.7 7138.6 14077.5 13778.0 13578.3 13378.6 6589.5 12979.3 6389.8;
8519.7 8609.4 8654.4 8701.0 8839.9 9085.5 8985.7 9294.2 9563.7 9085.5 9291.4 9734.5 9676.9 9734.5 9911.4 10223.7 9614.6 10095.0 10757.8 10221.2 12979.3 12380.2 11847.7 13618.3 13079.1 12579.9 12100.7 11681.3 14077.5 10902.6 10543.2 12779.6 12380.2 16007.8 9345.1 7571.2 8825.9 8606.3 8386.6 8167.0 9959.1 9734.5 12679.8 12380.2 9085.5 11847.7 11581.5 11348.5 16673.4 10882.6 10682.9 15724.9 10283.6 10083.9 9884.2 9717.8 14327.1 14077.5 13827.9 13628.2 13378.6 13179.0 12979.3 12779.6;
8453.7 8519.7 8453.2 8609.4 8608.6 8654.4 8654.7 8701.0 8863.9 8839.9 9009.9 8792.4 8985.7 8985.7 9085.5 8890.2 9161.6 9085.5 9059.2 9085.5 9734.5 9291.4 9478.2 9734.5 10060.9 9676.9 9315.9 9734.5 9393.3 9911.4 9593.8 9294.2 9904.2 12018.3 11681.3 10095.0 11044.9 10757.8 11980.9 10221.2 11396.1 11125.1 12679.8 10611.6 10383.4 10155.2 11598.1 9727.3 11115.6 10899.3 10682.9 10483.3 12340.3 12100.7 11881.0 11681.3 14327.1 11262.0 11082.3 13628.2 13403.6 13179.0 12979.3 10223.7;
8442.8 8453.7 8486.4 8519.7 8553.0 8586.3 8575.3 8609.4 8552.2 8608.6 8619.6 8654.4 8677.5 8818.0 8724.1 8701.0 8747.4 8863.9 8829.5 8839.9 8652.8 9009.9 8888.9 9085.5 9023.5 8985.7 8974.6 8985.7 9021.6 9085.5 9176.7 9294.2 9008.3 9161.6 9345.1 9563.7 9306.2 9562.5 9318.5 9085.5 9385.0 9734.5 9509.8 9291.4 9691.2 9478.2 9278.5 9734.5 9534.8 9342.2 9163.9 9676.9 9492.5 10092.2 9909.2 9734.5 10428.8 10247.3 10074.8 9911.4 9748.1 9593.8 10383.4 6815.8;
8426.5 8442.8 8486.4 8475.6 8497.5 8519.6 8536.1 8519.7 8552.8 8553.0 8558.3 8519.2 8530.4 8575.3 8637.7 8609.4 8649.1 8654.0 8608.8 8608.6 8654.2 8619.6 8619.6 8654.4 8722.7 8677.5 8654.0 8654.7 8676.5 8724.1 8794.3 8701.0 8810.4 8747.4 8900.1 8863.9 8840.9 8829.5 8828.0 8839.9 8863.6 8900.1 8950.4 8744.9 8810.2 8888.9 8698.6 9085.5 8899.1 9023.5 9163.9 8985.7 9144.7 8974.6 8811.9 8985.7 9181.3 9021.6 9239.4 9085.5 8935.7 9176.7 9029.1 6196.2;
8442.8 8464.6 8470.1 8475.6 8470.0 8470.0 8459.1 8475.6 8478.3 8497.5 8497.5 8486.4 8458.8 8497.3 8511.3 8519.7 8505.8 8502.8 8503.1 8497.5 8536.4 8497.1 8555.5 8519.2 8510.8 8530.4 8578.3 8575.3 8513.8 8553.0 8527.8 8519.7 8619.9 8553.0 8594.3 8552.2 8625.3 8502.5 8602.9 8608.6 8625.4 8654.2 8572.2 8619.6 8680.2 8619.6 8566.3 8519.2 8613.7 8579.7 8553.0 8677.5 8663.4 8654.0 8651.6 8654.7 8663.5 8676.5 8697.9 8724.1 8580.3 8614.8 8654.9 6103.7;
8434.6 8423.8 8425.1 8394.0 8395.3 8380.6 8392.7 8345.9 8332.5 8321.8 8204.5 8261.4 8085.3 8006.3 7754.7 8158.5 8277.1 8261.5 8175.1 8282.3 8281.1 8261.5 8275.9 8261.4 8308.6 8284.7 8285.1 8271.7 8279.4 8308.6 8277.0 8138.2 8304.5 8321.8 8308.4 8261.2 8321.4 8348.5 8336.4 8335.1 8290.0 8308.7 8337.4 8318.9 8308.2 8366.8 8373.8 8324.1 8345.3 8308.2 8344.4 8388.3 8369.7 8356.5 8134.0 8199.2 8199.4 8204.2 8214.7 8230.3 8250.3 8196.6 8145.8 5242.9;
8401.4 8412.9 8417.0 8412.9 8381.9 8368.5 8378.6 8324.6 8326.6 8328.5 8348.5 8269.4 8159.1 7646.1 7913.1 7190.3 7746.1 7796.4 7815.6 7991.5 8172.5 8247.1 8413.6 8372.4 8459.8 8371.0 8447.5 8440.0 8434.4 8388.5 8485.2 8220.0 8482.4 8344.4 8473.4 8478.3 8496.6 8425.1 8494.7 8361.7 8455.0 8478.3 8483.0 8497.5 8490.5 8492.0 8501.7 8486.4 8511.9 8476.7 8482.3 8494.5 8514.0 8503.1 8497.6 8458.9 8463.9 8473.8 8489.8 8511.3 8495.8 8527.8 8478.3 4972.0;
8426.8 8235.6 8431.2 8418.3 8395.4 8370.5 8376.2 8348.5 8329.6 8285.7 8330.2 8199.4 8188.2 8421.0 8393.7 7226.0 8384.2 8386.6 7041.5 7002.7 7246.0 7662.9 8374.9 8412.9 8408.9 8371.1 8438.3 8449.6 8454.3 8439.4 8442.8 8345.9 8392.7 8389.9 8437.6 8441.4 8371.1 8425.1 8388.6 8348.4 11959.8 12041.6 11993.2 12016.7 12054.1 12009.8 12007.8 11918.1 12070.8 12033.4 12074.8 11877.5 12044.2 12041.6 12047.2 12061.1 12004.4 12073.4 12070.5 12074.8 12086.0 12061.1 12085.4 7050.8;
8423.1 8273.0 8208.6 8158.5 8031.5 7905.0 7783.4 7945.5 8012.6 8056.2 7997.7 7791.2 7312.7 7014.9 6871.1 6369.6 6723.0 6725.8 6612.7 6676.7 6845.5 7326.6 8242.2 8429.1 8408.9 8384.3 8415.4 8369.2 8424.8 8353.5 8069.6 7573.1 8392.7 8384.2 8408.0 8410.9 8408.5 8405.8 8401.8 8361.8 8392.5 8399.7 8337.8 8400.1 8398.7 8398.0 8397.5 7234.0 8403.3 8408.9 8361.5 8397.3 8405.4 8438.3 8357.7 8440.0 8320.1 8444.4 8399.5 8388.6 8382.1 8432.2 8371.5 4433.0;
11865.5 11700.2 8081.0 8042.6 8051.6 7968.7 7914.7 7873.2 7690.8 7553.4 7405.0 6735.5 6465.8 6240.7 6071.6 6070.4 6352.0 6411.6 6216.3 6193.8 6500.7 9538.8 9767.7 9849.5 9744.3 9805.9 6837.0 6802.7 6793.7 6727.1 6724.0 6252.4 6607.5 6528.7 6462.1 6354.7 6305.2 6333.3 6340.4 6379.7 6291.2 6459.7 6413.3 6432.8 6546.5 6467.9 6646.6 6839.8 6614.7 6618.1 6547.8 6582.0 6578.8 6608.3 6515.9 6568.2 6484.3 6599.7 6481.8 5850.3 6014.0 6022.5 5871.9 4141.2;
8329.1 10210.8 6729.8 5982.7 5734.9 5447.6 5189.1 4880.2 4736.1 5329.8 4473.7 4295.4 4151.9 4001.4 3915.2 4320.7 4986.9 5222.4 5770.8 6041.0 6555.8 6941.9 7086.5 7039.9 6985.2 6872.7 6995.0 6952.9 6752.4 6687.6 6680.7 3381.3 6545.3 6474.7 6477.0 6417.8 6469.2 6541.0 6549.2 6628.1 6600.1 6545.5 6320.7 6335.4 6320.8 6323.0 6240.5 6461.2 6290.9 6226.9 6289.6 6342.3 6332.3 6235.0 6065.6 6261.6 6129.9 6210.8 6212.4 6162.8 6133.5 6100.0 5984.3 2975.5;
10210.0 7710.4 7007.7 6004.9 5391.6 4882.8 4340.9 3966.4 3602.9 3653.0 3095.2 2993.3 2985.3 2871.8 2834.5 2106.3 3583.1 3598.9 3562.2 3902.7 4139.8 4420.6 4835.1 5753.3 5478.3 7030.2 5832.4 6073.7 6225.8 6158.7 6317.2 1974.8 6242.3 6264.8 6378.2 6286.0 6374.0 6475.7 6691.1 6860.4 6722.9 6692.2 6630.6 9157.9 6628.7 6481.1 6615.8 5219.8 6508.9 6634.5 6662.8 6827.6 6406.8 6453.0 6144.5 6521.6 6537.7 6594.4 6507.1 6610.0 6515.5 6568.7 6328.2 1812.0;
];
% 创建网格
[X, Y] = meshgrid(strides, sizes);
% 绘制三维图
figure;
surf(X, Y, data);
% 设置颜色映射
colormap jet;
colorbar;
% 添加标签
xlabel('Stride');
ylabel('Size (KB)');
set(gca, 'YDir', 'reverse')
zlabel('Throughput (KB/sec)');
title('Memory Mountain');
% 调整视角
view(45, 30);
3. 测量TLB代码:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define ARRAY_SIZE (256 * 1024 * 1024) // 256MB
#define PAGE_SIZE 4096 // 4KB
#define NUM_TRIALS 1000 // 访问次数
void clear_cache() {
int* dummy = (int*)malloc(ARRAY_SIZE);
for (int i = 0; i < ARRAY_SIZE / sizeof(int); i += PAGE_SIZE / sizeof(int)) {
dummy[i] = i;
}
free(dummy);
}
void measure_tlb_miss_rate() {
int* array = (int*)malloc(ARRAY_SIZE);
int stride, i, trial;
LARGE_INTEGER start, end, frequency;
double elapsed_time;
// 获取高精度计时器的频率
QueryPerformanceFrequency(&frequency);
printf("Stride (pages)\tTime (ms)\n");
for (stride = 1; stride <= 1024; stride *= 2) {
elapsed_time = 0.0;
for (trial = 0; trial < NUM_TRIALS; trial++) {
// 清空缓存
clear_cache();
// 开始计时
QueryPerformanceCounter(&start);
// 访问数组
for (i = 0; i < ARRAY_SIZE / sizeof(int); i += stride * PAGE_SIZE / sizeof(int)) {
array[i] = i;
}
// 结束计时
QueryPerformanceCounter(&end);
// 累加时间
elapsed_time += (double)(end.QuadPart - start.QuadPart) * 1000.0 / frequency.QuadPart;
}
// 计算平均时间
elapsed_time /= NUM_TRIALS;
printf("%d\t\t%f\n", stride, elapsed_time);
}
free(array);
}
int main() {
measure_tlb_miss_rate();
return 0;
}
常用虚拟机指令:
实验五:/*
进入实验五文件夹(需要先创建):cd ~/Desktop/experiment_5
编译main_a.c:gcc -o main_a main_a.c
以不同大小运行main_a(此处为100):./main_a 100
编译main_a_better.c:gcc -o main_a_better main_a_better.c
以不同矩阵大小、块大小运行优化的main_a(此处为1500、16):
./main_a_better 1500 512
解压mountain:tar-xvf mountain.tar
*/