简短回答:
在乱序处理器中,加载存储队列用于跟踪和强制执行内存排序约束。 Alpha 21264 等处理器具有必要的硬件来防止相关负载重新排序,但强制执行这种相关性可能会增加处理器间通信的开销。
长答案:
依赖性跟踪的背景
这可能最好用一个例子来解释。假设您有以下指令序列(为了简单起见,使用伪代码指令):
ST R1, A // store value in register R1 to memory at address A
LD B, R2 // load value from memory at address B to register R2
ADD R2, 1, R2 // add immediate value 1 to R2 and save result in R2
在此示例中,之间存在依赖关系LD
和ADD
操作说明。这ADD
读取值R2
所以它不能执行,直到LD
使该值可用。这种依赖性是通过寄存器实现的,并且处理器的发出逻辑可以跟踪它。
然而,两者之间也可能存在依赖关系。ST
和LD
,如果地址A
and B
我们是一样的。但与之间的依赖不同LD
和ADD
,之间可能的依赖关系ST
和LD
在发出指令(开始执行)时未知。
处理器不会在问题时尝试检测内存依赖性,而是使用称为加载-存储队列的结构来跟踪它们。该结构的作用是跟踪已发出但尚未退役的指令的挂起加载和存储的地址。如果存在内存顺序冲突,则可以检测到这一点,并且可以从发生冲突的点重新开始执行。
因此,回到伪代码示例,您可以想象这样一种情况:LD
在之前执行ST
(也许 R1 中所需的值由于某种原因尚未准备好)。但当ST
执行它会看到该地址A
and B
是相同的。所以LD
确实应该读取所产生的值ST
,而不是缓存中已经存在的过时值。结果是LD
需要重新执行,以及之后出现的任何指令LD
。有多种优化方法可以减少部分开销,但基本思想是成立的。
正如我之前提到的,检测这种依赖性的逻辑存在于所有允许推测执行内存指令的乱序处理器(包括 Alpha 处理器)中。
内存排序规则
然而,内存排序规则不仅仅限制处理器从其自己的内存操作中看到结果的顺序。相反,内存排序规则限制了在一个处理器上执行的内存操作对其他处理器可见的操作的相对顺序。
阿尔法示例
在依赖负载重新排序的情况下,处理器必须跟踪此信息以供自己使用,但 Alpha ISA 不要求它确保其他处理器看到此排序。下面是如何发生这种情况的一个示例(我引用了这个链接 http://www.cs.umd.edu/~pugh/java/memoryModel/AlphaReordering.html)
Initially: p = & x, x = 1, y = 0
Thread 1 Thread 2
--------------------------------
y = 1 |
memoryBarrier | i = *p
p = & y |
--------------------------------
Can result in: i = 0
目前,该异常行为仅可能出现在基于 21264 的计算机上
系统。显然您必须使用我们的多处理器之一
服务器。最后,你真正看到它的机会非常低,
但这是可能的。
以下是要出现此行为所必须发生的情况。假设T1
在 P1 上运行,T2 在 P2 上运行。 P2 必须缓存位置 y,其值为 0。
P1 执行 y=1,这会导致向 P2 发送“无效 y”。这
invalidate进入P2的传入“探测队列”;随你便
看,问题的出现是因为理论上这会无效
坐在探测队列中,而不在 P2 上执行 MB。无效的是
此时立即确认(即,您不必等待它
在发送之前实际上使 P2 缓存中的副本无效
致谢)。因此,P1可以通过它的MB。它继续
写入 p.现在P2继续读取p。阅读 p 的回复
允许在其传入路径上绕过 P2 上的探测队列(这
允许回复/数据快速返回到 21264,无需
等待之前的传入探测得到服务)。现在,P2可以
取消引用 P 以读取位于其缓存中的 y 的旧值
(P2 的探测队列中的无效 y 仍然存在)。
P2 上的 MB 如何解决这个问题? 21264 刷新其输入探头
每个 MB 都有队列(即,为其中的任何待处理消息提供服务)。
因此,在读取 P 之后,您执行一个 MB,将 inval 拉入 y
一定。并且您无法再看到 y 的旧缓存值。
尽管上述情况在理论上是可能的,但可能性
观察到的问题是极其微小的。原因是
即使你正确设置缓存,P2 也可能有足够的
为探测队列中的消息(即无效)提供服务的机会
在收到“read p”的数据回复之前。尽管如此,如果你
陷入这样一种情况:你在 P2 的探针中放置了很多东西
队列在对 y 的无效之前,则有可能对 p 的回复
返回并绕过此 inval。你会很难
设置场景并实际观察异常情况。
上述内容解决了当前 Alpha 可能如何违反您的规定
显示。由于其他优化,未来的 Alpha 可能会违反它。一
有趣的优化是价值预测。
Summary
所有乱序处理器中都已经存在强制执行相关负载排序所需的基本硬件。但确保所有处理器都能看到这种内存排序会给处理缓存行失效增加额外的限制。它也可能在其他场景中增加额外的限制。然而,在实践中,对于硬件设计人员来说,弱 Alpha 内存模型的潜在优势似乎不值得以软件复杂性和需要更多内存屏障的额外开销为代价。