【问题标题】:CPU Registers and Cache CoherenceCPU 寄存器和缓存一致性
【发布时间】:2010-12-30 03:42:02
【问题描述】:

当涉及到 MESI 等缓存一致性协议时,CPU 寄存器和 CPU 缓存之间有什么关系?如果某个值存储在 CPU 的缓存中,并且还存储在寄存器中,那么如果缓存行被标记为“脏”会发生什么?据我了解,即使缓存已更新(由于 MESI),也无法保证寄存器会更新其值。

验证这段代码:

 static void Main()  
  {  
  bool complete = false;   
  var t = new Thread (() =>  
  {  
    bool toggle = false;  
    while (!complete) toggle = !toggle;  
  });  
  t.Start();  
  Thread.Sleep (1000);  
  complete = true;  
  t.Join();        // Blocks indefinitely  
}

(假设编译器没有优化循环外的“完成”负载)
据我了解,第二个线程看不到“完成”的更新,因为它的值保存在寄存器中(但是 CPU 2 的缓存已更新)。

设置内存屏障是否会强制“刷新”所有寄存器?寄存器与缓存的关系是什么?那么寄存器和内存屏障呢?

【问题讨论】:

    标签: multithreading cpu-architecture lock-free cpu-cache


    【解决方案1】:

    x86 平台中使用的 MESI 协议保证了缓存的一致性,即一个 CPU 缓存中的更改会自动传播到其他 CPU 缓存。 因此,x86 和 x64 上的 volatile 关键字仅用于防止重新排序。

    【讨论】:

    • 多线程运行在多个内核上,volatile 不会让您免于重新排序;不同的核心将以不同的方式重新排序,并且在他们不知道彼此的重新排序选择的情况下,volatile 无法拯救您。在一个 CPU 上有多个线程时,volatile 将确保编译器始终获取变量的值,但我认为这与 不重新排序 不太一样。事实上,我怀疑它根本没有提供关于重新排序行为的任何迹象......
    • 这看起来像 C# 代码。 volatile 在 C# 中的含义与在 C/C++ 中的含义不同。我实际上认为这是 MS 为线程函数构建闭包的方式中的一个错误。由于 complete 被拉入闭包中,因此应该将其视为全局变量。如果 complete 是全局变量,我们会看到相同的结果(永远阻塞)吗?
    • volatile 还会停止缓存在 CPU 寄存器中的值
    【解决方案2】:

    没有关系。使用“volatile”关键字。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-31
      • 2021-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-17
      • 2014-02-03
      相关资源
      最近更新 更多