如何从C程序在Linux中刷新CPUcaching?

我正在写一个C程序,我需要刷新我的记忆。 我想知道是否有任何UNIX系统命令刷新CPUcaching

这是我的项目需要计算我的逻辑所花费的时间。

我已经读了关于cacheflush(char *s, int a, int b)函数,但是我不确定它是否合适以及在参数中传递什么。

Solutions Collecting From Web of "如何从C程序在Linux中刷新CPUcaching?"

  1. 我认为你的意思是“CPU缓存”,而不是内存缓存

  2. 上面的链接是好的:建议“通过CPU写入大量数据” 不是 Windows特定的

  3. 这是同一主题的另一个变体:

    • 如何清除CPU L1和L2缓存
  4. 这里有一篇关于Linux和CPU缓存的文章:

注意:

在这个(非常非常低的)级别上,“Linux”!=“Unix”

如果你正在编写一个用户模式(而不是内核模式)的程序,并且它是单线程的,那么你真的没有理由在第一时间打扰你的缓存。 您的用户模式程序可能会忘记它甚至存在; 只是在那里加快程序的执行速度,操作系统通过处理器的MMU管理它。

只有几个原因,我可以想到,你可能真的想从你的用户模式应用程序清空缓存:

  1. 您的应用程序旨在运行在对称多处理器系统上,或者与外部硬件有数据交易)
  2. 你只是简单地测试一下你的缓存来进行某种性能测试(在这种情况下,你应该真的应该编写你的测试在内核模式下运行,或许是一个驱动程序)。

无论如何,假设你正在使用Linux …

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

这假设你有一个你刚刚写的内存块,你想确保它从缓存刷新回主内存。 该块从addr开始,它的长度为nbytes,位于两个缓存之一(或两者)中:

  ICACHE Flush the instruction cache. DCACHE Write back to memory and invalidate the affected valid cache lines. BCACHE Same as (ICACHE|DCACHE). 

通常你只需要刷新DCACHE,因为当你写数据到“内存”(即缓存),通常是数据,而不是指令。

如果你想刷新“所有的缓存”出于某种奇怪的测试原因,你可以malloc()一个大块,你知道比你的CPU的缓存大(拍摄,使它的8倍!),写任何旧的垃圾进入它,并冲洗整个块。

另请参阅: 如何在C ++中执行缓存操作?

好的,对于我的第一个答案感到抱歉 我后来在你的问题后面阅读了你的后续评论,所以我现在意识到你要刷新INSTRUCTION CACHE来将你的程序(或其中的一部分)从缓存中引导出来,这样当你测试它的性能时,其初始加载时间超出主存到指令缓存中。 你是否也需要清空代码将用于主内存的数据,以便数据和代码都是新的加载?

在此之前,我想提一下,主内存本身也是一种缓存形式,你的硬盘(不管是磁盘上的程序还是磁盘上的交换空间)是程序指令可能最低,最慢的地方从。 也就是说,当你第一次运行一个例程时,如果它已经由于接近已经执行的其他代码而没有从磁盘加载到主存储器中,那么它的CPU指令将首先被加载从磁盘。 这比从主存储器将其加载到高速缓存中的时间要长一个数量级或更多。 然后,一旦将其加载到主存储器中,就需要从主存储器加载到缓存中的时间比从缓存中加载到CPU的指令获取器所需要的时间长一些。 所以,如果你想测试你的代码的冷启动性能,你必须决定什么冷启动手段….把它从磁盘上拉出来,或者从主内存中拉出来。 我不知道有什么命令将指令/数据从主内存中“冲出”到交换空间,所以将其清除到主内存大概就像你所能做的那样(我知道),但请记住即使您执行刷新指令高速缓存,您的测试结果仍可能与第一次运行(即将其从磁盘中拔出时)不同。

现在,如何去刷新指令缓存,以确保自己的代码刷新到主内存?

如果我需要这样做(在我看来是非常奇怪的事情),我可能会开始找到我的功能在内存中的长度和大致的位置。 因为我使用的是Linux,所以我会发出命令“objdump -d {myprogram}> myprogram.dump.txt”,然后在编辑器中打开myprogram.dump.txt并搜索我要刷新的函数通过使用十六进制计算器从他们的起始地址中减去他们的结束地址,计算出他们的时间。 我会写下每个的大小。 稍后,我会在代码中添加cacheflush()调用,并将每个函数的地址都作为“addr”输出,并将其长度设置为“nbytes”和ICACHE。 只是为了安全起见,我可能会勉强一点,并增加10%的大小,以防万一我对代码做了一些调整,忘记调整nbytes。 我会打电话给cacheflush()这样的每个功能,我想刷新。 那么如果我还需要刷新数据,如果它使用全局/静态数据,我也可以刷新这些数据(DCACHE),但是如果它是堆栈或堆数据,那么我可以(或者应该)执行刷新超出缓存。 试图这样做会是一种愚蠢的行为,因为它会创造一个在正常执行中永远或很少存在的条件。 假设你正在使用Linux …

 #include <asm/cachectl.h> int cacheflush(char *addr, int nbytes, int cache); ...where cache is one of: ICACHE Flush the instruction cache. DCACHE Write back to memory and invalidate the affected valid cache lines. BCACHE Same as (ICACHE|DCACHE). 

顺便说一句,这是一个班的作业吗?

这是英特尔建议刷新缓存的方式:

 mem_flush(const void *p, unsigned int allocation_size){ const size_t cache_line = 64; const char *cp = (const char *)p; size_t i = 0; if (p == NULL || allocation_size <= 0) return; for (i = 0; i < allocation_size; i += cache_line) { asm volatile("clflush (%0)\n\t" : : "r"(&cp[i]) : "memory"); } asm volatile("sfence\n\t" : : : "memory"); }