2017-03-17 57 views
1

如果CPU内核使用写入缓冲区,则负载可以将最近的存储从写入缓冲区旁路到引用的位置,而不必等到它出现在缓存中。但是,因为它是写在A Primer on Memory Consistency and Coherence,如果CPU荣誉TSO内存模型,然后为什么不能通过写入缓冲区绕过由同一内核上的另一个线程写入的值?

...多线程引入了TSO一个微妙的写缓存的问题。 TSO 写入缓冲区对于每个线程环境(虚拟 核心)在逻辑上是私有的。因此,在多线程内核中,一个线程上下文决不应该绕过另一个线程上下文的写入缓冲区。可以利用每个线程上下文写入缓冲器 或更通常地通过使用具有线程上下文标识符标记的条目的共享写入缓冲器来实现该逻辑分隔,该线程上下文标识符仅当标签 匹配时才允许旁路。

我无法理解这种限制的必要性。当允许某个线程绕过由同一个内核上的另一个线程写入的写入缓冲区条目导致违反TSO内存模型时,您能否给我举一个例子?

+0

我投票结束这个问题作为题外话题,因为它是关于计算机处理器设计,而不是编程。 –

+1

OP已经恰当地标记了问题,我会说它是一个有效的问题,所以不要关闭它。 –

+0

我认为它的存在是因为,存储缓冲区中的数据没有通过一致性协议,因此允许另一个线程在使其全局可见之前尽早看到写入可能是违规行为。考虑一个4线程的情况,其中两个线程修改相同的位置,另外两个线程尝试读取它。 [我的知识在编写缓冲区时有点生疏,我拉着头发去了解上述场景中写入的内容,大概是必须重做] –

回答

1

的TSO从顺序一致性(SC)之间的不同的典型例子是:

(这是实施例2.4在这里 - http://www.cs.cmu.edu/~410-f10/doc/Intel_Reordering_318147.pdf

thread 0  |  thread 1 
--------------------------------- 
write 1-->[x] | write 1-->[y]  
a = read [x] | b = read [y]  
c = read [y] | d = read [x]  

两个地址存储0开始。问题是:会c = d = 0是一个有效的结果?我们知道a和b必须在它们之前转发商店,因为它们匹配本地商店的地址,并且可能会从本地线程存储缓冲区转发。但是,c和d可能不会跨上下文转发,因此它们仍可能显示旧值。

这里有趣的问题是,由于每个线程都观察两个存储并转发本地数据,并且a = 1的结果,c = 0意味着t0首先看到存储为[x]。 b = 1,d = 0的结果意味着t1首先发现商店存在[y]。由于存储缓冲区转发的缘故,这是一个可能的结果,这一事实将会破坏顺序一致性,因为它要求所有上下文都在相同的全局存储顺序上达成一致。相反,x86决定采用允许这种情况的较弱的TSO模型。

全球转发商店实际上是不可能的,因为缓冲商店不一定是承诺的,这意味着他们甚至可能在分支预测失误的错误路径。本地转发没问题,因为flush可以消除从它们转发的所有负载,但是在多个上下文中没有这些。 我也看到了一些尝试在全局核心之外缓冲全局存储的工作,但由于延迟和带宽的原因,这不太实际。对于进一步阅读,这里有一个最近可能相关的文章 - http://ieeexplore.ieee.org/abstract/document/7783736/

+0

感谢您的解释。我认为作为内存系统一部分的写缓冲区只包含退役指令,并且所有推测性存储区都在早期阶段的内部CPU缓冲区内进行处理。 – undermind

+0

如果仅在退休的商店中允许商店加载转发,则与以前的商店相匹配的每个加载都必须停止。这将简化订购,但可怕地降低性能。如果你允许转发投机性商店,那么它们所处的结构并不重要,在逻辑上它只是商店的另一个缓冲区。顺便说一下,存储缓冲区既包含推测性商店又包含非投机性商店,但这些非投机性商店也必须是可窥探的。 – Leeor

+0

好的答案,但它并没有真正解决OP引用的具体问题,这是为什么绕过从逻辑核心上的一个线程到同一核心上的另一个线程(这在硬件级别上是“自然的”)的负载不是在TSO中不允许。您指出,从一种上下文绕过到另一种上下文在推测执行方面存在问题,这是事实,但它可能是可以解决的(例如,只通过转发非推测性商店或通过另一核心上的某些资源-speculation)。 – BeeOnRope

相关问题