写策略与一致性:写直达与写回,写分配与写不分配

好,咱们今天聊聊缓存写策略。这个话题,说白了就是CPU往缓存里写数据时,到底该怎么处理。你想想看,缓存是快的,内存是慢的,那数据写进去之后,两边不一致了怎么办?这就是一致性问题。

我在项目里见过不少同学,一上来就纠结选哪个策略。其实没那么玄乎。我们先搞清楚两个维度:写命中时怎么做,和写未命中时怎么做。

写命中策略:写直达 vs 写回

先看写命中的情况。也就是你要写的数据,已经在缓存里了。这时候有两种选择。

写直达(Write-Through)

写直达,顾名思义,就是数据同时写入缓存和下一级存储(比如内存)。

  • 优点:实现简单,缓存和内存永远一致。你不用担心数据丢失。
  • 缺点:慢。每次写操作都要等内存写完,写操作的延迟被拉长了。

我记得有一次做视频编解码芯片的优化,发现写直达导致整个流水线经常卡住。为什么呢?因为编码器写数据太频繁了,每次都要等内存,带宽根本扛不住。

核心要点:写直达适合写操作少、对一致性要求极高的场景。比如一些控制寄存器的更新。

写回(Write-Back)

写回就聪明多了。数据只写到缓存里,标记为“脏”(dirty)。等缓存行被替换出去时,才真正写回内存。

  • 优点:快。写操作只到缓存就结束了,延迟极低。
  • 缺点:实现复杂。需要维护脏位,还要处理一致性协议。

我建议,大部分通用计算场景,用写回就对了。你想想看,CPU写数据通常有局部性,写了一次可能马上又写第二次。写回能把这些写操作攒起来,一次刷回内存,效率高得多。

个人经验:我在做AI推理芯片时,矩阵乘法的中间结果全部用写回。因为数据量大,写操作密集,写直达的话带宽直接爆炸。

写未命中策略:写分配 vs 写不分配

好,现在看另一种情况。你要写的数据,缓存里没有。这时候怎么办?

写分配(Write-Allocate)

先把数据从内存加载到缓存,然后再写缓存。说白了,就是“先加载,再写”。

  • 通常搭配写回使用。因为既然都加载进来了,后面可能还会写,用写回更划算。
  • 优点:后续的写操作都能命中缓存,性能好。
  • 缺点:第一次写未命中时,需要读内存,延迟较高。

写不分配(No-Write-Allocate)

不加载到缓存,直接写到下一级存储。缓存里还是没这个数据。

  • 通常搭配写直达使用。反正每次都要写内存,何必多一步加载呢?
  • 优点:避免缓存被污染。如果这个数据只写一次,以后再也不用了,那加载进来就是浪费。
  • 缺点:后续再读这个数据,还是缓存未命中。
避坑指南:我曾经在一个流媒体处理项目里,默认用了写分配+写回。结果发现大量数据是“写一次就不再读”的,比如视频帧的元数据。缓存被这些一次性数据塞满了,反而把热点数据挤出去了。后来改成写不分配+写直达,性能反而提升了。

四种组合,一张表说清楚

写命中策略 写未命中策略 典型场景 我的建议
写直达 写不分配 控制寄存器、状态标志 简单场景首选
写直达 写分配 极少用,性能差 别这么配
写回 写分配 通用计算、AI推理 大部分情况选这个
写回 写不分配 流式数据、一次性写入 特殊优化场景

嗯,这里要注意。写直达+写分配这个组合,基本没人用。为什么呢?你想想看,写未命中时加载数据到缓存,然后写直达又把数据刷回内存。缓存白加载了,还多了一次读内存的开销。纯属浪费。

核心逻辑图:写策略决策树

下面这张图,是我自己画的一个决策流程。你写代码或者配硬件时,可以照着这个思路走。

写策略决策流程 写操作发生 是否命中缓存? 是 写直达还是写回? 写直达:写缓存+内存 写回:只写缓存,标记脏 否 写分配还是不分配? 写分配:加载到缓存再写 写不分配:直接写内存 常见组合 写回 + 写分配:通用场景首选 写直达 + 写不分配:简单控制场景

实际项目中的选择建议

我个人习惯,拿到一个算子映射任务时,先问自己三个问题:

  1. 这个数据写完之后,还会再读吗? 如果会,用写分配+写回。如果不会,考虑写不分配。
  2. 写操作的频率高吗? 频率高,用写回。频率低,写直达也可以接受。
  3. 一致性要求有多严格? 如果其他核或设备需要立即看到最新数据,写直达更安全。
一个小技巧:很多现代处理器其实支持按页配置写策略。你可以在页表里设置某个内存页是写直达还是写回。这样同一个程序里,不同数据可以用不同策略。

嗯,最后说一句。写策略没有绝对的好坏,关键看你的数据访问模式。我见过有人把写回用在一堆只写一次的数据上,结果缓存污染严重,性能反而下降。也见过有人死守写直达,结果带宽被打满,整个系统卡成PPT。

理解你的数据,比死记硬背策略更重要。

一句话总结:写回+写分配是万金油,写直达+写不分配是轻量级选择。具体用哪个,看你的数据是“反复写”还是“写一次就扔”。

想要更多资料,联系可可