Assembly 内核如何决定在MESI中使哪个缓存线失效?

Assembly 内核如何决定在MESI中使哪个缓存线失效?,assembly,x86-64,cpu-architecture,cpu-cache,Assembly,X86 64,Cpu Architecture,Cpu Cache,我对缓存线有一些误解。我正在使用Haswell和Ubuntu。现在让我们假设我们有两个线程的应用程序,其中发生了以下情况 mov [addr], dword 0xAC763F ;starting Thread 1 and Thread 2 现在让我们假设线程并行执行以下操作: Thread 1 Thread 2 mov rax, [addr] mov rax, [addr] mov [addr], dword 1

我对缓存线有一些误解。我正在使用
Haswell
Ubuntu
。现在让我们假设我们有两个线程的应用程序,其中发生了以下情况

mov [addr], dword 0xAC763F
;starting Thread 1 and Thread 2
现在让我们假设线程并行执行以下操作:

Thread 1                        Thread 2
mov rax, [addr]              mov rax, [addr]
mov [addr], dword 1     mov [addr], dword 2
现在我对发生的事情的理解是:

  • 在启动之前,主线程会写入相应的缓存线(
    addr
    ),并将其标记为
    独占
  • 如果两个线程
    Thread 1
    Thread 2
    在开始写入之前都已完成读取,则缓存线在所有缓存中都具有状态
    Shared
  • 现在,如果
    线程1
    中的
    mov[addr]、dword 1
    线程2
    中的
    mov[addr]、dword 2
    同时发生,我不明白哪个缓存行被标记为
    无效

    首先,“同时”感觉有点模糊。我认为这是“在相同的CPU时钟周期内”。
    MESI
    protocolimplementation如何解决“从不同线程同时写入”的问题

    我认为这是“在相同的CPU时钟周期内”

    不同的内核可以使用不同的时钟;e、 g.一个磁芯的频率为4GHz,而另一个磁芯的频率为800MHz。(不过,仅适用于Haswell Xeon;双核/四核部件的所有内核都在一个时钟域中。我已经读到了这一点,它与在一个内核忙时查看空闲内核上的CPU频率相匹配。)

    相关:这是一个非常相似的问题。(但这个问题的执行官不知道梅西是什么)。尽管如此,我还是对发送RFO请求进行了更详细的介绍,所以如果这个答案太简洁的话,也许可以阅读一下

    在启动之前,主线程写入相应的缓存线(addr)并将其标记为独占

    核心必须先使缓存线处于独占状态,然后才能对其进行修改。实际上,向L1D提交写操作会将其从独占翻转到修改,而不与其他内核通信。(L1D和L2是回写缓存)

    但是,是的,如果两个内核都在写入缓存线之前读取缓存线,那么它们都将使缓存线处于共享状态。只有在收到对该行RFO请求的成功回复后,他们才能将该行翻转为独占。有状态转换图和RFO的定义


    冲突的RFO请求当然有可能立即生效。到达另一个核心需要很多周期,因此,在收到RFO之前,不同核心上的存储都有足够的时间启动RFO。(这并不是说会阻止核心发送自己的RFO;写入无效的共享行需要RFO才能使其进入独占状态,以便存储可以提交。)

    我不能100%确定哪一个请求会在三级缓存中决定。但是

    Haswell的L3是包容性的,用作一致性流量的后盾/过滤器。L3不是将所有请求实际广播到所有内核,而是使用包含额外信息的标记来跟踪哪些内核(可能)具有哪一行的副本。L1和L2是每个核心的专用缓存,因此L3是第一个共享级别的缓存

    我猜L3会首先处理哪个core的RFO完成的仲裁,因为它已经在跟踪哪些core(可能)需要查看哪些RFO。这大概是在保存相关物理地址的L3片中完成的

    ,MESI是围绕总线拓扑设计的,而不是一个更复杂的消息路由网络。英特尔的设计具有相同的状态,但实际上不必像通常的CPU体系结构描述所说的那样简单

    因此,我们可以肯定地说:通过一些未知的内部机制,CPU决定一个RFO是第一个。当第一个仍在执行往返时到达的后一个可能会被取消(因此内核必须稍后重试),或者它可能会被缓冲

    我们知道Intel CPU有一种硬件仲裁机制,用于竞争原子RMW操作,如
    lock add[mem],eax
    。想必,仲裁对同一行的多个只写访问的机制是完全相同的,因为唯一的区别是
    lock
    ed操作在操作期间保持该行,而在操作期间不响应invalidate请求


    您可以谈论多个RFO请求在L3使用的“uncore”时钟的同一时钟周期内到达L3的同一片。

    这在哈斯韦尔的实践中可能是可行的;(每路32字节宽),因此每个(未加密)时钟周期可以有两条消息到达三级缓存的任何给定片。此外,L3的每个片都连接到一个核心,因此来自该核心的请求也可以同时到达


    在这种情况下,它可能很简单:如果一个片甚至可以在同一个周期内接收到多条发送给它的消息(而不仅仅是通过环),那么它可能是硬连接的,因此该片的三个源中的一个总是赢。

    在总线上(MESI开发的拓扑结构),没有“同时”所有的访问都是串行的,如果两个核心想同时访问总线,一个称为总线仲裁器的组件会让两个核心中的一个有权首先访问。请注意,Haswell是一个不好的例子,因为据我所知,它没有总线拓扑,使用MESIF而不是MESI。@fuz谢谢你的回答。我可以问你是否有一个工具来跟踪一致性流量吗?我们可以使用.use.perf来实现吗?如果是这样的话,我应该获得哪种类型的事件计数器?我认为您可以查看各种RFO计数器以了解情况。根据cpu型号的不同,I/S/E状态计数器中也可能有二级缓存线。没有要写入缓存线的总线事务,但有cer