作为学校作业,我需要找到一种方法来获取L1数据缓存行大小,而无需读取配置文件或使用api调用。假设使用存储器访问读/写时序来分析&得到这个信息。那我该怎么做呢?
在对作业的另一部分进行不完整的尝试时,找到等级&缓存的大小,我有:
for (i = 0; i < steps; i++) {
arr[(i * 4) & lengthMod]++;
}
我想也许我只需要改变第2行,(i * 4)
部分?所以一旦我超过缓存行大小,我可能需要更换它,这需要一些时间?但它是如此直截了当?所需的块可能已经存在于内存中?或者perpahs我仍然可以依靠这样一个事实,即如果我有一个足够大的steps
,它仍然可以非常准确地运作?
更新
Heres an attempt on GitHub ...下面的主要部分
// repeatedly access/modify data, varying the STRIDE
for (int s = 4; s <= MAX_STRIDE/sizeof(int); s*=2) {
start = wall_clock_time();
for (unsigned int k = 0; k < REPS; k++) {
data[(k * s) & lengthMod]++;
}
end = wall_clock_time();
timeTaken = ((float)(end - start))/1000000000;
printf("%d, %1.2f \n", s * sizeof(int), timeTaken);
}
问题是时间似乎没有太大差异。仅供参考。因为它用于L1缓存。我有SIZE = 32 K(数组大小)
答案 0 :(得分:27)
分配一个BIG char
阵列(确保它太大,不适合L1 或 L2缓存)。用随机数据填写。
开始以n
字节为步长遍历数组。使用检索到的字节执行某些操作,例如对它们进行求和。
基准测试并计算您可以使用不同的n
值处理多少字节/秒,从1开始计算到1000左右。确保您的基准测试打印出计算的总和,因此编译器无法优化基准测试代码。
当n
==您的缓存行大小时,每次访问都需要在L1缓存中读取新行。所以基准测试结果在这一点上会变得非常缓慢。
如果数组足够大,那么当你到达终点时,数组开头的数据将再次超出缓存,这就是你想要的。因此,在您递增n
并重新开始后,结果将不会受到缓存中已有数据的影响。
答案 1 :(得分:5)
查看Calibrator,所有作品均受版权保护,但source code可免费使用。从其document想法来计算缓存行大小听起来比那里已经说过的更有教养。
我们的校准器工具的基本思想是拥有一个仅依赖性能的微基准测试 关于发生的缓存未命中的频率。我们的校准器是一个简单的C程序,主要是一个小循环 执行一百万次内存读取。通过改变步幅(即,后续两个之间的偏移) 内存访问)和内存区域的大小,我们强制不同的缓存未命中率。
原则上,缓存未命中的发生由数组大小决定。适合的数组大小 一旦数据加载到缓存中,L1缓存就不会生成任何缓存未命中。类似地, 超过L1缓存大小但仍然适合L2的数组将导致L1未命中但没有L2未命中。最后, 大于L2的数组会导致L1和L2未命中。
缓存未命中的频率取决于访问跨度和缓存行大小。大踏步前进 等于或大于高速缓存行大小,每次迭代都会发生高速缓存未命中。大踏步前进 如果小于高速缓存行大小,则仅在每n次迭代(平均)中发生高速缓存未命中,其中n为 比率缓存 线 大小/步幅。
因此,我们可以通过比较执行时间来计算缓存未命中的延迟 每次迭代只错过一次错过执行时间。 此方法仅适用于 内存访问是纯粹顺序执行的,即我们必须确保两个或两个以上的加载 指令,内存访问和纯CPU工作可以重叠。我们使用简单的指针追逐 实现此目的的机制:我们访问的内存区域被初始化,以便每个负载返回 下一次迭代中后续加载的地址。因此,超标量CPU无法从中受益 他们通过推测性执行隐藏内存访问延迟的能力。
为了测量缓存特性,我们多次运行实验,改变步幅和 数组大小。我们确保步幅至少在4个字节和最大值的两倍之间变化 预期的缓存行大小,以及数组大小从最小预期缓存大小的一半变化到 至少是最大预期缓存大小的十倍。
我必须注释#include "math.h"
才能编译,之后它才能正确找到笔记本电脑的缓存值。我也无法查看生成的postscript文件。
答案 2 :(得分:3)
您可以在汇编程序中使用CPUID
函数,虽然不可移植,但它会为您提供所需的内容。
对于英特尔微处理器,可以通过在调用cpuid函数0x1后将bh乘以8来计算高速缓存行大小。
对于AMD微处理器,数据高速缓存行大小在cl中,并且在调用cpuid函数0x80000005之后指令高速缓存行大小为dl。
我从article here获取了这个。
答案 3 :(得分:2)
我认为你应该编写程序,它将以随机顺序直接遍历数组,因为现代流程会进行硬件预取。 例如,make int of int,其值将是下一个单元格的数量。 我做了类似的程序1年前http://pastebin.com/9mFScs9Z 对不起我的英语,我不是母语。
答案 4 :(得分:1)
了解如何实现memtest86。他们以某种方式测量和分析数据传输速率。速率变化点对应于L1,L2的大小和可能的L3缓存大小。
答案 5 :(得分:1)
答案 6 :(得分:0)
我认为应该对使用一定量内存的操作进行计时。然后逐步增加操作使用的内存(例如操作数)。 当操作性能急剧下降时,您已找到限制。
我只需要阅读一堆字节而不打印它们(打印会使性能如此糟糕,以至于会成为瓶颈)。在读取时,时间应该与读取的字节数直接成比例,直到数据不再适合L1,然后你将获得性能损失。
您还应该在程序开始时和开始计时之前分配一次内存。
答案 7 :(得分:0)
只是一张纸条。
高速缓存行大小在少数ARM Cortex系列中是可变的,并且可以在执行期间更改,而不会向当前程序发送任何通知。