MSI:当共享和无效状态可以同时出现时
MSI: When shared and invalid states can occur at the same time
因此,正如标题所说,是否有可能处理器 0 的行 A 处于共享 (S) 状态,而处理器 1 的行 B 处于无效 (I) 状态?
想象一下以下情况:
- P0:A线|已修改
- P1:A线|无效
- P2:A线|无效
如果P2对Line A发出读请求,P1的最终状态是什么?共享还是保持无效?
TL;DR
P1的线路A仍将处于Invalid状态。其他处理器的操作无法更改无效状态。
P0 和 P2 都有处于共享状态的线路 A。
在 Wikipedia's page for the MSI protocol 上有算法的状态机描述。
除了英文说明,还有两张图片。
给定一组处理器及其相关的高速缓存行,处理器可以通过在“load/read”和“store/write”之间执行一个操作来“主动”,或者可以“被动” " 通过监听总线上的事件。
MSI(和类似)协议的输入是动作或总线事件。为简单起见,维基百科将状态机分为两部分:一个输入是动作,另一个输入是总线事件。
这样你就可以用一张图片计算主动处理器线路的新状态(正好是一个),另一张图片计算被动处理器线路的状态。
假设处理器 X 是活动处理器,因此进行加载或存储。
第一张图片描述了处理器 X(活动处理器)的缓存行状态如何变化:
每个标签的形式为 x/y 其中 x 是输入操作(PrRd 对于 load/read 或 PrWr 对于 store/write) 和 y 是发出的总线事件(“-”表示总线上没有发出任何事件)。
第二张图片的用法类似,但用于无源处理器(除处理器 X 之外的任何处理器):
这里的每个标签都是 x/y 对,但是 x 是一个总线事件,y 是总线操作。
总线事件是:
- BusRd -> 另一个处理器需要从内存(或上层缓存)读取一行。
- BusRdX -> 另一个处理器需要从内存(或上层缓存)读取一行,但随后会立即修改它(即因为它正在执行 写).
- BugUpgr -> 另一个处理器刚刚写入了到目前为止只读过的其中一个缓存行。
当然,一个Flush就是往内存中写一行的行为。维基百科将其视为总线事务(我将其视为总线操作,因为它不用作输入)。
我们现在可以回答您的问题了。
P2 是活动处理器,需要读取行 A,因此它执行 PrRd。第一张图告诉我们它的线 A 将以 S 状态结束,并且在总线上发出 BusRd(注意这是一个心智模型,真实的硬件可能不会发送一个特殊的事务,而是它会检测读取本身)。
P2: LineA -> Shared
P0 和 P1 都是无源处理器,都看到 BusRd。
P0 的线路处于修改状态,第二张图片告诉我们它将刷新线路(使最后一个值对 P2 可用)并将线路 A 设置为共享状态。
P1 的行处于 Invalid 状态,从第二张图片我们可以看出,对于被动处理器来说,没有办法摆脱 Invalid 状态。具体来说,BusRd输入会再次将A线的状态设置为Invalid(实际上是被忽略了)。
所以从 P2 读取后我们有:
P0: LineA -> Shared
P1: LineA -> Invalid
P2: LineA -> Shared
因此,正如标题所说,是否有可能处理器 0 的行 A 处于共享 (S) 状态,而处理器 1 的行 B 处于无效 (I) 状态?
想象一下以下情况:
- P0:A线|已修改
- P1:A线|无效
- P2:A线|无效
如果P2对Line A发出读请求,P1的最终状态是什么?共享还是保持无效?
TL;DR
P1的线路A仍将处于Invalid状态。其他处理器的操作无法更改无效状态。
P0 和 P2 都有处于共享状态的线路 A。
在 Wikipedia's page for the MSI protocol 上有算法的状态机描述。
除了英文说明,还有两张图片。
给定一组处理器及其相关的高速缓存行,处理器可以通过在“load/read”和“store/write”之间执行一个操作来“主动”,或者可以“被动” " 通过监听总线上的事件。
MSI(和类似)协议的输入是动作或总线事件。为简单起见,维基百科将状态机分为两部分:一个输入是动作,另一个输入是总线事件。 这样你就可以用一张图片计算主动处理器线路的新状态(正好是一个),另一张图片计算被动处理器线路的状态。
假设处理器 X 是活动处理器,因此进行加载或存储。
第一张图片描述了处理器 X(活动处理器)的缓存行状态如何变化:
每个标签的形式为 x/y 其中 x 是输入操作(PrRd 对于 load/read 或 PrWr 对于 store/write) 和 y 是发出的总线事件(“-”表示总线上没有发出任何事件)。
第二张图片的用法类似,但用于无源处理器(除处理器 X 之外的任何处理器):
这里的每个标签都是 x/y 对,但是 x 是一个总线事件,y 是总线操作。
总线事件是:
- BusRd -> 另一个处理器需要从内存(或上层缓存)读取一行。
- BusRdX -> 另一个处理器需要从内存(或上层缓存)读取一行,但随后会立即修改它(即因为它正在执行 写).
- BugUpgr -> 另一个处理器刚刚写入了到目前为止只读过的其中一个缓存行。
当然,一个Flush就是往内存中写一行的行为。维基百科将其视为总线事务(我将其视为总线操作,因为它不用作输入)。
我们现在可以回答您的问题了。
P2 是活动处理器,需要读取行 A,因此它执行 PrRd。第一张图告诉我们它的线 A 将以 S 状态结束,并且在总线上发出 BusRd(注意这是一个心智模型,真实的硬件可能不会发送一个特殊的事务,而是它会检测读取本身)。
P2: LineA -> Shared
P0 和 P1 都是无源处理器,都看到 BusRd。
P0 的线路处于修改状态,第二张图片告诉我们它将刷新线路(使最后一个值对 P2 可用)并将线路 A 设置为共享状态。
P1 的行处于 Invalid 状态,从第二张图片我们可以看出,对于被动处理器来说,没有办法摆脱 Invalid 状态。具体来说,BusRd输入会再次将A线的状态设置为Invalid(实际上是被忽略了)。
所以从 P2 读取后我们有:
P0: LineA -> Shared
P1: LineA -> Invalid
P2: LineA -> Shared