是否在x86中对非读和非写指令重新排序有关系吗?

时间:2018-06-27 05:53:27

标签: multithreading assembly x86 memory-barriers

mfence documentation说:

  

对所有“从内存加载”和“   MFENCE之前发布的存储到内存指令   指令。此序列化操作可确保每个负载和   将MFENCE指令之前的指令存储在程序中   在任何加载或存储指令之前,订单变得全局可见   遵循MFENCE指令。

据我所知,x86中没有栅栏指令可以阻止对非读和非写指令的重新排序。

现在,即使我的程序只有一个线程,即使对指令进行了重新排序,也仍然看起来指令在按顺序执行。

但是,如果我的程序有多个线程,并且在其中一个线程中对非读和非写指令进行了重新排序,其他线程会注意到这种重新排序(我认为答案是,否则会有围栏指令停止对非读和非写指令的重新排序,或者我丢失了某些东西)?

1 个答案:

答案 0 :(得分:5)

  

其他线程是否会注意到此重新排序

否,除了性能(定时或使用硬件性能计数器直接测量)。或微体系结构辅助通道(例如,与超线程/ SMT共享物理内核的逻辑内核的ALU端口压力):一个线程可以计时自己来了解其他硬件线程正在执行的操作。

线程观察彼此之间唯一的“正常”方式是加载其他线程存储的数据。

即使负载排序也仅是间接可见的(通过它对其他线程决定以后存储的内容的影响)。


  

据我所知,x86中没有栅栏指令可以阻止对非读和非写指令的重新排序。

在Intel CPU(而非AMD)上,lfence执行此操作。英特尔手册如此说,这不是只是实现细节。实际上,可以保证将来的微体系结构。

  

英特尔的LFENCE instruction-set reference manual entry

     

直到在本地完成所有先前的指令后,LFENCE才会执行,并且在LFENCE完成之前,没有后续的指令开始执行。

(本地完成=从混乱的核心中退出,即离开ROB)。

lfence作为实际的负载屏障并不是特别有用,因为x86不允许来自WB内存的弱排序负载(仅来自WC)。 (甚至movntdqaprefetchnta都无法从普通WB内存中创建弱排序的负载。)因此,与sfence不同,lfence基本上不需要进行内存排序,具有特殊效果,例如lfencerdtsc。或者,为了减轻“幽灵”攻击,阻止过去的投机执行。


但是,作为实现细节,在至少包括Skylake的Intel CPU上,mfence 是无序执行的障碍。 请参见Are loads and stores the only instructions that gets reordered?,以及更多相关内容。