Optimal Caching: Farthest-in-Future算法

1. 线下cache

   在现代计算机系统中,大多拥有多级存储结构。这是因为不同的存储器拥有不同的读写速度和成本。在我们最常见的个人电脑中,从离CPU最近到最远的顺序一般是:CPU中的寄存器、cache、内存(RAM)、外存(硬盘)。显然,他们的容量也逐渐变大,内存往往是8G或者16G,外存往往是512G或者1T。容量的大小很大一部分决定因素是其成本,意味着上述存储器的单位成本也逐渐减小(很好理解,便宜的存储器给的容量才大)。而成本又和读写速度密不可分,读写速度快的存储器性能更好,而这样的性能往往是用其他东西为代价的。例如DRAM的读写速度和功耗均差于SRAM,但是DRAM便宜,所以在电脑中DRAM的容量往往大于SRAM。
   既然读写速度越快的存储器容量越少,那其存储的内容就需要有讲究,我们总是想将常用的数据存放在性能最好的存储器中,这样我们读写的平均速度就能提高。于是,在现代计算机中,cache的存储策略就成了很重要的一环(个人理解,CPU中的寄存器容量太少,对整体性能影响不大,所以不太考虑其存储策略的优化)。对于一个cache,当我们需要读取某个数据的时候,其已经存放在cache中,我们称为“命中(hit)”;如果该数据没有存放在cache中,称为“miss”。在miss的情况下,我们需要从主存储器中读取这个数据并将其放入cache,即将cache中某个数据替换掉。而线下(offline)cache指的是,我们需要读取的数据是确定的,这是一种重要的模型。现在我们接触的更多的是线上(online)cache,即需要读取的数据并不确定,是随机的,根据计算机任务的变化而变化,也是最贴近实际的模型。本文我们讨论线下cache及其最优的存储算法。
   考虑下列7个数据
a , b , c , c , a , a , b . a,b,c,c,a,a,b. a,b,c,c,a,a,b.假设我们有一个能存放2个数据的cache,初始状态为 { a , b } \{a,b\} {a,b}。当第3个数据 c c c来临的时候,我们遭遇一个miss,于是需要从主存储器中读出 c c c,并且将cache中某个数据替换成 c c c。这里考虑替换 a a a,于是cache变为 { c , b } \{c,b\} {c,b}。当第5个数据 a a a到来时,又是一次miss,这次将 c c c替换回 a a a。于是,整个过程进行了两次替换。这里举例的cache容量很小,可替换的选择很有限,但是如果是一个可以存放成千上万个数据的cache,那么每次遇到miss的时候如何替换数据,就是一个大问题了。显然,不同的替换算法,会导致不同的替换次数,替换次数越多,系统性能越差。因此,我们想找到一个线下的cache替换算法,使其替换次数总是最少的。

2. 最优线下cache规则

   1960年代,Les Belady提出了一个简单的cache规则:当一串需要读取数据确定的时候,每当遇见一个miss,则考虑cache中已有的所有数据,比较这些数据在确定的需要读取的数据中的位置,选取位置最远的数据进行替换。改规则是一种最优的线下cache算法,称为Farthest-in-Future(FF)算法
   这里举一个例子,假设我们的cache初始值为
{ a , b , c , d , e , f } , \{a,b,c,d,e,f\}, {a,b,c,d,e,f},需要读取的数据为
g , a , b , c , e , d , a , b , b , a , c , d , e , a , f , a , d , e , f , g , h . g,a,b,c,e,d,a,b,b,a,c,d,e,a,\bm{f},a,d,e,f,g,h. g,a,b,c,e,d,a,b,b,a,c,d,e,a,f,a,d,e,f,g,h.显然第一个数据就遭遇了miss,我们观察cache里已有的数据,发现 f f f是需要去读的数据中位置最远的,因此我们将cache中的 f f f替换为 g g g

