一个简单的ia32的CPU指令重排序与cache问题,我的推算为什么得不出示例的结果?

篇幅略长,直接贴过来格式上不方便阅读,所以放到ItEye上(请教处理器cache与指令重排序问题 ),请各位点开链接查看一下具体描述,然后在知乎上解答…
关注者
103
被浏览
6,224

2 个回答

Intel的手册没有错。你推理的Processor 0和Processor 1上的三条指令不能reorder也是对的。

问题的关键在于处理器(这里指processor 0和processor 1)内的Write Buffer。为了提高性能,把Write从Critical Path上移除掉,现代处理一般都实现了Write Buffer。它的作用是存储已经committed (retired)的store指令的结果,直到cache已经取得相应数据的读写权限。

用你的例子来说明:processor 0先把[_x]写成1,实际只是把数据[_x]=1写到了Write Buffer里面。然后接着执行r1=[_x],由于[_x]就在Write Buffer里面,所以直接返回数据,因此r1=1。同理,此时processor 1也只是把[_y]=1写到了它自己的Write Buffer里面,还没有获取到[_y]的读写权限,所以cache里面的[_x]和[_y]还是旧数据([_x]=[_y]=0)。因此,接下来的r2=[_y]和r4=[_x]都可能读取到旧数据0。

这种情况是满足cache一致性协议的。比如processor 0的私有cache里面有[_y]=0并且具有只读权限,processor 0把[_x]=1写到Write Buffer同时向directory要求[_x]的读写权限,随后的r2=_y在私有cache里面命中,直接返回旧数据[_y]=0。(此时processor 1要求invalidate processor 0私有cache里面的[_y]的请求可能还没有到。)

谢邀。

Intel的手册里写的是对的,r2 r4可以同时为0。你可以写个简单的代码,就有一定概率把r2r4同时为0的情况复现出来。

关键问题在于没有加锁。只有在加了锁或者使用了其他机制确保串行操作的前提下,core1修改的值才能被core2及时看到,不然的话两个core就有可能都从cache里面读取x=0,y=0的旧数据然后开始执行,core1的数据来不及通过一致性协议传递给core2,core2也不能传给core1,也就是说,你的推理的第三步成立的前提条件遗漏了。

在你所阅读的8.2.1小节里面就有这句话,可能看漏了:

Software intended to operate correctly in processor-ordered processors (such as the Pentium 4, Intel Xeon, and P6 family processors) should not depend on the relatively strong ordering of the Pentium or Intel486 processors.Instead, it should ensure that accesses to shared variables that are intended to control concurrent execution among processors are explicitly required to obey program ordering through the use of appropriate locking or serializing operations (see Section 8.2.5, “Strengthening or Weakening the Memory-Ordering Model”).