C 为什么双链表中的指针追踪可以避免缓存抖动(自逐出)?

C 为什么双链表中的指针追踪可以避免缓存抖动(自逐出)?,c,caching,cpu,cpu-architecture,cpu-cache,C,Caching,Cpu,Cpu Architecture,Cpu Cache,我试图了解缓存计时问题 在第3.6节中,作者解释了一种技术,该技术允许您填充连续缓存区域并测量此填充过程的时间。他们提到: “原始和探测步骤的简单实现(即以固定的步幅扫描内存缓冲区)由于在现代CPU中实现了两种优化而产生了很差的结果:内存访问的重新排序,以及“硬件预取器”在内存之前的自动读取。我们的 攻击代码通过使用以下“指针追踪”技术来解决这两种中断。在初始化期间,攻击者的内存被组织成一个链表(可选,随机排列);稍后,通过遍历该列表来完成启动和探测(见图7)。以最小化缓存抖动(自逐出),我们使

我试图了解缓存计时问题

在第3.6节中,作者解释了一种技术,该技术允许您填充连续缓存区域并测量此填充过程的时间。他们提到:

“原始和探测步骤的简单实现(即以固定的步幅扫描内存缓冲区)由于在现代CPU中实现了两种优化而产生了很差的结果:内存访问的重新排序,以及“硬件预取器”在内存之前的自动读取。我们的 攻击代码通过使用以下“指针追踪”技术来解决这两种中断。在初始化期间,攻击者的内存被组织成一个链表(可选,随机排列);稍后,通过遍历该列表来完成启动和探测(见图7)。以最小化缓存抖动(自逐出),我们使用一个双链表,向前遍历它进行启动,向后遍历它进行探测。此外,为了避免“污染”它自己的样本,探测代码将每个获得的样本存储到它刚刚完成测量的同一个缓存集中。在某些平台上,可以通过使用写入而不是读取,或者超过W次读取来改善时间间隔。”

我对这一段有一个问题:


链表如何避免由于硬件预取和重新排序而导致的定时变化?

目前实现的硬件预取器仅处理固定的跨步访问模式,因此,根据内存地址任意排序的访问不会被识别为可预取。这种硬件预取器仍然可以检测并使用意外的步幅模式。例如,如果地址[X+5]=地址[X]+N和地址[X+7]=地址[X+5]+2N(请注意,地址之间不必用常数访问计数分隔),预取器可能会预测N的步长。这可能会适度减少明显的未命中延迟(某些预取是有效的)或引入一些缓存污染

(如果检测到的/预测的N很小,并且链表包含在相对于缓存大小的内存的适当区域内(因此,大多数跨步预取都是针对将要使用的soonish的地址),则基于跨步的预取可能具有明显的积极效果。)

通过使用依赖于数据的访问(遍历链接需要访问数据),可以防止访问重新排序。在上一个节点的下一个指针可用之前,硬件无法加载下一个节点

有学术建议支持预取此类模式,甚至支持通用关联(例如,see),但(据我所知)尚未在商业硬件中实现


作为旁注,通过以与启动访问相反的顺序遍历探测访问,对于常见的、面向LRU的替换,可以避免过多的未命中。

回答得好。关于这个话题的另一篇有趣的论文是Roth和Sohi撰写的。预取链接列表如此困难的原因是,除非您以前见过它,否则您无法在读取之前运行,而不必自己获取下一个节点。感谢您的见解。