假设一条带有变量 X 的缓存行同时上传到 CPU0 的 L1d 和 CPU1 的 L1d。从CPU0改变X的值后,当CPU1的L1d缓存线失效时,如果CPU0有一条带X的缓存线,CPU1就不能从CPU0的L1d缓存中复制变量X吗?即使不是这种情况,我也想知道是否存在 CPU0 引入 CPU1' 的情况
2 回答
所描述的情况是不允许的。当处理器内核对某个地址执行存储时,数据会被写入“存储缓冲区”,以便稍后传输到高速缓存。在从存储缓冲区传输数据之前,缓存需要对行进行独占访问——这种状态一次只能存在于一个缓存中。
三个简单的案例:
- 如果核心的缓存已经具有独占访问权限(即,该行处于 Exclusive 或 Modifed 状态),则存储缓冲区可以随时将数据写入缓存。
- 如果核心的缓存有该行的有效副本而没有独占访问(例如“共享”状态),存储缓冲区中新数据的存在将导致缓存为该行生成“升级”请求。在所有其他高速缓存(或目录)确认它们已使该地址的任何副本无效之前,不会授予升级到 E 或 M 状态。
- 如果核心的缓存没有有效的行副本(无地址匹配或地址匹配处于无效状态),缓存将发出“Read With Intent To Modify”请求。这将导致缓存行的当前数据(无论是在内存中还是从另一个内核缓存中的修改副本)传输到请求内核的缓存,并且系统中每个其他缓存中的缓存行无效。
如果两个核心“同时”执行存储指令,则执行细节将导致两个核心之一获得独占访问。另一个核心将“拒绝”其请求(NACK'd),并且它将重试该请求,直到第一个核心+缓存完成其缓存行状态的升级和数据的更新。这种机制强制所有存储到单个地址按顺序处理,即使它们是同时发出的。
一般来说,用户不可能可靠地在两个内核中“同时”发生某些事情(或检测它是否同时发生),但实现必须通过上述序列化过程来解决它.
您将如何从副本已失效的 L1 中复制?它不再有该行的副本。
但无论如何,很确定在 L1d 未命中后首先检查的地方是本地 L2,然后是共享 L3。
在 Skylake 服务器或更高版本(因此不包含 L3)上,我认为 L3 未命中将从 DRAM 重新加载,除非该线路在另一个内核中处于修改状态。
否则,在客户端芯片和更早的 Xeon 上,如果任何内核具有有效副本,则 L3 未命中是不可能的,因为它具有包容性。(真正的老芯片,在 Nehalem 之前,也没有包含的最后一级缓存,例如 Core2 的 L2)
当您说“如果我们使一个核心中的缓存无效”时,我不确定您是否只是将其从该缓存中逐出,例如为其他内容腾出空间,或者您的意思是运行类似clflush
. 或者,如果您的意思是核心进行了存储,因此必须执行读取所有权 (RFO) 以获得该行的 MESI 独占所有权(即使所有其他副本无效),以便它可以将存储从存储缓冲区提交到 L1d。