zoukankan      html  css  js  c++  java
  • cache的工作原理

    在CPU的所有操作中,访问内存是最频繁的操作。由于一般微机中的主存储器主要由MOS型动态RAM构成,其工作速度比CPU低一个数量级,加上CPU的所有访问都要通过总线这个瓶颈,所以,缩短存储器的访问时间是提高计算机速度的关键。采用在CPU和内存之间加进高速缓冲存储器cache的办法较好地解决了这一问题。所谓“cache”原意是指勘探人员的藏物处,这里引申为“高速缓存”。在保证系统性能价格比的前提下,使用速度与CPU相当的SRAM芯片组成小容量的高速缓存器,使用低价格、小体积能提供更大存储空间的DRAM芯片(或内存条)组成主存储器。


      下面,以取指为例对cache的工作原理进行说明。命中率是高速缓存子系统操作有效性的一种测度,它被定义为高速缓存命中次数与存储器访问总次数之比,用百分率来表示,即


    例如,若高速缓存的命中率为92%,则意味着CPU可用92%的总线周期从高速缓存中读取数据。换句话说,仅有8%的存储器访问是对主存储器子系统进行的。假设经过前面的操作cache中已保存了一个指令序列,当CPU按地址再次取指时,cache控制器会先分析地址,看其是否已在cache中,若在,则立即取来,否则,再去访问内存。因为大多数程序有一个共同特点,即在第一次访问了某个存储区域后,还要重复访问这个区域。CPU第一次访问低速DRAM时,要插入等待周期。当CPU进行第一次访问时,也把数据存到高速缓存区。因此,当CPU再访问这一区域时,CPU就可以直接访问高速缓存区,而不访问低速主存储器。因为高速缓存器容量远小于低速大容量主存储器,所以它不可能包含后者的所有信息。当高速缓存区内容已装满时,需要存储新的低速主存储器位置上的内容,以代替旧位置上的内容。高速缓存器的设计目标是使CPU访问尽可能在高速缓存器中进行,其工作原理如图5.25所示。

    这里讲述的读/写策略依然是针对CPU对存储器的读/写访问的,即cache读操作实际上是CPU读存储器,cache写操作实际上是CPU写存储器。在cache中应尽量存放CPU最近一直在使用的数据。当cache装满后,可将长期不用的数据删除,以提高cache的使用效率。为保持cache中的数据与主存储器中的数据的一致性,同时避免CPU在读/写过程中遗失新数据,确保cache中更新过的数据不会因覆盖而消失,必须将cache中的数据及时更新并准确地反映到主存储器。这里涉及CPU、cache与主存储器三者之间的协调,使得读/写操作复杂化,从而也引入了一些新的方法与专业术语。

     

    1.读策略

    读策略又可分为以下两种。


    (1)贯穿读出式(look through)


    贯穿读出式的原理如图5.26所示。


      在这种方式下,cache位于CPU与主存之间,CPU对主存的所有数据请求都首先送到cache,由cache在自身查找。如果命中,则切断CPU对主存的请求,并将数据送出;如果未命中,则将数据请求传给主存。该方法的优点是降低了CPU对主存的请求次数,缺点是延迟了CPU对主存的访问时间。


    (2)旁路读出式(look aside)


      旁路读出式的原理如图5.27所示。


      在这种方式中,CPU发出数据请求,并不是单通道地穿过cache,而是向cache和主存同时发出请求。由于cache速度更快,如果命中,则cache在将数据回送给CPU的同时,还来得及中断CPU对主存的请求;若未命中,则cache不做任何动作,由CPU直接访问主存。它的优点是没有时间延迟,缺点是每次CPU都要访问主存,这样就占用了部分总线时间。

    还有另外一个值得注意的概念,那就是“行填充”。


      每当CPU由主存储器读入数据时,同时还要将该数据复制到cache中。即使当前CPU仅读一个字节,cache控制器也总是要将主存储器中包含该字节的一个完整的cache行复制到cache中。一个cache行占据32个字节,这种从主存储器向cache传送一行数据的操作就称为cache行填充(line fill),这是考虑到数据与代码往往具有连续性,CPU下一次所需的数据或代码通常还是处在上一次的数据或代码附近,即同处一cache行中的可能性最大,这样处理就提高了cache的命中率。由此可见,cache中的数据是由空到满逐行建立起来的。


      cache行的容量过小时,会产生频繁的行填充操作,整机效率不会有明显提高。然而当一行的容量空间过大时,填充一行所需的时间较长,而且可能有许多数据并不是CPU最近所需要的,从而造成过大的浪费,这样也不会使整机效率显著上升。因此必须折中各种因素来选择cache行的大小。Intel体系的32位微处理器中一个cache行由32个字节组成,并且cache控制器用后面即将讨论的突发模式传送数据块,一次突发传送一个cache行的32个字节,其传输速率比常规访问几乎高出一倍。


      就cache整体容量而言,也有同cache行类似的矛盾。cache容量过小将起不到明显改善系统性能的效果;增加cache容量自然可以存储更多的信息,但随之也就增加了成本,且搜索大容量的cache还不如搜索小容量的速度快。可见,cache的容量要兼顾多种因素,选择适中,一般取主存储器的几十分之一或者几百分之一。


      每当CPU所需的数据或代码不在cache中而出现未命中时,cache控制器就必须在主存储器中读取数据,这段时间较长且需要等待。此时,cache控制器使“准备好”或类似的信号变为无效,于是CPU插入等待时钟周期,cache控制器将访问主存储器,将所需数据传送给CPU。

    2.替换策略

      当cache已经装满后,主存储器中新的数据还要不断地替换掉cache中过时的数据,这就产生了cache块数据的替换策略。那么应替换哪些cache块才能提高命中率呢?理想的替换策略应该使得cache中总是保存着最近将要使用的数据,不用的数据则被替换掉,这样才能保证很高的命中率。目前,使用较多的是随机(random)替换、先入先出(FIFO)替换与近期最少使用(LRU)替换三种策略。


    (1)随机(random)替换策略


      随机替换是不顾cache块过去、现在及将来使用的情况而随机地选择某块进行替换,这是一种最简单的方法。


    (2)先入先出(FIFO)替换策略


      先入先出(FIFO)替换策略的基本思想是:根据进入cache的先后次序来替换,先调入的cache块被首先替换掉。这种策略不需要随时记录各个块的使用情况,容易实现,且系统开销小。其缺点是一些需要经常使用的程序块可能会被调入的新块替换掉。


    (3)近期最少使用(LRU)替换策略


      近期最少使用LRU(least recently used)替换策略的基本思想是:把CPU近期最少使用的块作为被替换的块。这种替换算法相对合理,命中率最高,是目前最常采用的方法。它需要随时记录cache中各块的使用情况,以便确定哪个块是近期最少使用的块,实现起来比较复杂,系统开销较大。

      不管是哪种策略,它们都只能用硬件电路来实现,试想若依靠软件的话,cache的“高速”含义就毫无意义了。

    3.写策略

     以上讨论的都是CPU读数据的情况,另一种是CPU写数据的情况。cache控制器同样会判断其地址是否定位在cache中。如果在,CPU的数据就会写到cache中。对于进一步的主存储器操作,cache控制器有以下几种主要的写策略。


    (1)通写方式(write through)


      通写方式的原理如图5.28所示。

    2)回写方式(write back)


      回写方式的原理如图5.29所示。


      为了尽量减少对主存的访问次数,克服通写方式中每次数据写入都要访问主存,从而导致系统写速度降低并占用总线时间的弊病,又有了回写方式。它的工作原理是:数据一般只写到cache,而不写入主存,从而使写入的速度加快。但这样有可能出现cache中的数据得到更新而对应主存中的数据却没有变(即数据不同步)的情况。此时可在cache中设置一个标志地址及数据陈旧的信息,只有当cache中的数据被再次更改时,才将原更新的数据写入主存相应的单元中,然后接受再次更新的数据。这样就保证了cache和主存中的数据不产生冲突。

    3)失效(invalidation)


      当系统中存在其他微处理器或DMA操作的系统部件时,主存储器即成为共享存储器。它们之中的任何一方对主存储器都有可能覆盖写入。此时cache控制器必须通报有关的cache行,它们的数据由于主存储器已被修改而成为无效,这种操作就称为cache失效。

  • 相关阅读:
    C# Path 目录
    Maxscript 窗体与结构体this的传递
    python---文件操作
    python---数据类型---集合
    python---购物车---更新
    python---三级菜单
    python---数据类型---字典
    python---数据类型---字符串
    python---购物车
    python---数据类型---列表
  • 原文地址:https://www.cnblogs.com/lianjiehere/p/4182219.html
Copyright © 2011-2022 走看看