确定缓存是写回还是直通。

3
我如何通过测试写入缓存来确定缓存类型(写回/直通)?我可以使用与确定缓存级别和大小相似的方法,通过记录修改缓存的时间来优化内容,但我需要进行比较。例如,如果时间明显短于已知的L1写入直通缓存,则可以说它是写回。但是,我需要一个基准进行比较,不是吗? 这是我在GitHub上尝试的结果 主要思想是:
- 如果是直通写入,则写入x次所需的时间与写入x * 100次的时间大约相同 - 如果是写回,则时间大约相同?
因此,将循环的时间(WRITES_BASE次与WRITES次)减去仅执行循环(没有内存访问)的时间,然后进行比较...这让我觉得我的Core i3 2100具有所有的写入直通缓存...
16, 0.03, 1.04 (31.28) 
128, 0.07, 2.31 (31.78) 
2048, 0.10, 3.19 (31.74) 

上述数值为:测试大小(KB),WRITES_BASE的时间,WRITES的时间(t(WRITES)/t(WRITES_BASE)) 我猜测实验中的问题在于我没有消除运行WRITES更多次所需的时间差异...
更新:
我注意到一个奇怪的事情,如果我保持WRITES = 64 * WRITES_BASE,那么如果我有WRITES_BASE = 400万
16, 0.01, 0.13 (17.16) 
128, 0.01, 0.29 (31.60) 
2048, 0.01, 0.41 (30.53) 

如果我增加WRITES_BASE = 1600万

16, 0.02, 0.52 (25.53) 
128, 0.04, 1.16 (31.74) 
2048, 0.05, 1.57 (31.89)

注意,当WRITES_BASE较小时,时间差异较小,可能表明L1是写回高速缓存。然而,由于这并不总是正确的,例如当我增加WRITES_BASE时,我想知道是否存在一些逻辑错误?
1个回答

2
您不能仅通过此过程区分写回缓存和写直通缓存。考虑:如果您正在使用写回缓存,则执行循环中的指令需要X时间,并且需要Y时间进行写回。 Y不由您的代码测量(您没有任何关于显式缓存刷新或类似操作的计时)。当您循环N次时,需要N * X时间,加上在代码执行完成后刷新缓存所需的Y。

对于写直通缓存,X更高,而Y为零。但是,单个循环与多个循环之间的比率相同。因此,您无法通过此过程区分它们。

尽管如此,有一些方法可以检测到这一点。关键是在计时时强制缓存刷新其缓存行。尝试比较编写各种大小的数组所需的时间。在写入之间,请确保通过读取大量不相关的数据来刷新任何写回缓存(注意:不要只分配一个大型数组并从未写入它 - 在程序启动时将其写入一次,然后在计时运行之间读取整个数组。否则,数组中的所有页面可能会指向物理内存中的相同清零页面,具体取决于您的操作系统)。

您还可以尝试查看写入大量数据何时影响读取的速度。在写直通缓存中,读取不应仅因为您最近写入数据而花费更长时间。在写回缓存中,读取可能必须等待缓存刷新 - 因此,在单独计时读取与立即在写入之后进行读取之间的时间可能会给您带来一些有趣的结果。


嗯...“编写各种大小的数组”部分是如何涉及到这个问题的呢?这是指每个缓存级别的大小吗? - Jiew Meng
如果你写入的数据超出了缓存,你会期望等待写回操作完成,对吧? - bdonlan
是的,但它会写入另一个高速缓存吗?如果是这种情况,时间增加可能是由于下一级较慢的写入时间引起的?在另一个实验中确定高速缓存的级别和大小时,我使用了 *另一个实验**。 - Jiew Meng
GitHub 上更新了源代码。当大小超过当前缓存级别大小时,似乎会出现时间上的峰值。然而,由于该代码与用于**确定缓存级别或大小**的代码非常相似,我想知道是否在其中一个代码中做错了什么? - Jiew Meng
@JiewMeng,说得好,很难区分写回时间和首次加载缓存行所需的时间。我添加了另一个建议。 - bdonlan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接