如何强制 L2 缓存未命中?

How can I force an L2 cache miss?

我想研究 L2 缓存未命中对 CPU 功耗的影响。为了衡量这一点,我必须创建一个逐渐增加工作集大小的基准,以便核心 activity(每个周期执行的微操作)和 L2 activity(每个周期的 L2 请求)保持不变,但是L2未命中与L2请求的比率增加。

谁能给我一个强制 "N" 次二级缓存未命中的 C 程序示例?

您通常可以通过随机访问大于该缓存级别的工作集来在某些缓存级别强制缓存未命中1.

您会期望任何给定负载未命中的概率类似于:p(hit) = min(100, C / W)p(miss) = 1 - p(hit) 其中 p(hit)p(miss) 是概率命中和未命中,C 是相关缓存大小,W 是工作集大小。因此,对于 50% 的未命中率,使用两倍于缓存大小的工作集。

快速浏览一下上面的公式可以看出,p(miss) 永远不会是 100%,因为 C/W 只会在 W 趋于无穷大时趋于 0(而且您可能负担不起无穷大内存量)。所以你的选择是:

  1. 通过使用非常大的工作集(例如,4 GB 为 256 KB 提供 99% 以上的失误率)获得 "close enough",并假设您的失误率为100%.

  2. 应用公式来确定实际预期的未命中数。例如,如果您对 256 KB 的 L2 缓存使用 2560 KB 的工作大小,则您的未命中率为 90%。所以如果你想检查 1,000 次未命中的影响,你应该进行 1000 / 0.9 = ~1111 内存访问以获得大约 1,000 次未命中。

  3. 使用任何近似的方法,然后 实际计算 使用 CPU 上的性能计数器单元导致的未命中次数。例如,在 Linux 上,您可以使用 PAPI or on Linux and Windows you could use Intel's PCM(如果您使用的是 Intel 硬件)。

  4. 使用 "almost random" 方法来强制达到您想要的未命中次数。上面的公式对随机访问有效,但如果您选择访问模式使其随机并注意它不会重复 "recent" 访问,您可以获得 100% 的未命中率。这里 "recent" 表示访问可能仍在缓存中的缓存行。准确计算这意味着什么是棘手的,并且在细节上取决于缓存的关联性和替换算法,但是如果您不重复在最后 cache_size * 10 次访问中发生的任何访问,您应该是非常安全的。

至于 C 代码,您至少应该向我们展示您的尝试。一个基本的轮廓是创建一个字节或整数或任何具有所需大小的向量,然后随机访问该向量。如果您使每次访问都依赖于先前的访问(例如,使用整数读取来计算下一次读取的索引),您还将粗略测量该级别缓存的延迟。如果访问是独立的,您可能会立即对缓存有几个未命中,并且每单位时间会出现更多未命中。你对哪一个感兴趣取决于你学的是什么。

对于跨不同步幅和工作集大小进行此类内存测试的开源项目,请查看 TinyMemBench


1 对于内核之间共享的缓存级别(例如,对于最近的英特尔芯片通常是 L3),这会有点棘手 - 但如果您的机器,它应该可以正常工作测试时非常安静。