前言
今天做了实验5,通过 c 语言测 cache 参数。其实按理来说挺简单的,只是我们班没给代码,纯靠自己。听说别的班有给代码
示例代码也有,在《深入理解计算机系统》这本书的 6.6 小结。
上面给的代码是 Linux 平台下的,而且需要一个 fcyc2 头文件,可以在 这里 找到。出于某些原因 我是懒狗 我并没有用这份代码,我想在 win10 下进行测试。
⚠
我没有在 Linux 下试过课本上面的代码。。。
我是在 win10 下测试的。。。
所以 。。。
我并不确定我的代码是否正确。。。
请谨慎食用 Orz
注意事项(⚠ 重要)
唔。。。。我再编辑下,因为这个实验在 win10 下不是特别容易成功,有很多值得注意的地方:
- 请不要使用 visual studio 这个 IDE,因为它是大聪明,会优化掉你的代码。
- 最好使用 dev c++ 这个 IDE,并且开启 std c++11 才能完整地运行代码
开启方法:
- 最好增大测试的次数,114514190 就是一个好数字!
- 不要使用 rand() 这些小随机数生成器
- 不要在最内层循环直接生成随机数,因为生成随机数时间远大于访问内存,这样最多只能测出 L3 的大小
别问我怎么知道的 - 运行时最好关闭所有应用程序,什么秋秋,微信,网抑云,
关掉统统关掉!防止 cpu 抢占 - 可以通过 CPU-Z 这个软件查询精确的缓存大小,但是 emmm 因为我的代码不能够精确地测出 L1 数据缓存和 cache Line 的大小,于是我就用任务管理器糊弄一下就交了报告。。。
![](https://i-blog.csdnimg.cn/blog_migrate/1410a8ff4597729fc2d8f60fd90741dd.png)
- 实验的几个参数最好起不同的变量名。比如随机数的范围就是数组大小,而访问次数应该被设定为一个常数(比如 114514190)
- 以虔诚地跪拜姿势,点击启动运行按钮
- 我编不下去了 Orz
总之就是很玄学 祝大家实验顺利。。。 我先 run 了(逃
实验说明
增进对cache工作原理的理解
体验程序中访存模式变化是如何影响 cahce 效率进而影响程序性能的过程;学习在 X86 真实机器上通过调整程序访存模式来探测多级 cache 结构以及 TLB 的大小。
按照下面的实验步骤及说明,完成相关操作记录实验过程的截图:
- x86 cache 层次结构的测量:
首先设计一个用于测量 x86 系统上 cache 层次结构的方案然后设计出相应的代码;然后,运行你的代码获得相应的测试数据。最后,根据测试数据分析你的x86机器有几级cache,各自容量是多大。 - 选做:尝试测量你 L1 cache 行的大小
- 选做:尝试测量你的 x86 机器 TLB 有多大
要求 1(90分)(报告撰写质量10分)
实验步骤
cache 层级的测量
首先测量我们的电脑 cache 的层级关系。我的方案是这样的:
- 开辟一块大小为 size kb 的内存空间
- 进行若干次随机内存访问
- 记录时间,计算平均的数据吞吐量(kb/s)
- 画图分析,记录 size 与 kb/s 的关系
注:
随机数生成,不要用 rand() 口牙,rand() 范围为 0~32768 好像,这才 30k 不到
我们随机访问是要产生大量随机且有意义的内存访问,要完全覆盖内存,这样才能使得内存尽可能被装进 cache 里面,这意味着随机数的范围需要非常大
要用 c++11 的 uniform_int_distribution
详见下文代码部分~
可行性分析:因为我们使用完全随机的地址进行内存访问,那么:
- 如果该内存能够被完整装入 cache,我们只需要花费很少的时间就可以访问到
- 如果内存块大小 size 超过我们的 cache 大小,即当前内存块不能被完整的放入 cache,那么我们的随机访问时间就会大大增加,因为发生了 miss
所以根据以上的两个分析,我们通过观察【吞吐量/数据集】大小的图表,就能分析出对应的 cahce 的大小和层次结构。
我使用 std c++ 11 在 Windows10 系统上进行实验,IDE 使用 dev c++,未开启任何 O1,O2 优化。
我们编写一个函数名叫 random_access,他会根据参数 size 的大小,创建一块大小为 size byte 的内存空间,并且进行 114514190 次随机访问,并且输出吞吐量(单位为 kb/s)。
void random_access(int size)
{
int n = size / sizeof(char);
char* buffer = new char[n];
fill(buffer, buffer+n, 1);
uniform_int_distribution<> dis(0, n-1);
int test_times = 11451419 * 10;
vector<int> random_index;
for(int i=0; i<test_times; i++)
{
int index = dis(gen);
random_index.push_back(index);
}
int sum = 0;
high_resolution_clock::time_point t1 = high_resolution_clock::now();
for(int i=0; i<test_times; i++)
{
sum += buffer[random_index[i]];
}
high_resolution_clock::time_point t2 = high_resolution_clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
double dt =