我无法理解JSR-133 Coookbook中 StoreLoad 障碍的定义。
商店1; StoreLoad; LOAD2
StoreLoad屏障使用Store1的数据值而不是从较新的商店到不同处理器执行的同一位置的数据值不正确地防止后续加载。
这是否意味着如果没有 StoreLoad 障碍,处理器可以将Store1存储到其写缓冲区并从其写缓冲区加载此存储的值,即使某些其他处理器写入了相同的内存位置并刷新到Store1和Load1之间的缓存?
答案 0 :(得分:4)
是的,这可能,取决于内存排序模型。
写缓冲区通常是预分配,这意味着其中的商店尚不能被外部世界观察到。但是,为了获得更好的性能,大多数微架构允许同一线程上的年轻负载执行,如果地址与存储的地址匹配 - 可以执行数据转发以使程序尽可能快地继续,同时使负载看起来好像这是在商店之后完成的。
这适用于线程内一致性,但是当外部处理器访问相同的地址并可能更改数据时,负载看起来可能为时已晚(尽管在负载上可能仍会捕获许多CPU)尚未完成,机器将自行修复)。
我不完全确定引用的含义是什么,但我认为可以通过这种情况更好地证明:
CPU0: CPU1:
store [x]<--1
store [x]<--2
store [y]<--2
load r1<--[x]
load r2<--[y]
没有障碍的可能结果(理论上)是r1 == 1, r2 == 2
,这意味着CPU1的两个存储都已经执行(因为我们从2
读取[y]
),但不知何故[x]
的值已经存活(因为它被转发)。
我真的不喜欢这个例子,首先是因为,正如我所说,大多数CPU应该成功地窥探那个负载的旧值,即使它已经执行了。其次 - 它过于复杂,因为他们坚持要求:
StoreLoad仅用于将商店与相同位置的后续加载分开,与存储在屏障之前的相同位置
这是错误的,当地址不同时也需要屏障,如下面(经典)示例所示:
CPU0: CPU1:
store [x]<--1 store [y]<--1
load r1<--[y] load r2<--[x]
这里的地址不同,仍然需要一个障碍来防止两个负载读取旧值的情况(即使两个存储都必须执行才能到达那里),这要归功于负载的无序执行。请注意,这与提供的问题(存储到加载转发)不同,但它证明引用是错误的。