0

对于一些精确的测量,我想从命令行使所有缓存无效/刷新到 RAM(主内存)(以便主程序运行时间评估不受此过程的影响)。我发现了以下内容(第一个和最后一个来自这里):

1. echo 3 > /proc/sys/vm/drop_caches

我可以用以下内容构建一个(预执行的)程序

2. #include <asm/cachectl.h>
int cacheflush(char *addr, int nbytes, int cache);

或者我终于可以做一个

3. int main() {
     const int size = 20*1024*1024; // Allocate 20M. Set much larger then L2
     char *c = (char *)malloc(size);
     for (int i = 0; i < 0xffff; i++)
       for (int j = 0; j < size; j++)
         c[j] = i*j;
 }

我的问题是:对于我需要做的事情,哪个版本是最好的,如果它是#2,我应该给它作为起始地址的地址是什么?我uname -a的是 Linux 3.2.0-33-generic #52-Ubuntu SMP Thu Oct 18 16:19:45 UTC 2012 i686

4

1 回答 1

3

你在一个操作系统上运行,它会在你背后做其他事情。操作系统将处理中断,在后台运行各种守护程序并执行各种维护任务,并可能将您正在运行的进程移动到不同的 cpu 等。

使缓存失效是您最不担心的事情,如果您的测量必须如此准确,您需要重新评估运行测试的环境。即使您设法控制了操作系统所做的一切(这基本上意味着使您的测试代码成为操作系统的一部分),您仍然需要考虑 TLB 行为和分支预测缓冲区(这将比缓存更影响您的性能),控制 SMM(除非您可以控制 BIOS,否则通常无法控制)并了解您用于测量的时钟的实际行为(我猜 10 度的温差会比拥有一个清理缓存)。

换句话说 - 算了吧。实际测量事物的典型方法是运行“足够”次并取平均值(或最小值或最大值或中值,具体取决于您要证明的内容)。

添加更多:您的方法 1 刷新文件系统缓存,与 cpu 上的数据缓存无关。第 2 号我不知道,我的 linux 风格没有它。如果您的 cpu 上具有完美的缓存关联性,那么第 3 号可能会起作用,而您没有,并且必须确保操作系统分配的物理页面将触及每个可能的缓存行,而您不能这样做。您还必须确保您要么在将运行测试的同一 cpu 上执行它,要么在所有 cpu 上执行它,并且不会安排任何东西在其间运行。由于您想从命令行运行它,因此您的 shell 将在程序运行之前很久就踩遍缓存(并且 exec 系统调用和文件系统操作无济于事)。

可靠地清除架构上的缓存的唯一方法是不允许调用 wbinvd 指令,因为您不是内核并且不应该乱用缓存。

于 2012-11-20T13:20:35.597 回答