【问题标题】:How to write a program in C to measure the speed of cache?如何用C编写程序来测量缓存的速度?
【发布时间】:2013-04-20 23:08:21
【问题描述】:

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

如果能做到,那如何衡量每一级缓存的速度呢?

【问题讨论】:

  • tnis 是否可行?缓存不在您的控制之下,您无法知道何时从何处加载数据。 (好吧,也许你可以跟踪缓存未命中,但我猜跟踪开销会混淆结果。)
  • 也许使用寄存器和mmap?但这似乎非常主观(除此之外,计算机上还有其他进程运行)。听起来像是应该在硬件级别上完成的事情;否则其他线程/进程/操作系统的东西会妨碍
  • 据我所知,如果我在 C 中定义一个大数组,当我访问该数组中的一个元素时,该元素周围的数据似乎存储在缓存中。因此,如果我从头到尾访问数组,它将比随机访问(访问每个元素一次)更快——这是真的,但我不知道这是缓存或其他方式的结果。
  • 也许您应该相信您可以真正、真正快速地从缓存中检索元素...
  • 用于缓存基准测试的 Google 将产生大量点击,包括一些备受推崇的缓存基准测试程序。

标签: c caching


【解决方案1】:

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

说真的,如果没有连接到 CPU 和内存的特殊硬件和跟踪,可能无法 100% 可靠地做到这一点,但我会这样做:

将“一堆”内容写入内存中的 1 个位置 - 足以确保它一致地访问 L1 缓存并记录时间(这会影响您的缓存,因此请注意)。您应该在没有分支的情况下执行这组写入,以尝试消除分支预测不一致。那是最好的时机。现在,每隔一段时间,将缓存行的数据写入 RAM 中您已知位置右侧的随机遥远位置并记录新时间。希望这需要更长的时间。继续记录不同的时间,希望你会看到几个倾向于组合的时间。这些组中的每一个“可以”显示 L2、L3 和内存访问时序的时序。问题是有太多其他的东西阻碍了。操作系统可以上下文切换你并搞砸你的缓存。中断可能会出现并通过你的时间休息。将会有很多东西可以使价值观偏离。但是,希望您在数据中获得足够的信号,看看它是否有效。

在操作系统(如果有的话)不会妨碍您的更简单的嵌入式系统上,这可能会更容易做到。

【讨论】:

  • 但是如何测量读取一次数据的时间呢?它很短,可能只有几纳秒!
  • 通过做足够的次数。您应该能够数到毫秒级。不过,我并没有说这会很容易:)
  • 但是做了一次之后,可能会被加载到缓存中(假设不是之前)。
【解决方案2】:

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

这是一个初步的方法:

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

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

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

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

【讨论】:

    【解决方案3】:

    看看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?

    【讨论】:

    • 啊,如果仿真质量足够好,仿真可能是更好的选择。好主意。
    猜你喜欢
    • 1970-01-01
    • 2010-11-15
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    相关资源
    最近更新 更多