4 种 cache 替换策略对比

4 种 cache 替换策略对比

RAND, FIFO, LRU, LFU

实验参考条件

参考的是我电脑上的 i7-10750H ,根据《Intel Core i7-10750H Processor 12M Cache up to 5.00 GHz 产品规范》显示,这款 CPU 的缓存容量大小为 12MB ,行大小为 64 Bytes,考虑到其有 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 ,可以点开播放

数据量均在 \(10^6\) ~ \(8 \cdot 10^6\) 个地址左右(约15MB ~ 45MB)

1-2 随机访问

结果相差不大

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

1.gif

2.gif

二叉树式数据结构

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

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

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

3.gif

DP 转移

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

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

4.gif

图的 DFS

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

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

5.gif

总结

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

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

10.gif

附代码

"""
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'out{2}.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);
"""
posted @ 2022-04-06 09:50  LacLic  阅读(762)  评论(1编辑  收藏  举报