4 种 cache 替换策略对比

Posted LacLic

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4 种 cache 替换策略对比相关的知识,希望对你有一定的参考价值。

4 种 cache 替换策略对比

RAND, FIFO, LRU, LFU

实验参考条件

参考的是我电脑上的 i7-10750H ,根据《Intel Core i7-10750H Processor 12M Cache up to 5.00 GHz 产品规范》显示,这款 CPU 的缓存容量大小为 12MB ,考虑到其有 6 个相同大小的核心,实际运行简单程序时,基本上是单核心工作,我们将其进行平分为每个核 2MB (实际上 intel 处理器缓存不止一层,实验为了简化模型,只采取一层模型)

个人考虑了 5 种常见的使用情况

  1. linar array random query / 线性表随机访问
  2. 2-demension random query / 二维随机访问
  3. binary tree query / 二叉树式数据结构询问
  4. DP trans / DP转移
  5. Graph DFS / 图DFS遍历

根据根号分块原理,我们采取 128 路组相联映射方式

实验结果

以下图片都是 gif ,可以点开播放

1-2 随机访问

结果相差不大

|Cache 命中率|RAND|FIFO|LRU|LFU|
|---|---|---|---|---|---|
|一维|25.71|25.99|26.00|25.91|
|二维|25.69|25.97|25.96|25.96|

二叉树式数据结构

局部性原理在此体现的较为突出

二叉树式数据结构能维护 set, map, heap 等信息,是极为常见的数据结构,故 LRU, LFU 还是体现出了较大的优越性

||RAND|FIFO|LRU|LFU|
|---|---|---|---|---|---|
|Cache 命中率|90.29|90.49|91.81|92.76|

DP 转移

由于 DP 转移主要在时间上较为饱和,占用空间普遍不多,测试了多种 DP 代码,cache 命中率普遍高于 99%

||RAND|FIFO|LRU|LFU|
|---|---|---|---|---|---|
|Cache 命中率|99.33|99.50|99.50|100.00|

图的 DFS

||RAND|FIFO|LRU|LFU|
|---|---|---|---|---|---|
|Cache 命中率|7.52|7.72|7.72|7.69|

由于 DFS 耗时最大的主要是栈递归,在空间使用分布上极为稀疏,cache 命中率普遍较低

总结

在 cache 缓存映射方式较为合理、缓存大小较大等条件下,四种替换策略差距并不是很大,考虑对 cache 空间的额外占用, LFU 虽然在几种情况下表现出了一定的时间上的优越性(主要在二叉式数据结构上),但结合空间上的占用,总体可能并没有明显的优势。

总图表变化(随机替换策略全程垫底)

附代码

"""
RAND, FIFO, LRU, LFU
i7-10750H cache size 12MB = 12,582,912 Bytes (3,145,728 integers) 3e6
6 cores
2MB cache per core

1. linar array random query
2. 2-demension random query
3. binary tree query
4. DP trans
5. Graph DFS

coherency_line_size = 64 Bytes = 16 integers

Cache: 2,097,152 Bytes --- 32,768 Blocks
Memory: 17,179,869,184 Bytes --- 268,435,456 Blocks

use "128-set-associative mapping" # 256 * 128

data size: about 2e6

"""

import random
import time

# data test, done

