WC与WB内存有何区别?x86_64架构上还有哪些其他类型的内存?

7
你能描述一下x86_64架构中WC和WB内存的含义和区别吗?请完整地描述x86_64中的其他类型内存(如果有的话)。

3
请参阅《Intel® 64和IA-32体系结构软件开发人员手册卷3:系统编程指南》,第11.3节“可用的缓存方法”。 - Jester
1个回答

23
我将首先介绍写回缓存(WB),因为它比较容易理解。 写回缓存 顾名思义,这种缓存策略尝试尽可能延迟对系统内存的写入。
这个想法是只使用缓存,理想情况下。
然而,由于缓存具有有限的大小,小于内存的有限大小和其内部组织请参见Wikipedia的Cache文章进行介绍引入一些冲突别名,偶尔需要将缓存行驱逐到内存中。
这是一个写回事件 - 另一个写回事件的来源是高速缓存一致性机制请参见MESI
这就是WB的基本思想,更技术上地说,缓存策略是通过对四个主要事件采取的操作来定义的。
Event              | Action
-------------------+----------------------------------------------
Read hit           | Read from the cache line
-------------------+----------------------------------------------
Read miss          | Fill the line then read from the cache line
-------------------+----------------------------------------------
Write hit          | Write to the cache line
-------------------+----------------------------------------------
Write miss         | Fill the line then write to the cache line*

* Since P6, we will assume this is always the case

正如您所看到的,没有写入内存的操作。这是缓存限制的副作用,反过来又迫使清除操作。
其他缓存属性,如替换策略、一致性、允许的推测行为(以及所有这些如何影响内存访问的可见性和排序)被省略在此答案中,因为它们与缓存策略无关。
英特尔为每个策略隐式设置了某些属性,但这只是为了节省一些配置位。
为了完整起见,以下是与其他缓存策略的比较表。
写合并 (WC) 故意被省略。
Legend
   LF = Line Fill;         LR = Read from line;   MR = Read from memory
   LW = Write to line;     MW = Write to memory

   WB = Write back;        UC = Uncachable (Not cached);
   WT = Write through;     WP = Write protect

Event              | WB      |  UC | WT       | WP     |
-------------------+---------+-----+----------+--------+----------
Read hit           | LR      | MR* | LR       | LR     |
-------------------+---------+-----+----------+--------+----------
Read miss          | LF, LR  | MR  | LF, LR   | LF, LR |
-------------------+---------+-----+----------+--------+----------
Write hit          | LW      | MW  | LW, MW** | MW***  |
-------------------+---------+-----+----------+--------+----------
Write miss         | LF, LW  | MW* | MW       | MW     |

* A hit on a UC region can happen if the cache type has been
  changed without invalidating the cache. In truth for UC talking about
  hits is a bit misleading. Caching is bypassed, so it is actually a
  N.A. case.   

** The line can be invalidated as the result of the eviction operation
   used.

*** Evict the line, even if it was Modified or Exclusive, e.g. because of 
    writes via other current or previous mapping for the same physical page.
    Writing directly to memory by bypassing the caches also invalidates
    all the copies of the affected line in other processors.

备注: WP和WT之间的区别在于后者可以被视为“穿透”缓存,而前者则“绕过”缓存。

写合并

WC实际上不是一种缓存策略,但由于它与缓存策略紧密耦合,因此在这里讨论。
我发现英特尔SDM在这个主题上非常混乱,这是我目前对此事的解释。
欢迎纠正!

有一篇来自英特尔的旧论文可在这里找到关于WC的内容已经包含在Intel SDM 3的第11.3.1节中,但在这样做时,英特尔失去了原始文件中可用的一些上下文和结构。

WC的想法是在长时间操作(如总线事务或高速缓存一致性事务)之前或期间合并写入。

为了实现这一点,处理器拥有多个 WC缓冲区 - 不要将其与缓存行的存储缓冲区混淆。
WC缓冲区是完全独立的实体!

WC缓冲区的数量是有限制的:在P6(因此在Pentium M)中有6个WC缓冲区,Pentium 4有8个,自Nehalem以来有10个WC缓冲区请参见英特尔优化手册的第3.6.10节

每个WC缓冲区的大小没有架构定义,但到目前为止,它总是与缓存行的大小相同(因此对于P6为32字节,对于其他缓存为64字节)。

