MFENCE / SFENCE / etc"序列化内存但不执行指令执行"?

时间:2014-10-31 20:42:39

标签: assembly x86

英特尔系统编程指南的第8.3节,阐述了关于MFENCE / SFENCE / LFENCE:

“以下指令是内存排序指令,而不是序列化指令。这些指令会耗尽数据存储器子系统。它们不会序列化指令执行流。

我想弄清楚为什么这很重要。在多线程代码中,对内存的写入/读取正是需要以明确定义的顺序发生的事情。当然,I / O发生的顺序可能很重要,但I / O指令仍然是“序列化指令”。 CPU应该可以重新排序指令(例如)在寄存器中进行算术运算;我认为你没有任何理由想要“序列化”这样的行动。

是否真的需要完全序列化指令,而MFENCE仅对加载和存储进行序列化是“不够”?

2 个答案:

答案 0 :(得分:3)

  

是否真的需要完全序列化指令,而且只有加载和存储的MFENCE序列化是不够的"?

基准测试和代码分析。

如果您正在尝试衡量代码序列的性能,特别是如果代码序列非常短,那么确保部分基准操作不会在代码序列之外执行是非常重要的。定时序列。例如,如果您的代码看起来像这个伪代码:

start = RDTSC()
do some stuff
end = RDTSC()
cycles = end - start

确保中间的所有代码都不会在第一个RDTSC之前或第二个之后执行,这一点非常重要。

令人高兴的是,有一个完美的指令:CPUID完全序列化。

答案 1 :(得分:1)

英特尔手册的第8.3节包含被视为已完全序列化的指令的完整列表(另请参见:How many memory barriers instructions does an x86 CPU have?):

  
      
  • 特权序列化指令-INVD,INVEPT,INVLPG,INVVPID,LGDT,LIDT,LLDT,LTR,MOV(通过   MOV CR8 3),MOV(用于调试寄存器),WBINVD和WRMSR除外   4。

  •   
  • 非特权序列化指令-CPUID,IRET和RSM。

  •   

我认为除CPUID以外的所有这些指令都是序列化的,因为指令的语义要求它必须像这样。例如,如果WBINV没有进行序列化,那么它可能会与其他访问内存的较早或更晚的操作进行重新排序,并且当指令退出时,还不清楚缓存层次结构的状态。

CPUID指令最初是在奔腾处理器中引入的,奔腾处理器是一种推测性的顺序处理器。该指令的一种典型用法是检查当前处理器是否支持特定功能,然后跳转到使用该功能的一段代码(如果受支持)(例如执行一条指令)。我不确定如果CPUID尚未序列化会引起什么复杂性。例如,如果用于检查处理器是否支持某些特定指令,并且分支预测器错误地预测出采用了包含该指令的路径,则解码器会将其视为无效指令。可以使用与分支错误预测和无效指令相同的机制来处理这种情况。

RDTSC指令也是最早在奔腾处理器中引入的。但是,在Pentium软件开发人员手册中的任何地方都没有提到您需要对RDTSC使用序列化指令。这是有道理的,因为处理器是有序的且为2宽,因此RDTSC只能与在它之前或之后的一条指令重叠。在Pentium Pro手册中,确实提到由于执行顺序混乱而需要使用序列化指令。这里重要的一点是,CPUID甚至在我们不需要RDTSC的处理器上进行序列化。这意味着CPUID进行序列化的最初原因是其他原因。奔腾手册确实提到了两种需要使用序列化指令的情况。

  

15.4。 I / O的订购

     

因此,使用内存映射的I / O可能会导致   I / O读取可能在之前的存储器写入之前执行   指令。要消除Intel486 CPU上的这种可能性,请使用   读取的I / O指令。为了消除这种可能性   奔腾处理器,插入序列化指令之一,例如   CPUID,在两次操作之间。

     

18.2.3。自我修改代码

     

因为要根据线性检查写入的线性地址   预取说明的地址,请特别注意   必须采取自我修改的代码才能在   指令的物理地址和写入的数据是   相同,但线性地址不同。在这种情况下,有必要   在写入之后和之前执行序列化操作   执行修改后的指令。

CPUID以外的所有序列化指令均不适合用于通用序列化,因为它们要么具有特权,否则可能会严重影响性能,更改程序的控制流或更改段描述符表。 CPUID也不完美,因为它会更改某些体系结构寄存器的值。因此,我认为英特尔可以选择引入一种新的通用序列化指令,该指令除了对管道进行序列化外什么也不做,或者使CPUID成为序列化指令。也可能是CPUID本身出于某种原因需要序列化的情况。无论哪种方式,似乎他们都决定让CPUID扮演通用串行化指令的角色。考虑到CPUID修改四个寄存器这一事实与串行化的影响相比,对性能的影响可以忽略不计。

稍后,在奔腾Pro处理器中,英特尔建议在手册中将CPUIDRDTSC结合使用以进行准确的测量(请参阅:Get CPU cycle count?)。