3. Farthest-in-Future(FF)算法最优性的证明

   前面提到FF算法是线下cache算法中最优的,这意味着,对于确定的需要读取的序列,无论采用任何其他替换策略,总的替换次数都不会小于FF算法。FF算法的证明需要用数学归纳法,其核心思想是:对于任意一个确定的需要读取的数据,考虑一个最优替换策略 S o S_o So,考虑FF算法导致的替换策略 S F F S_{FF} SFF,我们总能将 S o S_o So通过某种变换方法进行变换,在这种变换方法下,每一次变换都不增加替换次数,经过一系列变换 S o S_o So可以变成 S F F S_{FF} SFF,这也意味着两者的替换次数相同
   为简化文字,我们将需要读取的数据称为输入数据,每一种特定的替换策略称为一种schedule。
   在证明FF算法是最优算法之前,引入reduced schedule的概念。对于一个schedule,他可以是在输入数据中的某个数据miss的时候被替换到cache中,也可以是任意时刻进行数据的替换,这意味着即使某次输入数据命中,他也可以替换cache中的某个数据。reduced schedule定义为:一个schedule,他只在miss的时候进行数据替换
   任意一个schedule S S S,均可以变换成一个reduced schedule S ′ S^{'} S,而不增加替换次数。证明考虑两种情况:

  • S S S中某次没有miss的时候, a a a在时刻1被替换成了 b b b,而某次miss的时候,记为时刻2, b b b又被替换成了 c c c;在 S ′ S^{'} S中, a a a在时刻2倍替换成 c c c。显然, S ′ S^{'} S S S S少一次替换。
  • S S S中某次没有miss的时候, a a a在时刻1被替换成了 b b b,而在时刻2,命中 b b b;在 S ′ S^{'} S中, a a a在时刻2被替换成 b b b。显然,两者替换次数相同。

通过上述两种情况的变换,我们可以将任意schedule S S S变换成一个reduced schedule S ′ S^{'} S,且不增加替换次数。引入reduced schedule的意义在于简化分析,因为我们不用再考虑随机的替换的可能,只需要考虑有数据miss的情况下的替换。
   显然,给定输入数据,我们总是能找到一个reduced schedule是最优的schedule(之一)。因为前面的定义,假如找到一个最优schedule不是reduced schedule,我们总是能将其变换成reduced schedule,并且不增加替换次数,那么这个reduced schedule也是一个最优schedule。下面进行FF算法最优性的证明。

   给定输入数据,考虑一个reduced schedule S S S,以及FF算法给出的schedule S F F S_{FF} SFF,他们的前 j j j步相同(每一步cache中数据的组成一样,但可能顺序不一样,但是顺序不影响替换)。我们总是能将 S S S变换成一个新的schedule S ′ S^{'} S,使得 S ′ S^{'} S S F F S_{FF} SFF的前 j + 1 j+1 j+1步相同,并且 S ′ S^{'} S的替换次数不大于 S S S

证明

因为 S S S S F F S_{FF} SFF j j j步相同,而 j + 1 j+1 j+1步不同,这意味着 j + 1 j+1 j+1步两个schedule进行了不同的数据替换。记第 j + 1 j+1 j+1步的输入数据为 d d d S S S中将 f f f替换成了 d d d,而 S F F S_{FF} SFF e e e替换成了 d d d。显然, S S S S F F S_{FF} SFF在第 j j j步的时候,同时拥有 e e e f f f,在第 j + 1 j+1 j+1步的替换后:

  • S S S的cache: { e , d , 其 他 元 素 } \{e,d,其他元素\} {e,d,}
  • S F F S_{FF} SFF的cache: { d , f , 其 他 元 素 } \{d,f,其他元素\} {d,f,}

此时考虑如何构造 S ′ S^{'} S。首先,我们令 S ′ S^{'} S的前 j + 1 j+1 j+1步与 S F F S_{FF} SFF相同。至此,如果只考虑前 j + 1 j+1 j+1步的话, S S S S F F S_{FF} SFF S ′ S^{'} S的替换次数是一样的。关键在于我们如何构造 S ′ S^{'} S后面的步骤,使得其替换次数不大于 S S S

步骤 S S S S F F S_{FF} SFF S ′ S^{'} S
j j j { e , f , 其 他 元 素 } \{e,f,其他元素\} {e,f,} { e , f , 其 他 元 素 } \{e,f,其他元素\} {e,f,} { e , f , 其 他 元 素 } \{e,f,其他元素\} {e,f,}
j + 1 j+1 j+1 { e , d , 其 他 元 素 } \{e,d,其他元素\} {e,d,} { d , f , 其 他 元 素 } \{d,f,其他元素\} {d,f,} { d , f , 其 他 元 素 } \{d,f,其他元素\} {d,f,}

要使 S ′ S^{'} S的替换次数不大于 S S S,我们可以尽量模仿 S S S的替换策略。于是从 j + 1 j+1 j+1步开始,我们尽量模仿 S S S的替换策略。但是,因为从 j + 1 j+1 j+1步开始, S S S S ′ S^{'} S就有了区别,为了尽量模仿 S S S,我们需要将 S ′ S^{'} S尽快调整至和 S S S拥有相同元素组成。如果在某一步开始, S S S S ′ S^{'} S的元素组成完全一样,那么后面的步骤 S ′ S^{'} S就能完全复制 S S S了。

如果在第 j + 1 j+1 j+1步之后的输入数据既不是 e e e也不是 f f f,并且 S S S没有替换数据 e e e,那么 S S S S ′ S^{'} S拥有相同的动作。那么我们的关注点应该是,在第 j + 1 j+1 j+1步后, S S S S ′ S^{'} S第一次有不同动作的时候

这里需要注意一个重点,那就是在第 j + 1 j+1 j+1步之后,假如某次输入数据是 e e e,那么在他之前,必然有一次输入数据是 f f f。这是因为在第 j j j步的时候, S F F S_{FF} SFF替换了 e e e而不是 f f f,这意味着 f f f在后面的输入数据中,要先于 e e e出现。因此,我们在考虑在第 j + 1 j+1 j+1步后, S S S S ′ S^{'} S第一次有不同动作的时候,不会出现输入数据是 e e e这一种情况。下列分析两者在第 j + 1 j+1 j+1步后第一次与不同动作的几种可能情况。

情况一(输入数据是 f f f):假如输入数据是 f f f S S S可能把 e e e替换掉,在这种情况下, S ′ S^{'} S命中 f f f,不需要额外动作,至此,两者的cache均为 { d , f , 其 他 元 素 } \{d,f,其他元素\} {d,f,}。另一种情况是 S S S将其他元素(非 e e e,记为 x x x)替换成 f f f,这种情况下, S ′ S^{'} S命中 f f f。但是为了变化成和 S S S相同元素组成, S ′ S^{'} S x x x替换成 e e e,此时,两者的cache均为 { e , d , f , 其 他 元 素 } \{e,d,f,其他元素\} {e,d,f,}

情况二(输入数据既不是 e e e也不是 f f f):此时 S S S只能是替换 e e e,因为我们现在讨论的是 S S S S ′ S^{'} S第一次有不同动作,假如 S S S不替换 e e e,而是其他元素,那么 S ′ S^{'} S也可以替换其他元素,两者动作相同,不符合我们现在的讨论。当 S S S替换 e e e为新元素 g g g,为了与之相同, S ′ S^{'} S f f f替换成新元素 g g g。至此,两者的cache均为 { g , d , 其 他 元 素 } \{g,d,其他元素\} {g,d,}

上面讨论的情况1中需要注意,当 S S S将其他元素(非 e e e,记为 x x x)替换成 f f f,为了变化成和 S S S相同元素组成, S ′ S^{'} S x x x替换成 e e e。这种情况下, S ′ S^{'} S变成了一个非reduced schedule,但是,有前面的定理,我们可以将其变回reduced schedule而不增加替换次数。

在上述两种情况下,我们保证了 S S S S ′ S^{'} S在经历了一次不同动作后,拥有完全相同的元素组成,这意味着,我们可以让 S ′ S^{'} S在后续的步骤中完全模仿 S S S的步骤,使得 S ′ S^{'} S的替换次数不大于 S S S

综上,我们证明了这个性质。
□ \square

   有了上述性质,我们利用数学归纳法可以很容易证明FF算法是最优的。给定输入数据,记它的一个最优reduced schedule是 S o S_o So,记FF算法下的schedule是 S F F S_{FF} SFF S o S_o So S F F S_{FF} SFF的前 j j j步相同。这里需要注意的是,我们总是能找到至少一步相同点,比如还没有数据的时候,第 0 0 0步,即cache刚填满的时候。另外一个角度看,假如cache最开始是空的,那么显然在cache被数据填满之前,两者步骤都是一样的。

   因此,在保证了我们总是能找到一个最优的 S o S_o So S F F S_{FF} SFF在前 j j j步相同的情况下,我们利用上面的性质,将 S S S变换成一个新的schedule S ′ S^{'} S,使得 S ′ S^{'} S的替换次数不大于 S o S_o So,同时 S ′ S_{'} S S F F S_{FF} SFF在前 j + 1 j+1 j+1步相同。如此反复,我们最终将 S S S变换成与 S F F S_{FF} SFF相同,证明到 S F F S_{FF} SFF也是一种最优的算法。

参考文献

[1] Kleinberg J., Tardos E.,Algorithm Design,2006。

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值