内存类型write-through Read-allocate详解
好的,我们来详细解析 AXI 协议中 Write-Through Read-Allocate 这一内存属性。这是一个非常实用且常见的缓存策略组合,旨在优化一种特定的数据访问模式。
核心结论先行
- 是什么:
Write-Through Read-Allocate是一种缓存策略。Write-Through指写入时同时更新缓存和主内存;Read-Allocate指仅在读未命中时,将数据从内存载入缓存。 - 目标: 针对 “读取频繁,写入后需立即共享” 的数据。它通过
Read-Allocate提升后续的读取性能,同时通过Write-Through保证写入的数据能立刻被系统其他主设备(如DMA)看到,维持强数据一致性。 - 本质: 为读取操作加速,为写入操作保序。是一种在一致性和读取性能之间取得平衡的策略。
深入解析:拆解概念
1. Write-Through (透写)
- 工作原理: 当 CPU 执行存储(写)操作时,如果数据在缓存中(缓存命中),则同时更新缓存行和主内存。
- 优点: 数据一致性极佳。缓存和主内存中的数据始终保持一致。任何其他总线主设备(如 DMA、另一个 CPU 核心)都能立即看到 CPU 写入的最新数据,无需等待缓存行被后期刷回。这对于多设备共享数据至关重要。
- 缺点: 写入性能开销大。每次写入都必须要完成相对缓慢的主内存访问,这限制了写入的吞吐量,消耗了更多总线带宽和功耗。
2. Read-Allocate (读分配)
- 工作原理: 这是一个关于缓存未命中(Cache Miss) 时行为的策略。
- 当发生读未命中时,数据从主内存读取后,会将其放入缓存中,以便后续快速读取。
- 当发生写未命中时,不会为要写入的数据在缓存中分配一个新的缓存行。
- 设计意图: 基于一个假设——数据更可能被读取,而不是被再次写入。因此,值得在第一次读取时将其缓存起来,为后续可能的多次读取提速。而对于写入,如果第一次都没缓存,那就不值得为它分配空间。
3. Write-Through Read-Allocate 的组合效应
让我们通过两个场景来看这个组合的行为:
场景一:CPU 读取数据(核心优化场景)
- CPU 读取地址 A,发生读未命中。
- Read-Allocate 策略生效: 系统从主内存读取数据,并分配一个缓存行,将数据载入缓存。
- 数据返回给 CPU。
- 后续: 当 CPU 再次读取地址 A 时,发生读命中,数据直接从高速缓存中返回,速度极快。
场景二:CPU 写入数据(一致性保障场景)
- 情况A:写命中。CPU 写入地址 B,且地址 B 已在缓存中(很可能是因为之前被读取过)。
- Write-Through 策略生效: 数据同时更新缓存行和主内存。
- 情况B:写未命中。CPU 写入地址 C,且地址 C 不在缓存中。
- Read-Allocate 的“另一面”生效(即No Write-Allocate): 不会为地址 C 分配缓存行。
- 数据直接写入主内存。
这个组合的最终效果是:
- 数据通过读操作被主动加载到缓存中。
- 一旦数据在缓存中,后续的读操作极快(命中)。
- 所有的写操作(无论命中与否)都直达主内存,保证强一致性。
- 缓存只会被那些至少被读过一次的数据占据,避免了被“只写一次”的数据污染。
为什么需要它?—— 应用场景
这种策略适用于典型的 “读多写少” 且需要 “写入立即可见” 的共享数据。
-
配置寄存器或内存中的状态标志:
- 特点: 一个设备驱动需要频繁读取某个状态寄存器或内存中的状态位(
read-heavy),以检查设备是否就绪。但写入操作相对较少,通常只在初始化时配置一次。而且,配置写入后必须立即对设备生效。 - 为什么用它:
Read-Allocate: 第一次读取状态后,该状态被缓存,后续成千上万次的检查状态循环速度极快,大幅提升驱动效率。Write-Through: 当 CPU 写入配置命令时,命令被立即写入设备寄存器,确保设备能及时收到并开始工作。CPU 写入状态标志时,也能立即被 DMA 控制器等其他主设备看到。
- 特点: 一个设备驱动需要频繁读取某个状态寄存器或内存中的状态位(
-
共享的任务队列或生产者-消费者缓冲区:
- 特点: 生产者(CPU核心1)将任务写入队列,消费者(CPU核心2)不断从队列中读取任务。消费者读取任务的频率远高于生产者放入任务的频率。
- 为什么用它:
Read-Allocate: 消费者核心第一次从队列头部读取任务后,该内存区域被缓存,后续的读取操作会非常快。Write-Through: 生产者核心放入新任务时,写入操作直达内存,确保消费者核心能立即看到新的任务,避免了因缓存未同步而导致的任务延迟处理。
-
只读数据的初始化:
- 特点: 程序启动时需要加载(写入)大量的常量数据到一片内存区域,之后这片区域在绝大部分时间里都被只读访问(例如存储程序代码、常量表)。
- 为什么用它:
- 初始化时的写入通过
Write-Through保证数据正确落盘。 - 后续的只读访问通过
Read-Allocate机制享受到缓存带来的加速好处。
- 初始化时的写入通过
在 AXI 协议中的表示
在 AXI 协议中,这是通过 ARCACHE 和 AWCACHE 信号实现的。
AxCACHE[1](Cacheable): 1 (表示是 Cacheable 的)AxCACHE[2](Read-Allocate): 1 (表示 Enable Read-Allocate)AxCACHE[3](Write-Allocate): 0 (表示 No Write-Allocate)AxCACHE[0](Bufferable): 通常为 0 (但对于 Write-Through,它有时可为1,取决于具体实现,核心是 RA=1, WA=0)
一个典型的 Write-Through Read-Allocate 配置是 AxCACHE = 4'b1010。
C=1: CacheableRA=1: Read-AllocateWA=0: No Write-AllocateB=0: Not Bufferable (强调写入完成必须得到内存确认)
对比总结
| 属性 | 读未命中行为 | 写未命中行为 | 写命中行为 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|---|---|
| Write-Through Read-Allocate | 分配缓存行 | 不分配,直写内存 | 更新缓存和内存 | 读性能好,数据强一致 | 写入带宽开销大 | 读多写少的共享数据(状态标志、队列) |
| Write-Back Read/Write-Allocate | 分配缓存行 | 分配缓存行,只写缓存 | 只更新缓存 | 读写性能均优 | 数据有暂不一致风险 | 处理器私有的频繁读写数据 |
| Write-Through No-Allocate | 不分配 | 不分配,直写内存 | 更新缓存和内存 | 避免缓存污染,强一致 | 所有访问都可能慢 | 写入后共享且不再读的数据(帧缓冲) |
| Non-cacheable | (不适用) | 直写内存 | (不适用) | 强一致,简单 | 所有访问都慢 | 严格共享的设备寄存器 |
总结
Write-Through Read-Allocate 是一种非常精巧的缓存策略,它并非追求极致的写入性能,而是在保证数据强一致性的前提下,最大化读取操作的性能。
- 它的设计哲学: “为读而存,写则直达”。数据值得被缓存的前提是它被读取过;而所有写入都必须立即全局可见,不能打折扣。
- 它的核心价值: 完美解决了多设备共享环境中,对读性能有高要求、对写一致性有严要求的平衡问题。
- 它的应用标志: 当你处理的数据访问模式是 “频繁读取,偶尔写入” 并且写入后的结果需要被其他系统组件立即看到时,这个属性就是理想的选择。
浙公网安备 33010602011771号