繁体   English   中英

如何通过IO时序测量找到L1缓存行大小的大小?

[英]How to find the size of the L1 cache line size with IO timing measurements?

作为一项学校作业,我需要找到一种方法来获取L1数据缓存行大小,而无需读取配置文件或使用api调用。 假设使用内存访问读/写时序来分析和获取此信息。 那我该怎么做呢?

在完成另一部分任务的不完整尝试中,为了找到缓存的级别和大小,我有:

for (i = 0; i < steps; i++) {
    arr[(i * 4) & lengthMod]++;
}

我想也许我只需要改变第2行, (i * 4)部分? 所以一旦我超过缓存行大小,我可能需要更换它,这需要一些时间? 但它是如此直截了当? 所需的块可能已经存在于内存中? 或者perpahs我仍然可以依靠这样一个事实,即如果我有足够大的steps ,它仍然会非常准确地运作?

UPDATE

下面是对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(数组的大小)

分配一个BIG char数组(确保它太大,不适合L1 L2缓存)。 用随机数据填写。

n个字节为步长开始遍历数组。 对检索到的字节执行某些操作,例如对它们进行求和。

基准测试并计算您可以使用不同的n值处理多少字节/秒,从1开始并计数到1000左右。 确保您的基准测试打印出计算的总和,因此编译器无法优化基准测试代码。

n ==您的缓存行大小时, 每次访问都需要在L1缓存中读取新行。 因此,基准测试结果应该在这一点上变得非常急剧。

如果数组足够大,那么当你到达终点时,数组开头的数据将再次超出缓存,这就是你想要的。 因此,在增加n并重新开始之后,结果将不会受到缓存中已有数据的影响。

看看Calibrator ,所有的工作都受版权保护,但源代码是免费提供的。 从它的文档想法来计算缓存行大小听起来比这里已经说过的更有教育意义。

我们的校准器工具的基本思想是拥有一个微基准测试,其性能仅取决于发生的高速缓存未命中的频率。 我们的校准器是一个简单的C程序,主要是一个执行一百万次内存读取的小循环。 通过改变步幅(即,两个后续存储器访问之间的偏移)和存储区域的大小,我们强制改变缓存未命中率。

原则上,高速缓存未命中的发生由阵列大小决定。 一旦数据加载到缓存中,适合L1缓存的数组大小不会生成任何缓存未命中。 类似地,超过L1高速缓存大小但仍然适合L2的阵列将导致L1未命中但没有L2未命中。 最后,大于L2的阵列导致L1和L2未命中。

高速缓存未命中的频率取决于访问跨度和高速缓存行大小。 当步幅等于或大于高速缓存行大小时,每次迭代都会发生高速缓存未命中。 如果步幅小于高速缓存行大小,则仅每n次迭代(平均)发生高速缓存未命中,其中n是高速缓存行大小/步幅的比率。

因此,我们可以通过将没有未命中的执行时间与执行时间进行比较来计算高速缓存未命中的等待时间,每次迭代恰好一次丢失。 这种方法只有在内存访问是纯顺序执行的情况下才有效,即我们必须确保两个或多个加载指令,内存访问和纯CPU工作都不能重叠。 我们使用一个简单的指针追踪机制来实现这一点:我们访问的内存区域被初始化,以便每个load在下一次迭代中返回后续加载的地址。 因此,超标量CPU无法通过推测执行来隐藏内存访问延迟。

为了测量缓存特性,我们多次运行实验,改变步幅和数组大小。 我们确保步幅至少在4个字节和最大预期高速缓存行大小的两倍之间变化,并且数组大小从最小预期高速缓存大小的一半变化到最大预期高速缓存大小的至少十倍。

我不得不注释#include "math.h"来编译它,之后它发现我的笔记本电脑的缓存值正确。 我也无法查看生成的postscript文件。

您可以在汇编程序中使用CPUID函数,虽然不可移植,但它会为您提供所需的功能。

对于Intel微处理器,可以通过在调用cpuid函数0x1后将bh乘以8来计算高速缓存行大小。

对于AMD微处理器,数据高速缓存行大小在cl中,并且在调用cpuid函数0x80000005之后指令高速缓存行大小为dl。

我从这篇文章中得到了这个。

我认为你应该编写程序,它将以随机顺序直接遍历数组,因为现代流程会进行硬件预取。 例如,make int of int,其值将是下一个单元格的数量。 我做了类似的程序1年前http://pastebin.com/9mFScs9Z对不起我的英语,我不是母语。

了解如何实现memtest86。 他们以某种方式测量和分析数据传输速率。 速率变化点对应于L1,L2的大小和可能的L3高速缓存大小。

如果你陷入困境并无法离开,请看这里

有手册和代码可以解释如何做你要问的事情。 代码质量也很高。 看看“子程序库”。

代码和手册基于X86处理器。

我认为应该对使用一定量内存的操作进行计时。 然后逐步增加操作使用的内存(例如操作数)。 当操作性能急剧下降时,您已找到限制。

我只需要读取一堆字节而不打印它们(打印会使性能如此糟糕而成为瓶颈)。 在读取时,时间应该与读取的字节数直接成比例,直到数据不再适合L1,然后您将获得性能损失。

您还应该在程序开始时和开始计算时间之前分配一次内存。

只是一张纸条。

高速缓存行大小在少数ARM Cortex系列中是可变的,并且可以在执行期间更改,而无需向当前程序发送任何通知。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM