我阅读了《英特尔架构优化指南》。
但是,我仍然不知道什么时候应该使用
_mm_sfence()
_mm_lfence()
_mm_mfence()
谁能解释一下,在编写多线程代码时,什么时候应该使用这些?
发布于 2012-10-12 07:45:34
这是我的理解,希望是准确和简单到有意义的:
(安腾) IA64体系结构允许以任何顺序执行内存读取和写入,因此从另一个处理器的角度来看,内存更改的顺序是不可预测的,除非您使用栅栏以合理的顺序强制该写入完成。
从这里开始,我要说的是x86,x86是强有序的。
在x86上,英特尔不保证在另一处理器上完成的商店在此处理器上始终可见。有可能这个处理器推测性地执行加载(读取)的时间刚刚够早,以至于错过了另一个处理器的存储(写入)。它只保证写入对其他处理器可见的顺序是按程序顺序进行的。它不能保证无论您做什么,其他处理器都会立即看到任何更新。
锁定的读取/修改/写入指令完全顺序一致。因此,通常情况下,您已经处理了丢失的其他处理器的内存操作,因为锁定的xchg
或cmpxchg
将同步所有这些操作,您将立即获取相关的缓存线以获得所有权,并将自动更新它。如果另一个CPU正在与您的锁定操作竞争,要么您将赢得竞争,另一个CPU将错过高速缓存并在您的锁定操作之后将其取回,或者它们将赢得竞争,而您将错过高速缓存并从它们获得更新值。
lfence
会暂停指令发布,直到lfence
之前的所有指令都完成。mfence
专门等待所有先前的内存读取完全进入目标寄存器,并等待所有先前的写入变得全局可见,但不会像lfence
那样停止所有进一步的指令。sfence
仅对存储执行相同的操作,刷新写入组合器,并确保在允许sfence
之后的任何存储开始执行之前,sfence
之前的所有存储都是全局可见的。
在x86上几乎不需要任何类型的屏障,除非您正在使用写组合内存或非临时指令,否则不需要它们,如果您不是内核模式(驱动程序)开发人员,则很少这样做。通常,x86保证所有存储按程序顺序可见,但它不保证WC (写组合)内存或执行显式弱有序存储的“非临时”指令,如movnti
。
因此,总而言之,存储在程序顺序中总是可见的,除非您使用了特殊的弱有序存储或正在访问WC内存类型。使用锁定指令(如xchg
、xadd
或cmpxchg
等)的算法将在没有栅栏的情况下工作,因为锁定指令是顺序一致的。
https://stackoverflow.com/questions/4537753
复制相似问题