4. 缓存替换策略:LRU、LFU、随机替换、AI工作负载下的替换策略选择

缓存替换策略,说白了就是当缓存满了,新数据要进来,到底把谁踢出去的问题。

我刚开始做AI芯片那会儿,觉得这玩意儿不就是个算法题嘛。后来在项目里被坑过几次,才明白——选错替换策略,性能能差出好几倍。尤其是跑Transformer模型的时候,那叫一个酸爽。

今天咱们就把几种主流策略掰开揉碎,看看它们各自适合什么场景。

4.1 经典替换策略回顾

4.1.1 LRU(最近最少使用)

LRU的思路很直观:把最久没被访问的数据踢出去。它假设「过去被频繁访问的数据,未来大概率还会被访问」。

实现方式一般是链表+哈希表。每次访问数据,就把它挪到链表头部。淘汰时,直接干掉链表尾部的数据。

// 伪代码示例:LRU的访问逻辑
void access(Key key) {
    if (cache.contains(key)) {
        // 命中:把节点移到链表头部
        list.moveToHead(key);
    } else {
        if (cache.isFull()) {
            // 淘汰链表尾部节点
            Key victim = list.removeTail();
            cache.remove(victim);
        }
        // 新节点插入头部
        list.addToHead(key);
        cache.add(key);
    }
}

我的经验:LRU在通用计算场景表现不错,但在AI推理中,如果模型权重是顺序访问的,LRU反而会频繁换入换出,性能并不好。

4.1.2 LFU(最不经常使用)

LFU看的是访问频率。它记录每个数据被访问的次数,淘汰时选次数最少的那个。

听起来比LRU更合理对吧?但有个坑——频率老化问题。一个数据早期被频繁访问,后来再也没人用,它的计数却一直很高,占着茅坑不拉屎。

我见过一个项目,用LFU做指令缓存,结果某个初始化函数跑完后,它的指令一直赖在缓存里不走,后面真正热的数据反而进不来。

避坑指南:纯LFU不适合AI工作负载。我曾经在某个NPU项目里试过,效果惨不忍睹。后来加了衰减因子才勉强能用。

4.1.3 随机替换

随机替换,顾名思义——随机选一个倒霉蛋踢出去。

你可能会想:「这也太随意了吧?」

但说实话,在某些场景下,随机替换的效果并不差。它的优点是实现简单、硬件开销极低。对于某些访问模式高度随机的AI负载,随机替换甚至能跟LRU打个平手。

策略 硬件开销 命中率 适用场景
LRU 高(需要维护访问顺序) 较高 通用计算、有局部性规律
LFU 高(需要维护访问计数) 中等 访问频率差异明显的场景
随机替换 极低 中等 硬件资源紧张、访问模式随机

4.2 AI工作负载的特殊性

AI芯片的缓存访问模式,跟CPU那套完全不一样。我总结了几点:

  • 流式访问为主:权重和激活值通常是顺序读取的,很少有随机访问
  • 数据复用模式固定:卷积的权重复用、Transformer的KV Cache,复用模式是确定的
  • 对延迟极度敏感:推理场景下,缓存miss一次可能要多等几十个cycle

这就导致了一个问题:传统替换策略在AI芯片上水土不服。

举个例子,跑YOLO推理时,权重是按层顺序加载的。如果用LRU,每层的新权重会把上一层刚用完的权重挤出去——但上一层的数据其实再也不会被访问了。LRU还在那儿辛辛苦苦维护访问顺序,纯属白费功夫。

4.3 AI芯片的替换策略选择

我个人习惯,在AI芯片里不会只用一种策略。我会根据数据流的特征,做混合策略。

4.3.1 基于数据类型的策略

把缓存分成几个区域:

  • 权重区:用随机替换或FIFO。因为权重是顺序访问,不需要复杂的替换逻辑
  • 激活值区:用LRU。激活值可能有复用(比如残差连接),LRU能保留最近用过的数据
  • KV Cache区:用LFU的变种。因为不同token的访问频率差异很大

4.3.2 静态分析与动态调整

我在一个项目里做过这样的尝试:

  1. 编译阶段,分析模型的数据流图,提前标注哪些数据是「一次性使用」的
  2. 运行时,对这些数据直接走「不缓存」或「随机替换」路径
  3. 对复用次数多的数据,走LRU路径

效果还不错,命中率提升了15%左右。但代价是编译器要额外做一轮分析。

核心观点:AI芯片的缓存替换策略,不要迷信某一种算法。理解你的数据流特征,然后「对症下药」。

4.4 知识体系总览

下面这张图,是我梳理的缓存替换策略选择逻辑。你可以把它当作一个决策树来看:

AI芯片缓存替换策略选择逻辑 缓存替换策略 传统策略 AI专用策略 LRU LFU 随机替换 数据类型分区 静态分析 权重区:随机 激活值:LRU KV Cache:LFU变种 编译期标注 核心原则:理解数据流特征,对症下药

嗯,这张图基本把咱们刚才聊的内容串起来了。你从根节点往下走,先判断自己面对的是传统负载还是AI负载,然后选择对应的策略分支。

最后说一句:没有银弹。我见过不少团队,花了好几个月调LRU的参数,结果换个模型又得重来。与其这样,不如花点时间理解你的数据流,然后做针对性的设计。

想要更多资料,联系可可