def test(flag):
    st = time.time()
    lst = []
    tot = []
    for i in range(0,256):
        lst.append([[0,0,0]])
        tot.append(0)
        for j in range(1,128):
            lst[i].append([0,0,0])
    Tm = 0
    cached = 0
    uncached = 0
    
    with open(f\'out2.txt\',\'r\') as fio:
        content = fio.read().rstrip(\',\')
    # datas = [eval(\'0x4bb7318\'),eval(\'0x4bb7318\'),]
    datas = [int(n,16) for n in content.split(\',\')]

    for address in datas:
        address >>= 6
        thesign = address % 256
        address <<= 6

        lowC = [0,lst[thesign][0][1]]
        lowT = [0,lst[thesign][0][2]]
        isFound = False
        for i in range(0,128):
            thiz = lst[thesign][i]
            if thiz[0] == address:
                thiz[1] += 1
                thiz[2] = Tm
                isFound = True
            if lowC[1] > thiz[1]:
                lowC[0] = i
                lowC[1] = thiz[1]
            if lowT[1] > thiz[2]:
                lowT[0] = i
                lowT[1] = thiz[2]

        if isFound:
            cached += 1
        else:
            chosen = 0
            if flag == 0:
                chosen = int(random.random() * 128)
            elif flag == 1:
                chosen = tot[thesign]
                tot[thesign] += 1
                tot[thesign] %= 128
            elif flag == 2:
                chosen = lowT[0]
            else:
                chosen = lowC[0]
            lst[thesign][chosen] = [address,1,Tm]
            uncached += 1

        Tm += 1

    print(f\'cached / (cached + uncached) * 100:.2f%\')

test(3)

# out1.txt RAND 25.71%
# out1.txt FIFO 25.99%
# out1.txt LRU  26.00%
# out1.txt LFU  25.91%

"""
const data = [0,0,0,0,0]
const data = [25.71,25.99,26.00,25.91,23]
const data = [25.69,25.97,25.96,25.96,23]
const data = [90.29,90.49,91.81,92.76,88]
const data = [99.33,99.50,99.50,100.00,97]
const data = [7.52,7.72,7.72,7.69,5]
"""

# out3.txt RAND 90.29%
# out3.txt FIFO 90.49%
# out3.txt LRU  91.81%
# out3.txt LFU  92.76%

# out4.txt RAND 99.33%
# out4.txt FIFO 99.50%
# out4.txt LRU  99.50%
# out4.txt LFU  100.00%

"""# out4.txt RAND 99.97%
#          FIFO 99.97%
#          LRU  99.97%
#          LFU  99.97%"""

#    5          7.52%
#               7.72%
#               7.72%
#               7.69%

"""js
const data = [0,0,0,0,0];
const next = [[0,0,0,0,0],[25.71,25.99,26.00,25.91,23],
[25.69,25.97,25.96,25.96,23],
[90.29,90.49,91.81,92.76,88],
[99.33,99.50,99.50,100.00,97],
[7.52,7.72,7.72,7.69,5]];
var cnt = 0;
// 123a = 5;
option = 
  xAxis: 
    max: \'dataMax\',
    min: \'dataMin\'
  ,
  yAxis: 
    type: \'category\',
    data: [\'RAND\', \'LIFO\', \'LRU\', \'LFU\',\'\'],
    inverse: true,
    animationDuration: 300,
    animationDurationUpdate: 300,
    max: 3, // only the largest 3 bars will be displayed
    axisLabel: 
        show: true,
        fontSize: 20
    ,
  ,
  series: [
    
      realtimeSort: true,
      name: \'X\',
      type: \'bar\',
      data: data,
      label: 
        show: true,
        position: \'right\',
        valueAnimation: true
      
    
  ],
  legend: 
    show: true
  ,
  animationDuration: 0,
  animationDurationUpdate: 3000,
  animationEasing: \'linear\',
  animationEasingUpdate: \'linear\'
;
function run(cnt) 
  for (var i = 0; i < data.length; ++i) 
    data[i] = next[cnt][i];
  
  myChart.setOption(
    series: [
      
        type: \'bar\',
        data
      
    ]
  );

setTimeout(function () 
  run();
, 0);

function sleep(time)
 var timeStamp = new Date().getTime();
 var endTime = timeStamp + time;
 while(true)
 if (new Date().getTime() > endTime)
  return;
  
 


setInterval(function () 
  cnt += 1;
  cnt %= 6;
  run(cnt);
  // sleep(1000);
, 6000);
"""

以上是关于4 种 cache 替换策略对比的主要内容,如果未能解决你的问题,请参考以下文章

ARM/cacheDynamIQ架构及cache的替换策略

计算机组成原理 王道考研2021 第三章:存储系统 -- 高速缓冲存储器Cache基本概念和原理(程序访问的局部性原理)Cache和主存的映射方式替换算法写策略

ehcashe

cache 缓存的处理

三种缓存策略:Cache Aside 策略Read/Write Through 策略Write Back 策略

三种缓存策略:Cache Aside 策略Read/Write Through 策略Write Back 策略