mfence
documentation说:
对所有“从内存加载”和“ MFENCE之前发布的存储到内存指令 指令。此序列化操作可确保每个负载和 将MFENCE指令之前的指令存储在程序中 在任何加载或存储指令之前,订单变得全局可见 遵循MFENCE指令。
据我所知,x86中没有栅栏指令可以阻止对非读和非写指令的重新排序。
现在,即使我的程序只有一个线程,即使对指令进行了重新排序,也仍然看起来指令在按顺序执行。
但是,如果我的程序有多个线程,并且在其中一个线程中对非读和非写指令进行了重新排序,其他线程会注意到这种重新排序(我认为答案是否,否则会有围栏指令停止对非读和非写指令的重新排序,或者我丢失了某些东西)?
答案 0 :(得分:5)
其他线程是否会注意到此重新排序
否,除了性能(定时或使用硬件性能计数器直接测量)。或微体系结构辅助通道(例如,与超线程/ SMT共享物理内核的逻辑内核的ALU端口压力):一个线程可以计时自己来了解其他硬件线程正在执行的操作。>
线程观察彼此之间唯一的“正常”方式是加载其他线程存储的数据。
即使负载排序也仅是间接可见的(通过它对其他线程决定以后存储的内容的影响)。
据我所知,x86中没有栅栏指令可以阻止对非读和非写指令的重新排序。
在Intel CPU(而非AMD)上,lfence
执行此操作。英特尔手册如此说,这不是只是实现细节。实际上,可以保证将来的微体系结构。
英特尔的LFENCE instruction-set reference manual entry:
直到在本地完成所有先前的指令后,LFENCE才会执行,并且在LFENCE完成之前,没有后续的指令开始执行。
(本地完成=从混乱的核心中退出,即离开ROB)。
lfence
作为实际的负载屏障并不是特别有用,因为x86不允许来自WB内存的弱排序负载(仅来自WC)。 (甚至movntdqa
或prefetchnta
都无法从普通WB内存中创建弱排序的负载。)因此,与sfence
不同,lfence
基本上不需要进行内存排序,仅具有特殊效果,例如lfence
; rdtsc
。或者,为了减轻“幽灵”攻击,阻止过去的投机执行。
但是,作为实现细节,在至少包括Skylake的Intel CPU上,mfence
是无序执行的障碍。 请参见Are loads and stores the only instructions that gets reordered?,以及更多相关内容。