WC缓冲区位于高速缓存之前。

现在问题来了,WC实际上有两个含义:

  • 在写缺失的情况下,在CPU被允许写入缓存行之前,必须执行RFO(读取所有权)以通知其他CPU它们缓存的数据是否无效。
    由于这可能需要很长时间,CPU会将存储器暂存在WC缓冲区中,并继续进行其工作。然后,缓存子系统将自主地将WC缓冲区移动到适当的缓存中。
    如果连续一行正在执行RFO的存储器抵达,则它们都将沉在WC缓冲区中。

  • 如果内存类型不涉及缓存,则WC缓冲区可以充当存储器的停车场,直到一起传输到总线。
    启动总线事务需要一些开销,但一旦它开始,数据就可以相继传输(实际上每次传输8个字节),非常快。
    写入比内存总线宽度少的数据是浪费内存带宽 - 就像让一辆(真正的)公共汽车半空驶过去一样。 因此,WC试图利用完整的内存总线宽度。

备注:UC内存类型绕过缓存子系统,包括WC缓冲区。WC内存类型绕过缓存但不绕过WC缓冲区。

在第一种情况下,WC允许CPU在长时间操作进行时继续工作,在第二种情况下,它允许数据的高效传输。
英特尔在两种情况下都使用相同的术语WC,我认为这会导致混淆。
英特尔SDM读取WC仅允许在WC内存类型区域中使用,然而后来它声称用于所有内存类型,并在每个缓存策略的描述中报告它。
我认为这是因为英特尔正在参考上述两种WC。
我相信第二种类型是最初的类型,并且当MESI变得流行时,WC缓冲区已被重复使用。

编辑

我忘了提到WC内存类型是不可缓存的(但是具有推测性,推测性已被有意忽略)。 彼得·科德斯在他的评论中完美地概括了它:

WC是USWC的简写:“不可缓存的推测性写组合”。 关键点在于它是一种不可缓存的内存类型,这就是为什么movntdqa负载很有用(以加载一个[存储缓冲区条目,它与一个]完整的缓存行相同,而不是针对来自相同缓存行的单独访问DRAM进行分离的负载[驻留在可以缓存的地址范围内])

我只是添加了括号中的文本,因为我认为他使用“缓存行”作为度量单位和内存地址的区分属性。


在任何时刻只能有四个WC缓冲区处于活动状态。
Intel优化手册还报告说,只能使用两个缓冲区来合并写入高速缓存的操作。

当使用WC将存储器中的存储合并时,处理器不强制执行一致性。
WC缓冲区不被嗅探,此外,当前活动的WC缓冲区之间没有强制执行的顺序(哪一个首先分裂)。
当必须逐出WC时,如果WC缓冲区全部是脏的,则通过执行单个总线事务进行;如果WC缓冲区包含部分数据,则可以通过执行多达8个(64/8)或4个(32/8)总线事务来完成逐出。
同样,在溢出具有部分数据的WC缓冲区时,这些块之间也没有强制执行的顺序。

P6会在软件写入缓冲区大小之外的位置时立即逐出WC缓冲区,确切的算法是由实现定义的 - 通常有一个时间窗口允许软件合并写入操作。
可以通过访问UC内存类型区域或特定事件(请参见本节开头链接的论文)来强制逐出。


2
你可能应该提到WC是USWC的简称:"不可缓存的推测写组合"。关键点在于它是一种不可缓存的内存类型,这就是为什么movntdqa加载很有用(可以加载整个缓存行,而不是从同一缓存行分别访问DRAM进行单独的加载)。 - Peter Cordes
对的,一个64字节自然对齐的块,无论它实际上是在缓存中还是在行填充缓冲区中。 - Peter Cordes
1
WC-buffer和L1D缓存的Line Fill Buffer是一样的吗?我在英特尔Opt. Man.中没有找到明确的提及,但它们至少具有相同数量的条目。 - St.Antario
当需要驱逐一个脏缓存时,如果WC缓存全部是脏数据,则只需执行单个总线事务;如果WC缓存包含部分数据,则需要执行多达8个(64/8)或4个(32/8)总线事务。我不理解这一部分。为什么缓存不全是脏数据时需要更长时间? - SungJinKang
显示剩余3条评论

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