作者:mobiledu2502886131 | 来源:互联网 | 2022-12-17 18:35
在x86上,除了原子操作之外,还提供了lock
诸如lock cmpxchg
提供屏障语义之类的前缀指令:对于回写内存区域的正常内存访问,读取和写入不是lock
按照第3卷第8.2.2节中的预定指令重新排序的英特尔SDM:
无法使用I/O指令,锁定指令或序列化指令对读取或写入进行重新排序.
本节仅适用于回写内存类型.在同一个列表中,您会发现一个例外情况,它指出没有订购弱排序的商店:
读取不会与其他读取重新排序.
写入不会与较旧的读取重新排序.
写入内存不会与其他写入重新排序,但以下情况除外: -
使用非时间移动指令(MOVNTI,MOVNTQ,MOVNTDQ,MOVNTPS和MOVNTPD)执行的流存储(写入); 而且 -
字符串操作(参见第8.2.4.1节).
注意,列表中的任何其他项目中的非时间指令没有例外,例如,在涉及锁定前缀指令的项目中.
在本指南的各种其他部分中,提到当使用弱有序(非时间)指令时,mfence
和/或sfence
指令可用于命令存储器.这些部分通常不提及lock
- 作为替代的前缀指令.
所有这一切都让我不确定:do lock
-prefixed指令提供了相同的完整屏障,它mfence
提供了WB内存上的弱有序(非时间)指令之间的?同样的问题再次适用于WC内存的任何类型的访问.
1> Hadi Brais..:
锁定前缀的指令比英特尔强大mfence
.AMD64 mfence
是完全序列化的指令,因此它比Lock-prefixed指令更强大.还有32位x86 AMD处理器支持mfence
,我希望它的行为与AMD64相同.本答案的其余部分仅适用于英特尔mfence
.
的mfence
紧接之前或之后的锁定前缀指令是多余的.从第8.2.5节:
I/O指令,锁定指令,LOCK前缀和序列化指令强制处理器的排序更强.
(此处的锁定指令是指具有隐式的指令lock
.在本手册的其他地方,它们也引用了lock
明确前缀的指令.)
这里"更强"意味着比第8.2.2节(问题中引用)中讨论的默认排序更强.也是从8.2.5:
与I/O和锁定指令一样,处理器等待所有先前的指令完成,并且在执行序列化指令之前已将所有缓冲的写入耗尽到存储器.
第8.3节讨论了序列化指令,它根本没有提到锁定前缀.但它说:
以下说明是内存排序说明,而不是序列化说明.这些耗尽了数据存储器子系统.它们不会序列化指令执行流:
•非特权内存排序指令 - SFENCE,LFENCE和MFENCE.
值得注意的是,锁定前缀不会像第8.3节中列出的那样进行序列化指令.主要区别在于锁定前缀允许获取以下指令.另外,关于软件预取指令不订购锁定前缀指令.从英特尔手册V2:
PREFETCHh指令被认为是对这种推测行为的暗示.因为这种推测性提取可以在任何时间发生并且不依赖于指令执行,所以不对栅栏指令(MFENCE,SFENCE和LFENCE)或锁定存储器引用排序PREFETCHh指令.对于CLFLUSH和CLFLUSHOPT指令,其他PREFETCHh指令或任何其他通用指令,PREFETCHh指令也是无序的.它是针对序列化指令(如CPUID,WRMSR,OUT和MOV CR)进行排序的.
这同样适用于所有软件预取指令,而不仅仅是PREFETCHh
.
是什么使得锁前缀比mfence
它不仅提供所有指令(软件预取除外)的序列化更强大,而且还锁定对共享内存的访问,以便所有其他逻辑处理器在退出之前无法访问内存,从而提供原子性.
现在我已经看到了Necrolis的回答中的引用,该引用表明锁定前缀可能不会序列化引用弱有序内存类型的加载操作.但我认为这个陈述非常陈旧,并且在英特尔不想公开锁定前缀的完整保证的时候为非常老的处理器编写.此外,引用只说"可能没有",这并不是真正的矛盾.
这也可以从AMD手册V2 7.4.2中确认:
在发出I/O,锁定或序列化指令的存储器访问之前,所有先前的加载和存储都完成到存储器或I/O空间.
在发出后续指令的加载或存储之前,与I/O和锁定指令相关联的所有加载和存储都完成到存储器(无缓冲存储).
@ PeterCordes的实验表明,在Skylake上,锁定指令似乎不会阻止ALU指令在无序执行的同时MFENCE
串行化ALU指令(可能与mfence
存储缓冲区刷新的行为相同,就像锁定指令一样).
好吧,我并没有发现实施较弱的问题,实际上是:英特尔为其未来的优化和/或其ISA文档中的不同实现打开了一扇大门.没有太多的缺点:对于较弱的保证,可以使用较弱的指令的人,即使他们最终有更强的行为,他们至少与其他指令的保证强的行为"联系在一起" .