如何用C编写程序来测量缓存的速度?

时间:2013-04-26 17:34:12

标签: c caching

编写程序并尝试比较(测量,如果可以)从主存和缓存访问数据的时间。

如果可以这样做,那么如何衡量每个缓存级别的速度?

3 个答案:

答案 0 :(得分:5)

您需要提出一种启发式方法,强制100%(或非常接近)缓存未命中(希望您有缓存失效操作码?)和100%缓存命中。 Hooray,适用于1级缓存。现在,如何对2级和3级做同样的事情?

严肃地说,如果没有连接到CPU和内存的特殊硬件和跟踪,可能无法100%可靠地完成此操作,但这就是我要做的事情:

将一堆“东西”写入内存中的1个位置 - 足以让您确定它是否一致地命中L1缓存并记录时间(这会影响缓存,所以要小心)。你应该在没有分支的情况下进行这组写操作,以试图摆脱分支预测的不一致性。那是最好的时间。现在,每隔一段时间,将缓存行的数据写入已知位置末尾的RAM中的随机远程位置并记录新时间。希望这需要更长的时间。在不同时间继续进行此录制,希望您会看到几个倾向于分组的时间。这些组中的每一个“都可以”显示L2,L3和存储器访问时序的时序。问题是还有很多其他的东西妨碍了。操作系统可以上下文切换你并搞砸你的缓存。中断可能会出现并通过你的时间关闭。会有很多东西可以抛弃这些价值。但是,希望您在数据中获得足够的信号,看它是否有效。

这可能更容易在一个更简单的嵌入式系统上进行,操作系统(如果有的话)不会妨碍你。

答案 1 :(得分:3)

这通常需要一些关于缓存的“几何”及其它方面的知识。除了简单的用户访问系统和依赖于实现的事情之外,对系统进行一些控制也是有帮助的,例如比通过标准C clock机制提供的更精确的时序。

这是一个初步方法:

  • 编写一个例程,该例程采用指向内存的指针,长度和重复次数,并以连续的顺序重复读取所有内存。
  • 编写一个例程,该例程以连续的顺序重复读取内存,长度和重复次数并写入所有内存。
  • 上述例程可能必须将其指针转换为volatile,以防止编译器优化远程访问,否则无效。
  • 分配大量内存。
  • 调用上述每个例程,获取每次调用之前和之后的当前时间,并使用各种长度调用以查看不同长度的时间。

执行此操作时,通常会看到较小长度的快速速度(每秒读取/写入的字节数),较长的速度较慢。在超过不同级别的高速缓存的大小的情况下将发生速度降低。因此,您很可能会看到使用上述技术收集的数据中反映出L1和L2缓存的大小。

以下是一些方法不足的原因:

  • 它不控制用于读取或写入缓存的指令。 C编译器可以生成加载字和存储字指令,但是许多现代处理器具有可以一次加载和存储16个字节的指令,并且使用这些指令的读取和写入可能比使用四字节字指令更快。
  • 当您按顺序访问时,缓存的行为将与您随机访问缓存的行为不同。大多数缓存都会尝试跟踪何时使用数据,以便最近使用的数据保留在缓存中,而其他数据则被淘汰。实际程序的访问部分通常与上述连续操作不同。
  • 特别是,对内存的连续写入可能能够填充整个高速缓存行,因此不需要从内存中读取任何内容,而仅将一个单词写入特定位置的实际使用模式可能必须是通过从内存中读取缓存行并合并更改的字节来实现。
  • 来自系统上其他进程的竞争将干扰缓存和测量中的内容。

答案 2 :(得分:2)

看看cachegrind-valgrind

  

Cachegrind模拟程序与计算机缓存的交互方式   层次结构和(可选)分支预测器。它模拟一台机器   具有独立的第一级指令和数据缓存(I1和D1),   由统一的二级缓存(L2)支持。这完全符合   许多现代机器的配置。

请参阅以某种方式相关的好问题:

  1. How do I programmatically disable hardware prefetching?
  2. How would you generically detect cache line associativity from user mode code?
  3. How to invalidate cache when benchmarking?