为什么加载不能绕过写入缓冲区中同一内核上的另一个线程写入的值?

Why can't a load bypass a value written by another thread on the same core from a write buffer?

如果CPU核心使用写缓冲区,那么加载可以绕过最近的存储到写缓冲区中的引用位置,而不用等到它出现在缓存中。但是,正如 A Primer on Memory Consistency and Coherence 中所写,如果 CPU 支持 TSO 内存模型,那么

... multithreading introduces a subtle write buffer issue for TSO. TSO write buffers are logically private to each thread context (virtual core). Thus, on a multithreaded core, one thread context should never bypass from the write buffer of another thread context. This logical separation can be implemented with per-thread-context write buffers or, more commonly, by using a shared write buffer with entries tagged by thread-context identifiers that permit bypassing only when tags match.

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

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 模型。

全局转发存储实际上是不可能的,因为缓冲存储不一定被提交,这意味着它们甚至可能处于分支预测错误的错误路径中。本地转发很好,因为刷新也会消除从它们转发的所有负载,但在多个上下文中你没有。 我还看到过尝试在核心外部全局缓冲存储的工作,但由于延迟和带宽,这不是很实用。为了进一步阅读,这里有一篇可能相关的最新论文 - http://ieeexplore.ieee.org/abstract/document/7783736/