缓存的出现主要是为了解决CPU运算速度与内存读写速度不匹配的矛盾,由于CPU运算速度要比内存读写速度快不少,这样会使CPU花费很长时间等待数据到来或把数据写入内存。缓存
当CPU要读取一个数据时,首先从缓存中查找,若是找到就当即读取并送给CPU处理;若是没有找到,就用相对慢的速度从内存中读取并送给CPU处理,同时把这个数据所在的数据块调入缓存中,可使得之后对整块数据的读取都从缓存中进行,没必要再调用内存。服务器
按照数据读取顺序和与CPU结合的紧密程度,CPU缓存能够分为一级缓存,二级缓存,部分高端CPU还具备三级缓存,每一级缓存中所储存的所有数据都是下一级缓存的一部分,这三种缓存的技术难度和制形成本是相对递减的,因此其容量也是相对递增的。socket
性能提高:对于总体性能的做用,L1 cache最大,L2次之性能
一级缓存是相对于二级缓存来命名的,它是直接与CPU数据总线相连,传输速度接近于CPU处理速度。设计
一级缓存(Level 1 Cache)简称L1 Cache,位于CPU内核的旁边,是与CPU结合最为紧密的CPU缓存,一级缓存的技术难度和制形成本最高,提升容量所带来的技术难度增长和成本增长很是大,所带来的性能提高却不明显,性价比很低。blog
并且现有的一级缓存的命中率已经很高,因此一级缓存是全部缓存中容量最小的队列
l1致力于更快的速度,所以采用哈佛结构是一种将程序指令存储和数据存储分开的存储器结构。因此一级缓存能够分为一级数据缓存和一级指令缓存,可是AMD和inter采用不一样的方式。数据和指令分离能够作到减小冲突内存
而二级缓存和三级缓存都采用的是冯·诺依曼结构将程序指令存储器和数据存储器合并在一块儿的存储器结构。哈佛结构的微处理器一般具备较高的执行效率效率
而一级缓存小的缘由在于昂贵,并且作大了之后在一级缓存中查找数据也就慢了。硬件
二级缓存是CPU性能表现的关键之一,在CPU核心不变化的状况下,增长二级缓存容量能使性能大幅度提升。
主要缘由在于二级缓存提升命中。
根据28定律,80%的的数据在均可以直接在一级缓存中找到,而剩下的20%的80%能够再二级缓存中找到,所以就是说,96%的数据均可以在一二级缓存中找到。
其中一二级缓存,每一个核心都有一个,可是全部核心共享三级缓存
三级缓存是为读取二级缓存后未命中的数据设计的—种缓存,在拥有三级缓存的CPU中,只有约5%的数据须要从内存中调用,这进一步提升了CPU的效率。
三级缓存的做用是为了进一步提升命中。
存在四级缓存等。
Intel 的CPU已经有增长L4缓存的版本了,不过这里的L4主要用于解决核显和CPU之间交换数据,称为eDRAM。原先的核显没有显存,只能共享内存空间,限制了核显性能和效率。如今在CPU和GPU之间增长了128MB的eDRAM,让GPU与CPU作数据交换。
另外服务器cpu也有四级缓存
三级缓存的大小已经几乎是核心体积的一半了,再加缓存cpu体积会增长。
cpu缓存和内存之间交换的数据,是长度固定的块,称为缓存航.一般是2^n,通常16~256字节不等.
大量缓存是经过硬件哈希表来实现的.这些哈希表有固定长度的哈系桶.
每一个桶可以存储一个缓存行大小的数据.而后几个桶组成一路.也就是哈希值定位到的位置.
通常哈希都比较简单,单纯的使用4位来表示,所以也就是说有16路.每路多个桶.
缓存一致性协议管理缓存行的状态.防止数据不一致或是丢失数据.
协议十分复杂,每个缓存行行有十几种可选的状态.可是基本的有下面四中:
exclusive:独占,而且没有修改.也就是说某个cpu核心独占了该缓存,在其余的核心中都没有缓存该缓存行.而且该核心尚未修改该缓存行的数据,所以他能够丢弃该缓存,或是转移给其余核心
modified:独占,而且修改了该缓存,该核心拥有该缓存行的最新数据.所以必需要将其写会内存或是移交给其余核心
shared:非独占,多个核心可同时保持该缓存.可是不能修改,也不须要转交给别的核心
invalid:无效,也就是说该缓存行为空,以前的缓存行从该核心中移除了.
当一个核心须要读数据的时候,须要想起他cpu广播,那么拥有该缓存的,核心须要响应这个读消息.modified状态的缓存行的核心,必需要相应这个消息.而后将缓存行移交给核心,缓存行状态设置为shared
写,须要向其余核心发送使无效消息
当一个核心要覆盖某个缓存行中的数据是,也就是说要赋值,而不是简单的递增.
那么该核心收到该缓存之后就要将该缓存行覆盖,也就是说他并不须要缓存行中的数据.
可是为了等待该缓存行的到来.须要时间.
所以为了加速这种操做.cpu在缓存之间有加了一个存储缓冲.
也就是这些须要直接赋值(能够理解为直接覆盖)的缓存行先存储到存储缓冲中.当缓存行到了之后再覆盖回去.
可是,这种加速操做,是存在问题的:
在存储缓冲中的缓存行,必须须要等待缓存中的缓存行到来之后才能将其写到缓存中的缓存行.
而且,若是缓存行没有读到缓冲以前的这段时间,cpu会继续其余的操做.例如修改该核心独占的存储缓冲.
例如,cpu1,要覆盖a,可是缓存行a,不在cpu1.同时cpu1还要修改b,b在本身的缓冲中.
cpu2,须要判断b的值,而后对a进行操做.而且持有缓存行a
因此,cpu1由于要覆盖a,所以覆盖后的a存储在存储缓冲中,而且向其余核心,发送使读无效消息.(使读无效消息,延时到达cpu2,也就是说cpu之间的通讯不是队列形式的,和socket有的一拼)而后继续去修改b.而且在缓存行a到来以前,修改完b了.
而后cpu2发送读b的消息.cpu1收到之后,发送本身的缓存行b.而后cpu2收到缓存行b之后,判断b的值,能够进行下面的操做了.可是此时缓存行a的使读无效消息尚未到,所以cpu2此时使用的是a的旧数据.
也就是说数据不一致的行为的根源在于,cpu将要覆写的数据存储在存储缓冲中,继续执行别的指令.同时使读无效消息到达别的cpu以前,别的cpu,由于以前阻塞,可是在使读无效消息到达以前,阻塞解除.使用了该数据.
其实,理解3个cpu更好,由于那个使读无效消息到达的太晚了.
而内存屏障就是为了解决这个问题的.在于,当执行一条语句之后,若是该语句的消息必须实时更新.
那么使用内存屏障,会将该语句后面的修改语句都存储到存储缓冲里,而后当须要修改的缓存行到达缓冲中,才会将存储缓冲里的数据依次写到缓存行里.
这样就避免了缓存不一致的行为.
也就是说内存屏障的意义在于,在内存屏障语句调用以前,必须先讲存储缓冲中的数据所有刷新回缓存行,后面语句修改的数据才可以再次修改缓冲行,不然,就要放入存储缓冲中.
现代处理器采用指令并行技术-流水线,在不存在数据依赖性的前提下,处理器能够改变语句对应的机器指令的执行顺序来提升处理器执行速度.
这个过程是不会引发数据不一致的.由于操做若是存在数据依赖的状况,那么使用同一数据的指令,必定是按顺序执行的.并不会乱序.
只有使用不一样数据的执行之间才会乱序.