MultiQueue多优先级队列缓存替换算法分析

来源:互联网 发布:知乎 儿童 天文望远镜 编辑:程序博客网 时间:2024/06/05 15:50

注:本文的算法讨论只针对二级缓存

/*摘要*/

二级缓存拥有不同于一级缓存的访问模式。首先,一级缓存通常采用LRU算法以缓存最近访问数据块,较好地利用了时间局部性原理。但正因如此,进入二级缓存的数据块也就是被上一级淘汰了的数据块,其时间局部性较差。在一级缓存中表现优异的LRU算法,应用于二级缓存效果不佳。基于这一点,在设计二级缓存的替换算法时,首先应该分析进入二级缓存的请求访问特性,比较其与一级缓存的访问特性的差异。

 

/*衡量一个好的二级缓存替换算法的三条准则*/

Minimal Lifetime:对于一个给定的负载,缓存中的热数据块应该保持最少minDist时间;

Frequency-based priority:数据块的优先级应该基于它们的访问频率;

Temporal frequency:过去访问频繁但现在很少被访问的数据块应该被替换掉;

注:变量minDist是对多种实际环境下的负载进行统计后得出的结论,它描述进入二级缓存的数据块在缓存中应该驻留的最小时间量。

 

/*Multi-Queue算法*/

【算法描述】

MQ算法也称多级队列算法,能够同时满足以上三条准则。MQ算法使用多个LRU队列:Q0,Q1......,Qm-1。位于Qj中的缓存块拥有比Qi中缓存块更长的生存时间(j>i)。同时,MQ还有一个历史队列Qout,它是一个有限长的FIFO队列,用来记录从LRU队列中淘汰的缓存块,这一点与2Q算法相似。

当缓存块b命中时,根据优先级计算公式:

                                k = QueueNum(f)

                                       注:f为缓存块的频率

计算出b的优先级k,然后将数据块b移动到Qk队列的队尾。QueueNum(f)函数通常定义为对数函数log2(f)。因此,如果块b原先位于Q2队列,假定它当前的访问频率f为7,在这一次命中后,其访问频率f变为8,根据优先级计算公式log2(f),算得的b命中后的优先级为3,所以将块b从Q2移动到Q3。如果对数据块b的访问没有命中,MQ算法从优先级最低的非空队列中淘汰掉队首元素,为数据块b腾出空间。例如,MQ会优先从Q0中淘汰掉队首元素,如果Q0为空则选择Q1的队首元素,依此类推。当队首元素c被淘汰掉时,它的标志符和当前的访问频率将插入Qout队列队尾。如果Qout队列已满,则依据FIFO算法淘汰掉Qout队列中最老的也就是队首元素。如果被访问的数据b恰好在Qout队列中,则将b从Qout中移除,并将其访问频率在之前记录的访问频率的基础上加1,再根据优先级计算公式将其插入合适的队列。如果b不在Qout中,则将其初始访问频率设为1,根据优先级计算公式QueueNum(f),将其插入到LRU队列。

【老化机制】

根据上面的描述,数据块进入二级缓存后,只要不被淘汰,那么数据块的访问次数将不断增大,优先级别不断提升,直至最高优先级队列。而淘汰总是从低级队列中删除。如果数据块进入高优先级队列之后开始变冷,也就是说不再被访问了,那么这个数据块很难从二级缓存中淘汰出去。这种数据块污染了缓存空间,也浪费了缓存空间,降低了缓存的利用率。因此,还需要设计一个可以让数据块活跃级别降级的机制来解决缓存污染的问题,我们可以称其为MQ的老化机制。

MQ将每一个缓存块关联一个过期时间变量expireTime。这里的"时间"并不是以时分秒来表示的传统意义上的时间,它是一种逻辑时间,通过访问次数来定义。当缓存块在队列中所处的时间超过了过期时间而没有被访问,需要将该缓存块移动到次一级的队列中。当我们向某个优先级队列插入一个新的数据块的时候,我们必需设置该块的过期时间expireTime=currentTime+lifeTime,这里的lifeTime是一个可调节的量,它规定了缓存块在队列中不接任何一次访问可驻留的时间。每一次访问都会检查所有队列的队首元素的过期时间,将队首元素的过期时间与当前时间相比较,如果过期时间超过了当前时间,就将该队首元素移动到次一级队列的队尾,并且重新设置它的过期时间expireTime同时它的访问频率也要减半

【时间复杂度】

MQ的时间复杂度为O(1),因为MQ中所有的队列采用LRU算法,而队列的个数m通常是比较小的(小于10)。每一次访问最多检查(m-1)个队首元素。同时,相比FBR,LFRU或LRU-k等算法,MQ运行速度快,且易于实现。

【MQ与三条准则】

MQ满足一个好的二级缓存替换算法所必需的三条准则。首先,MQ满足最小生存时间(minimal lifetime)特性,因为热数据总是被放置在优先级更高的队列中,数据块能够驻留的最少时间为expireTime,对于一个给定的负载,expireTime要大于minDist值。其次,MQ满足基于频率的优先级划分,访问频率较高的数据块被移动到更高优先级队列,被淘汰的机率更低。最后,MQ也满足频率局部性特点,因为增加了老化机制,当数据块在当前队列的驻留时间超过了预设的过期时间而没有接受任何一次访问时,该数据块将被移动到次一级队列中。一个常期不被访问到的数据块,会慢慢地移动到Q0队列,并最终从二级缓存中淘汰掉。

【代码描述】

/*Procedure to be invoked upon a reference to block b*/

if b is in cache

{

        i = b.queue;

        remove b from queue Q[i];

}

else

{

        victim = EvictBlock();

        if b is in Qout

        {

               remove b from Qout;

        }

        else

               b.reference = 0;

        load b's data into victim's place;

}

b.reference++;

b.queue = QueueNum(b.reference);

insert b to the tail of queue Q[k];

b.expireTime = currentTime + lifeTime;

Adjust();

 

EvictBlock()

{

        i = the first non-empty queue number;

        victim = head of Q[i];

        remove victim from Q[i];

        if Qout is full

               remove the head from Qout;

        add victim's ID to the tail of Qout;

        return victim;

}

 

Adjust()

{

        currentTime++;

        for(k=1; k<m; k++)

        {

               c = head of Q[k];

               if (c.expireTime < currentTime)

               {

                       move c to the tail of Q[k-1];

                       c.expireTime = currentTime + lifeTime;

               }

        }

}

 

 

0 0
原创粉丝点击