Assembly 内存屏障是否确保缓存一致性已完成?
假设我有两个线程操作全局变量Assembly 内存屏障是否确保缓存一致性已完成?,assembly,x86,operating-system,cpu-cache,memory-barriers,Assembly,X86,Operating System,Cpu Cache,Memory Barriers,假设我有两个线程操作全局变量x。每个线程(或者我想每个核心)都有一个x的缓存副本 现在假设线程A执行以下指令: set x to 5 some other instruction 现在,当执行将x设置为5时,x的缓存值将设置为5,这将导致缓存一致性协议动作,并使用新值x更新其他核心的缓存 现在我的问题是:当线程A的缓存中x实际设置为5时,其他内核的缓存是否会在执行其他指令之前更新?或者应该使用内存屏障来确保: set x to 5 memory barrier some other instr
x
。每个线程(或者我想每个核心)都有一个x
的缓存副本
现在假设线程A执行以下指令:
set x to 5
some other instruction
现在,当执行将x设置为5
时,x
的缓存值将设置为5
,这将导致缓存一致性协议动作,并使用新值x
更新其他核心的缓存
现在我的问题是:当线程A
的缓存中x
实际设置为5
时,其他内核的缓存是否会在执行其他指令之前更新?或者应该使用内存屏障来确保:
set x to 5
memory barrier
some other instruction
注意:假设指令是按顺序执行的,也假设在执行将x设置为5
时,5
立即被放入线程A的缓存中(因此指令没有放入队列或稍后要执行的内容)
现在,当执行set x to 5时,缓存的x值将被设置为
5,这将导致缓存一致性协议起作用并更新
新值为x的其他内核的缓存
有多个具有不同缓存一致性协议(无、MESI、MOESI)的不同x86 CPU,以及不同类型的缓存(未缓存、写组合、仅写、直写、回写)
一般来说,当写操作完成时(将x设置为5),CPU会确定正在完成的缓存类型(从MTRRs或TLB),如果缓存线可以缓存,它会检查自己的缓存以确定缓存线处于何种状态(从自己的角度)
然后,缓存的类型和缓存线的状态用于确定数据是否直接写入物理地址空间(绕过缓存),或者它是否必须从其他位置获取缓存线,同时通知其他CPU使旧副本无效,或者,如果它在自己的缓存中具有独占访问权限,并且可以在缓存中修改它,而无需告诉任何事情
CPU从不将数据“注入”到另一个CPU的缓存中(并且只告诉其他CPU使缓存线的副本无效/丢弃)。告诉其他CPU使缓存线的副本无效/放弃会导致它们在需要时获取缓存线的当前副本
请注意,这些都与记忆障碍无关
有三种类型的内存屏障(sfence
、lfence
和mfence
),它们告诉CPU在允许以后的存储、加载或两者发生之前完成存储、加载或两者。因为CPU通常是缓存一致的,所以这些内存屏障/围栏通常是无意义/不必要的。但是,也存在CPU缓存不一致的情况(包括“存储转发”、使用写组合缓存类型、使用非时态存储等)。对于这些特殊/罕见的情况,需要使用内存屏障/围栏来强制订购(如有必要)。x86体系结构上存在的内存屏障-但这通常是正确的-不仅保证所有以前的1加载或存储,在执行任何后续加载或存储之前完成-它们还保证存储已成为全局可见的
全局可见意味着其他缓存感知代理(如其他CPU)可以看到存储。
如果目标内存被标记为不强制立即写入内存的缓存类型,则其他不知道缓存的代理(如支持DMA的设备)通常不会看到存储。
这与它本身的障碍无关,这是x86体系结构的一个简单事实:缓存对程序员是可见的,在处理硬件时,它们通常是禁用的
英特尔有意对这些障碍进行泛化描述,因为它不想将自己与特定的实现捆绑在一起。
您需要抽象地思考:全局可见意味着硬件将采取所有必要的步骤使存储全局可见。句号
然而,要了解这些障碍,有必要看看当前的实施情况。
请注意,只要保持可见行为正确,英特尔可以随意将现代实现的上下颠倒
x86 CPU中的存储在内核中执行,然后放入存储缓冲区。
例如,mov-DWORD[eax+ebx*2+4],ecx
,一旦解码被暂停,直到eax
,ebx
和ecx
已就绪,然后它被分派到能够计算其地址的执行单元。
执行完成后,存储已成为一对(地址、值),并移动到存储缓冲区中。
据说这家商店是在当地(核心)建成的
存储缓冲区允许CPU的OOO部分忘记存储,并考虑即使在尚未写入的情况下也完成了。p>
在发生特定事件时,如序列化事件、异常、执行屏障或耗尽缓冲区,CPU将刷新存储缓冲区。
刷新总是有序的-先入先写
从存储缓冲区,存储进入缓存领域。
如果目标地址标记为WC缓存类型,则可以将其组合到另一个称为写组合缓冲区的缓冲区中(随后通过传递缓存写入内存),如果缓存类型为WB或WT,则可以将其写入L1D缓存、L2、L3或LLC中(如果不是之前的缓存类型之一)。
如果缓存类型为UC或WT,它也可以直接写入内存
就像今天一样,全球可见意味着:离开存储缓冲区。
注意两个非常重要的问题
Memory ordering -- enforces --> Global visibility -- needs -> Cache coherency
'.______________________________'_____________.' '
Architectural ' '
'._______________________________________.'
micro-architectural