WC 与 WB 内存? x86_64 上的其他类型的内存?
WC vs WB memory? Other types of memory on x86_64?
能否描述一下x86_64上WC和WB内存的含义和区别?为了完整起见,请在 x86_64 上描述其他类型的内存,如果有的话。
我先从回写缓存(WB)开始,因为它更容易理解。
写回缓存
顾名思义,这种缓存策略会尽可能地延迟对系统内存的写入。
理想情况下,我们的想法是只使用缓存。
但是,由于缓存的有限大小小于内存的有限大小及其内部组织请参阅Wikipedia's Cache article了解介绍偶尔会引入一些冲突的别名缓存行必须被逐出内存。
这是回写事件 - 回写事件的另一个来源是 缓存一致性机制 参见 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
如您所见,没有写入内存。这是缓存限制的副作用,反过来会强制驱逐。
其他缓存属性,如替换策略、一致性、允许的推测行为(以及所有这些结果如何影响内存访问的可见性和顺序)被排除在这个答案之外,因为它们与缓存策略正交。
英特尔为每个策略隐式设置了其中一些属性,但这只是为了节省一些配置位。
为了完整起见,这里是 table 与其他缓存策略的比较。
写入组合 (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 上提供了一篇旧论文 here - 其内容已包含在英特尔 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(Read For Ownership)以通知其他 CPU 认为他们的缓存数据(如果有的话)并非无效。
由于这可能需要很长时间,因此 CPU 将商店停在 WC 缓冲区中并继续其工作。然后缓存子系统会自动将 WC 缓冲区移动到适当的缓存。
如果对正在执行 RFO 的同一行的连续存储到达,它们将全部沉入 WC 缓冲区。
如果内存类型不涉及缓存,则 WC 缓冲区在商店完全转移到总线之前充当商店的停车场。
启动总线事务需要一些开销,但一旦启动,数据可以以连续的突发传输(实际上每个 8 字节)非常快。
写入少于内存总线宽度的数据是对内存带宽的浪费——就像让总线(真正的总线,供人使用的总线)运行 半空一样。
所以 WC 正试图利用整个内存总线宽度。
备注:UC 内存类型绕过所有缓存子系统,包括 WC 缓冲区。 WC 内存类型绕过缓存但不绕过 WC 缓冲区。
在第一种情况下,WC 允许 CPU 在进行长期操作时继续其工作,在第二种情况下,它允许高效传输数据。
英特尔对这两种情况使用相同的术语 WC,导致我认为混淆。
Intel SDM 读到 WC 只允许在 WC 内存类型区域上使用,但后来它声称它用于所有内存类型,并在每个缓存策略的描述中报告它。
我相信这是因为英特尔指的是上述两个 WC。
我相信第二种类型是原始类型,并且在 MESI 流行时 WC 缓冲区已被重复使用。
编辑
我忘了说 WC 内存类型是不可缓存的(不过是推测,推测已被故意忽略)。
Peter Cordes 在 中完美地总结了它:
WC is short-hand for USWC: "Uncacheable Speculative Write-Combining".
The key point is that it's an uncacheable memory type, which is why movntdqa
loads are useful (to load a [store buffer entry, that is as wide as a] full cache line, instead of doing separate accesses to DRAM for separate loads [residing in an address range that could be cached ] from the same cache line)
我刚刚在括号中添加了文本,因为我相信他使用术语“缓存行”作为度量单位和内存地址的区分 属性。
在给定时刻只能激活四个 WC 缓冲区。
英特尔优化手册还报告说只有两个可以用来组合写入缓存。
当使用 WC 将存储组合到内存时,处理器不会强制执行一致性。
WC 缓冲区未被监听,此外,在当前活动的 WC 缓冲区(首先溢出)之间没有强制执行任何顺序。
当必须驱逐 WC 时,如果 WC 缓冲区全部变脏,则执行单个总线事务;如果 WC 缓冲区包含部分数据,则执行最多 8 (64 / 8) 或 4 (32 / 8) 个总线事务.
同样,当使用部分数据溢出 WC 缓冲区时,块之间不会强制执行任何顺序。
一旦软件写入超出缓冲区大小,P6 就会逐出 WC 缓冲区,具体算法由实现定义 - 通常有一段时间 window 允许软件合并写入。
可以通过访问 UC 内存类型区域或特定事件来强制逐出(请参阅本节开头链接的论文)。
能否描述一下x86_64上WC和WB内存的含义和区别?为了完整起见,请在 x86_64 上描述其他类型的内存,如果有的话。
我先从回写缓存(WB)开始,因为它更容易理解。
写回缓存
顾名思义,这种缓存策略会尽可能地延迟对系统内存的写入。
理想情况下,我们的想法是只使用缓存。
但是,由于缓存的有限大小小于内存的有限大小及其内部组织请参阅Wikipedia's Cache article了解介绍偶尔会引入一些冲突的别名缓存行必须被逐出内存。
这是回写事件 - 回写事件的另一个来源是 缓存一致性机制 参见 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
如您所见,没有写入内存。这是缓存限制的副作用,反过来会强制驱逐。
其他缓存属性,如替换策略、一致性、允许的推测行为(以及所有这些结果如何影响内存访问的可见性和顺序)被排除在这个答案之外,因为它们与缓存策略正交。
英特尔为每个策略隐式设置了其中一些属性,但这只是为了节省一些配置位。
为了完整起见,这里是 table 与其他缓存策略的比较。
写入组合 (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 上提供了一篇旧论文 here - 其内容已包含在英特尔 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(Read For Ownership)以通知其他 CPU 认为他们的缓存数据(如果有的话)并非无效。
由于这可能需要很长时间,因此 CPU 将商店停在 WC 缓冲区中并继续其工作。然后缓存子系统会自动将 WC 缓冲区移动到适当的缓存。
如果对正在执行 RFO 的同一行的连续存储到达,它们将全部沉入 WC 缓冲区。如果内存类型不涉及缓存,则 WC 缓冲区在商店完全转移到总线之前充当商店的停车场。
启动总线事务需要一些开销,但一旦启动,数据可以以连续的突发传输(实际上每个 8 字节)非常快。
写入少于内存总线宽度的数据是对内存带宽的浪费——就像让总线(真正的总线,供人使用的总线)运行 半空一样。 所以 WC 正试图利用整个内存总线宽度。
备注:UC 内存类型绕过所有缓存子系统,包括 WC 缓冲区。 WC 内存类型绕过缓存但不绕过 WC 缓冲区。
在第一种情况下,WC 允许 CPU 在进行长期操作时继续其工作,在第二种情况下,它允许高效传输数据。
英特尔对这两种情况使用相同的术语 WC,导致我认为混淆。
Intel SDM 读到 WC 只允许在 WC 内存类型区域上使用,但后来它声称它用于所有内存类型,并在每个缓存策略的描述中报告它。
我相信这是因为英特尔指的是上述两个 WC。
我相信第二种类型是原始类型,并且在 MESI 流行时 WC 缓冲区已被重复使用。
编辑
我忘了说 WC 内存类型是不可缓存的(不过是推测,推测已被故意忽略)。
Peter Cordes 在
WC is short-hand for USWC: "Uncacheable Speculative Write-Combining".
The key point is that it's an uncacheable memory type, which is whymovntdqa
loads are useful (to load a [store buffer entry, that is as wide as a] full cache line, instead of doing separate accesses to DRAM for separate loads [residing in an address range that could be cached ] from the same cache line)
我刚刚在括号中添加了文本,因为我相信他使用术语“缓存行”作为度量单位和内存地址的区分 属性。
在给定时刻只能激活四个 WC 缓冲区。
英特尔优化手册还报告说只有两个可以用来组合写入缓存。
当使用 WC 将存储组合到内存时,处理器不会强制执行一致性。
WC 缓冲区未被监听,此外,在当前活动的 WC 缓冲区(首先溢出)之间没有强制执行任何顺序。
当必须驱逐 WC 时,如果 WC 缓冲区全部变脏,则执行单个总线事务;如果 WC 缓冲区包含部分数据,则执行最多 8 (64 / 8) 或 4 (32 / 8) 个总线事务.
同样,当使用部分数据溢出 WC 缓冲区时,块之间不会强制执行任何顺序。
一旦软件写入超出缓冲区大小,P6 就会逐出 WC 缓冲区,具体算法由实现定义 - 通常有一段时间 window 允许软件合并写入。
可以通过访问 UC 内存类型区域或特定事件来强制逐出(请参阅本节开头链接的论文)。