高速缓存一致性操作期间处理器是否停顿

Tri*_*tos 3 multithreading caching cpu-architecture cpu-cache

假设变量a = 0

Processor1: a = 1
Processor2: print(a)
Run Code Online (Sandbox Code Playgroud)

Processor1首先执行它的指令,然后在下一个周期中,processor2读取变量以打印它。因此:

  1. Processor2将暂停,直到高速缓存一致性操作完成,它将打印1

    P1:   |--a=1--|---cache--coherence---|----------------
    P2:   ------|stalls due to coherence-|--print(a=1)---|
    time: ----------------------------------------------->
    
    Run Code Online (Sandbox Code Playgroud)
  2. 高速缓存一致性操作完成之前,processor2将运行,并且在此之前它将具有陈旧的内存视图。因此它将打印0?

    P1:   |--a=1--|---cache--coherence---|
    P2:   ----------|---print(a=0)---|----
    time: ------------------------------->
    
    Run Code Online (Sandbox Code Playgroud)

    换句话说,在高速缓存一致性操作完成之前,处理器可以拥有过时的内存视图吗?

Pet*_*des 5

所有现代ISA都使用MESI(的一种)进行高速缓存一致性。这在所有处理器拥有的内存共享视图(通过缓存)中始终保持一致性。

例如参见例如我可以在多核x86 CPU上强制缓存一致性吗? 一个常见的误解是,存储进入缓存,而其他内核仍具有缓存行的旧副本,然后必须发生“缓存一致性”。

但是事实并非如此:要修改高速缓存行,CPU需要对该行具有独占所有权(MESI的“已修改”或“互斥”状态)。仅在收到对“读取所有权”的响应(如果该响应以前使该缓存行处于共享或无效状态)之后,才有可能这样做。请参阅其他线程是否总是以相同的顺序看到两次对不同线程中不同位置的原子写入?例如。


但是,内存模型允许对存储和加载进行本地重新排序。顺序一致性太慢,因此CPU始终至少允许StoreLoad重新排序。另请参阅mov + mfence在NUMA上安全吗?有关x86上使用的TSO(总存储订单)内存模型的许多详细信息。许多其他的ISA使用甚至更弱的模型。

对于这种情况下的非同步读取器,如果两者都在单独的内核上运行,则有三种可能性

  • load(a)发生在缓存行无效之前在core#2上发生,因此它读取旧值,从而有效地a=1以全局顺序在存储之前发生。 负载可以达到L1d缓存
  • load(a)发生在core#1将存储提交到其L1d缓存后,尚未回写。Core#2的读取请求触发Core#2写回以共享共享级别的缓存(例如L3),并将该行置于Shared状态。 负载肯定会在L1d中丢失
  • load(a)发生在写回存储器之后,或者至少已经发生了L3,因此不必等待core#1写回。 除非硬件预取由于某种原因将其重新加载,否则L1d中的负载将丢失。但是通常这仅是顺序访问(例如,对数组)的一部分发生的。

因此,是的,如果另一个内核已在该内核尝试加载之前将其提交给缓存,则加载将停止。

另请参阅Intel硬件上的存储缓冲区大小?什么是存储缓冲区?有关存储缓冲区对所有事物的影响的更多信息,包括内存重新排序。

这里没关系,因为您有一个只写的生产者和一个只读的使用者。生产者核心无需等待其商店在全球范围内可见就可以继续操作,它可以在全局可见之前立即看到自己的商店。它确实当你有每个线程看着被其他线程中完成的商店关系; 那么您需要障碍或顺序一致的原子操作(编译器使用障碍来实现)。 参见https://preshing.com/20120515/memory-reordering-caught-in-the-act

另请参见 num ++是否对于'int num'是原子的?原子RMW如何与MESI配合使用,这对于理解该概念很有帮助。(例如,原子RMW可以通过使内核挂接到处于“修改”状态的高速缓存行并延迟对RFO的响应或请求共享它直到RMW的写入部分已提交而起作用。)


归档时间:

查看次数:

183 次

最近记录:

6 年,5 月 前