Multithreading 如果在x86中对非读和非写指令重新排序,这有关系吗?
Multithreading 如果在x86中对非读和非写指令重新排序,这有关系吗?,multithreading,assembly,x86,memory-barriers,Multithreading,Assembly,X86,Memory Barriers,mfence说明如下: 对从内存和内存加载的所有数据执行序列化操作 在MFENCE之前发出的存储到内存指令 指示此序列化操作确保每个加载和 在程序中存储MFENCE指令之前的指令 订单在任何加载或存储指令之前全局可见 遵循MFENCE指令 据我所知,x86中没有栅栏指令可以阻止非读和非写指令的重新排序 现在,如果我的程序只有一个线程,即使指令被重新排序,它仍然看起来好像指令是按顺序执行的 但是,如果我的程序有多个线程,并且其中一个线程中的非读和非写指令被重新排序,那么其他线程会注意到这种重新排序
mfence
说明如下:
对从内存和内存加载的所有数据执行序列化操作
在MFENCE之前发出的存储到内存指令
指示此序列化操作确保每个加载和
在程序中存储MFENCE指令之前的指令
订单在任何加载或存储指令之前全局可见
遵循MFENCE指令
据我所知,x86中没有栅栏指令可以阻止非读和非写指令的重新排序
现在,如果我的程序只有一个线程,即使指令被重新排序,它仍然看起来好像指令是按顺序执行的
但是,如果我的程序有多个线程,并且其中一个线程中的非读和非写指令被重新排序,那么其他线程会注意到这种重新排序吗(我假设答案是否,否则会有一个围栏指令来停止非读和非写指令的重新排序,或者可能我遗漏了什么)
其他线程会注意到这种重新排序吗
不,除了性能(使用硬件性能计数器计时或直接测量)或微体系结构侧通道(如与超线程/SMT共享物理内核的逻辑内核的ALU端口压力):一个线程可以对自身计时,以了解另一个硬件线程正在执行的操作
线程观察彼此的唯一“正常”方式是加载其他线程存储的数据
甚至加载顺序也只是间接可见的(通过它对另一个线程决定稍后存储的内容的影响)
据我所知,x86中没有栅栏指令可以阻止非读和非写指令的重新排序 在英特尔CPU(但不是AMD)上,
lfence
做到了这一点。英特尔的手册上说,这不仅仅是一个实现细节。它实际上保证了未来的微体系结构
英特尔:
LFENCE在所有之前的指令在本地完成之前不会执行,以后的指令在LFENCE完成之前不会开始执行
(本地完成=从无序堆芯中退出,即离开ROB)
lfence
作为实际的负载屏障并不特别有用,因为x86不允许从WB内存(仅从WC)进行弱顺序加载。(甚至movntdqa
或prefetchnta
都不能从正常WB内存创建弱顺序加载。)因此,与sfence
不同,lfence
基本上不需要用于内存排序,仅用于其特殊效果,如lfence
;rdtsc
。或者用于频谱缓解,以阻止经过它的推测执行
但是作为一个实现细节,在至少包括Skylake的Intel CPU上,
mfence
是无序执行的障碍。请参阅这一点以及更多相关内容。另一个线程如何检测非内存操作的重新排序?@RaymondChen:如果其中一条指令是rdtsc
,那么差异在体系结构上成为寄存器中的一个值。但这是一个非常特殊的情况。有趣的事实:至少在Skylake上,mfence
实际上确实阻止了所有指令的重新排序,比如lfence
。不过这是一个实现细节;从纸面上看,它只阻止了内存指令的重新排序。(但这也是Linux内核恢复为锁或[rsp],0
而不是MFENCE的部分原因)