You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MOESI一致性协议下,CPU1加载时CPU0存储缓冲区是否会刷新?

问题描述

考虑以下代码:

std::atomic<int> a = 100;
---
CPU 0:
a.store(101, std::memory_order_relaxed);
---
CPU 1:
int tmp = a.load(std::memory_order_relaxed);  // 假设`tmp`为101。

假设CPU0对a的存储操作在时间上早于CPU1对a的加载操作,此时tmp的值为101。

若采用MOESI一致性协议,CPU0存储a时会以修改(M)模式获取缓存行,该操作进入CPU0的存储缓冲区;若CPU1缓存中存在该行,其副本会转为无效(I)模式。

当CPU1加载a时,缓存行会转为共享(S)模式或拥有(O)模式。

假设CPU1加载a时,a仍在CPU0的存储缓冲区中。 由于CPU1无法读取CPU0的存储缓冲区,那么当CPU1读取a所在缓存行时,是否意味着CPU0的存储缓冲区(至少包含a的缓存行)被刷新?

若未发生刷新,则会出现CPU0与CPU1同时以共享(S)模式持有该缓存行,但CPU0看到a的值为101、CPU1看到a的值为100的不一致情况。

注:本文针对MOESI协议提问,尽管各微架构实现的一致性协议不同,但此类问题的处理逻辑大致相似。

解答

是的,CPU1读取a所在缓存行时,会触发CPU0存储缓冲区中对应缓存行的刷新,具体逻辑如下:

  • 总线事务触发同步:当CPU1发起读请求时,会在系统总线上广播该请求。CPU0的缓存控制器会监测到这个请求——因为它已将目标缓存行标记为M(修改)模式(即使存储操作还在缓冲区中,缓存行的权限状态已提前更新为M)。
  • 缓冲区冲刷与数据提交:CPU0必须响应这个读请求,首先将存储缓冲区中针对该缓存行的未完成存储操作冲刷到缓存中,然后把更新后的缓存行数据通过总线发送给CPU1。同时,CPU0的缓存行权限会从M转为O(拥有)或S(共享),CPU1的缓存行则被设置为S模式。
  • 一致性保障:这种机制是MOESI协议维护缓存一致性的核心,避免了你提到的“双CPU持S模式但数据不一致”的情况——缓存一致性协议的基本要求就是所有CPU看到的内存状态最终一致,且外部读请求必须获取到最新的已提交值。

另外需要说明:std::memory_order_relaxed仅保证操作的原子性,不强制内存顺序,但缓存一致性协议本身会确保当一个存储操作对其他CPU可见时,必然是已提交的最新值——这里的可见性触发点就是CPU1的读请求引发的总线事务,强制CPU0完成未提交的存储。

内容的提问来源于stack exchange,提问作者Jack Humphries

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:40:15