C++11 cpu如何使用';mfence&x27;为了保护顺序一致性?

C++11 cpu如何使用';mfence&x27;为了保护顺序一致性?,c++11,x86,cpu,atomic,C++11,X86,Cpu,Atomic,我想知道cpu是如何使用“mfence”来保护顺序一致性的,谁能告诉我呢?基本上,它只是做了一些事情,除了刷新读写内存操作的当前指令队列,以及在刷新完成之前停止处理读写内存的任何新指令 实际上,只要不修改内存,指令处理管道的各个部分都可以执行:解码、调度、地址计算、页面管理等,并且可以允许对寄存器进行任何读写,因此它没有完全刷新那么糟糕 至于他们是如何让它在硅中发生的。。。不知道。基本上,它只是做了一些事情,没有刷新任何读取或写入内存的操作的当前指令队列,并且在刷新完成之前停止处理任何读取或写入

我想知道cpu是如何使用“mfence”来保护顺序一致性的,谁能告诉我呢?

基本上,它只是做了一些事情,除了刷新读写内存操作的当前指令队列,以及在刷新完成之前停止处理读写内存的任何新指令

实际上,只要不修改内存,指令处理管道的各个部分都可以执行:解码、调度、地址计算、页面管理等,并且可以允许对寄存器进行任何读写,因此它没有完全刷新那么糟糕


至于他们是如何让它在硅中发生的。。。不知道。

基本上,它只是做了一些事情,没有刷新任何读取或写入内存的操作的当前指令队列,并且在刷新完成之前停止处理任何读取或写入内存的新指令

实际上,只要不修改内存,指令处理管道的各个部分都可以执行:解码、调度、地址计算、页面管理等,并且可以允许对寄存器进行任何读写,因此它没有完全刷新那么糟糕


至于他们是如何让它在硅中发生的。。。不知道。

对于对齐的加载和存储的顺序一致性,在x86上使用
mfence
指令跟踪每个存储就足够了。但是,没有必要这样做:更积极的方法只需要确保在每一对可能的存储指令和后续加载指令之间出现
mfence
指令。例如,一系列未被加载中断的存储指令不需要任何
mfence
,除非在最终存储之后

如果要以原子方式执行复合操作(如增加值),则需要的不仅仅是
mfence
——还需要一条锁定指令,如
lock inc
。这也意味着与
mfence
相同的屏障,因此在这种情况下不需要额外的屏障


在实践中,
mfence
可能不是执行顺序一致性的理想选择,即使是出于普通存储目的,因为其性能似乎比锁定操作差,因此,例如,可以使用
lock xchg
来代替它。

对于对齐负载和存储的顺序一致性,在x86上,用
mfence
指令跟踪每个存储就足够了。但是,没有必要这样做:更积极的方法只需要确保在每一对可能的存储指令和后续加载指令之间出现
mfence
指令。例如,一系列未被加载中断的存储指令不需要任何
mfence
,除非在最终存储之后

如果要以原子方式执行复合操作(如增加值),则需要的不仅仅是
mfence
——还需要一条锁定指令,如
lock inc
。这也意味着与
mfence
相同的屏障,因此在这种情况下不需要额外的屏障


实际上,
mfence
可能不是强制执行顺序一致性的理想选择,即使是出于普通存储的目的,因为它的性能似乎比锁定操作差,因此可以使用例如
lock xchg
来代替它。

不仅刷新指令队列,还刷新存储缓冲区(但这可能发生OoO)。看,和,和
mfence
不是在指令流上序列化,而是在内存操作上序列化,它确保存储已提交到L1d,而不仅仅是在指令流中本地执行。不仅刷新指令队列,还刷新存储缓冲区(但这可能会发生OoO)。看,和,和
mfence
不在指令流上序列化,只在内存操作上序列化,它确保存储已提交到L1d,而不仅仅在指令流中本地执行。
mfence
是存储加载重新排序的障碍。
mfence
是存储加载重新排序的障碍。不幸的是(?)gcc将C++11
atomic_var=1
编译为
mov-dword[atomic_var],1
/
mfence
,而不是
mov-eax,1
/
xchg[atomic_var],eax
。IDK如果编译器开发人员已经测试过,或者他们使用什么基准/微基准来决定这个代码生成策略。有了
-mno-sse
,它确实会使用
xchg
,我想。@PeterCordes-是的,我记得。我的评论可能应用于在C++原子化之前做这些事情的人,比如java,当操作本身不需要原子运算时,Java肯定使用了“虚拟锁定OP”方法。我也不知道gcc为什么会这样编译它。今天
mfence
实际上速度较慢,这可能是完全错误的:这些测试主要基于背靠背测试,可能是当代码越稀疏时速度越快(例如,UOP越小)。我把答案编辑成“可能不理想”,而不是“通常不使用”。不幸的是(?)gcc将C++11
atomic_var=1
编译成
mov-dword[atomic_var],1
/
mfence
,而不是
mov-eax,1
/
xchg[atomic_var],eax
。IDK如果编译器开发人员已经测试过,或者他们使用什么基准/微基准来决定这个代码生成策略。有了
-mno-sse
,它确实会使用
xchg
,我想。@PeterCordes-是的,我记得。我的评论可能应用于在C++原子化之前做这些事情的人,比如java,当操作本身不需要原子运算时,Java肯定使用了“虚拟锁定OP”方法。我也不知道gcc为什么会这样编译它。这可能是完全错误的,
mfence
实际上在今天变慢了:这些都是基于背靠背测试的,可能是当它看起来更稀疏的时候