一、设计思路
LRU替换算法,是在cache的一个组已经被填满的时候,而且在发生miss的情况下,选择最近最不常用的地址来替换为新的地址。
基于基本原理,我们通过c语言模型进行设计实现,当需要访问一个地址的时候,有下面三种情况,成功命中,未命中但是组中的物理块并没有填满,未命中且组中的物理块已经全部被填满。
对于最后一种情况,我们需要对其进行替换。那就需要寻找最近最不常用的地址所在的物理块的位置,所以我们需要一个时间表来记录每个物理块中存储的地址的最近使用时间与当前时间的时间差,在每次访问一个地址之后,我们对时间表中存储的时间更新。找到最近最不常用的地址之后,将其替换为最新的地址。
将LRU替换算法写成了一个函数,在源代码中已经有详细的过程。
#include<stdio.h>
#define N 4 //N-way组相连
#define Nl 10//输入的要访问的地址的序列长度
void LRU(int block[],int blockN,int list[],int listN)//LRU替换算法
{
int rep = 0, miss = 0, i, j, flag;//定义替换次数与失效次数
int time[blockN];//各个物理块最近一次访问至现在的时间
for(int i = 0;i < blockN;i++)//初始化
time[i] = 0;
for(i = 0;i < listN; i++)
{
for(j = 0; j < blockN; j++) //更新时间记录
if(block[j] != -1)
time[j]++;
for(j = 0; j < blockN; j++)
if(block[j] == list[i]) //命中
{
time[j] = 0;
break;
}
else if(block[j] == -1) //未命中但块中为空
break;
if(j < blockN && block[j] == -1)//未命中且物理块未满,直接存入
{
block[j] = list[i];
time[j] = 0;
miss++;
}
else if(j == blockN)//需要替换
{
int max = 0;
for(int k = 0;k < blockN;k++)//寻找最久未访问的地址所在的物理块的位置
{
if(time[max] < time[k])
max = k;
}
block[max] = list[i];
time[max] = 0;
miss++;
rep++;
}
printf("%d\n",list[i]);
for(int m = 0;m < blockN;m++)//显示当前物理块的状态
{
if(block[m] == -1)
break;
printf("|%d| ",block[m]);
}
printf("\n");
}
printf("失效次数:%d 失效率:%d/%d=%.2f\n", miss, miss, listN, (float)miss/(float)listN);
printf("替换次数:%d 替换率:%d/%d=%.2f\n", rep, rep, listN, (float)(listN - miss)/(float)listN);
}
int main()
{
int block[N], list[Nl];//定义的是一个组的N个块
for(int i = 0;i < N;i++)//初始化
{
block[i] = -1;
list[i] = -1;
}
printf("要访问的地址序列:\n");
for(int i = 0;i < Nl;i++)
scanf("%d", &list[i]);
printf("%d-way组相联\n", N);
LRU(block, N, list, Nl);//调用LRU替换算法的函数
return 0;
}
二、实验测试与结果
这里通过三组数据进行了测试,改变了一个组中的物理块的个数,分别为2,3,4个,输入的地址序列长度都是用的10。
这里每一行“||”格式表示的是当前物理块中存储的地址。为了方便分析,这里使用的地址输入序列为1,2,3,4,5,5,4,3,2,1。
三、实验分析
首先要说明的一点是,对于这三组的失效次数和替换次数并没有对比意义,因为这个LRU替换策略的模型仅仅使用了一个组,每个组的块数不同也就相当于整个cache的大小不同了,这里仅为了展示数据。
然后因为物理块个数的多少并不会改变这个策略本身,所以我们使用N=3的模型进行分析,分析如下图所示。
四、实验总结
通过实验结果可以看出来,设计的c语言模型是比较成功的,能够较好的实验LRU替换算法模型的功能。通过本实验,我进一步了解了LRU替换算法,进一步熟悉了cache的替换。