cache工作原理

转载自smc

Cache的基本原理 - 知乎

Cache组织方式 - 知乎

多核Cache一致性 - 知乎

基本原理

关于为什么使用cache不进行赘述,为了在性能和成本间平衡。

多级cache

当CPU试图从某地址load数据时,首先从L1 cache中查询是否命中,如果命中则把数据返回给CPU。如果L1 cache缺失,则继续从L2 cache中查找。当L2 cache命中时,数据会返回给L1 cache以及CPU。如果L2 cache也缺失,很不幸,我们需要从主存中load数据,将数据返回给L2 cache、L1 cache及CPU。这种多级cache的工作方式称之为inclusive cache。某一地址的数据可能存在多级缓存中。与inclusive cache对应的是exclusive cache,这种cache保证某一地址的数据缓存只会存在于多级cache其中一级。也就是说,任意地址的数据不可能同时在L1和L2 cache中缓存。

直接映射缓存(Direct mapped cache)

我们将cache平均分成相等的很多块,每一个块大小称之为cache line,其大小是cache line size。

cache line是cache和主存之间数据传输的最小单位。

我们一共有8行cache line,cache line大小是8 Bytes。所以我们可以利用地址低3 bits(如上图地址蓝色部分)用来寻址8 bytes中某一字节,我们称这部分bit组合为offset。同理,8行cache line,为了覆盖所有行。我们需要3 bits(如上图地址黄色部分)查找某一行,这部分地址部分称之为index。现在我们知道,如果两个不同的地址,其地址的bit3-bit5如果完全一样的话,那么这两个地址经过硬件散列之后都会找到同一个cache line。所以,当我们找到cache line之后,只代表我们访问的地址对应的数据可能存在这个cache line中,但是也有可能是其他地址对应的数据。所以,我们又引入tag array区域,tag array和data array一一对应。每一个cache line都对应唯一一个tag,tag中保存的是整个地址位宽去除index和offset使用的bit剩余部分(如上图地址绿色部分)。tag、index和offset三者组合就可以唯一确定一个地址了。因此,当我们根据地址中index位找到cache line后,取出当前cache line对应的tag,然后和地址中的tag进行比较,如果相等,这说明cache命中。如果不相等,说明当前cache line存储的是其他地址的数据,这就是cache缺失。在上述图中,我们看到tag的值是0x19,和地址中的tag部分相等,因此在本次访问会命中。

由于tag的引入,因此解答了我们之前的一个疑问“为什么硬件cache line不做成一个字节?”。这样会导致硬件成本的上升,因为原本8个字节对应一个tag,现在需要8个tag,占用了很多内存。tag也是cache的一部分,但是我们谈到cache size的时候并不考虑tag占用的内存部分。

我们可以从图中看到tag旁边还有一个valid bit,这个bit用来表示cache line中数据是否有效(例如:1代表有效;0代表无效)。当系统刚启动时,cache中的数据都应该是无效的,因为还没有缓存任何数据。cache控制器可以根据valid bit确认当前cache line数据是否有效。所以,上述比较tag确认cache line是否命中之前还会检查valid bit是否有效。只有在有效的情况下,比较tag才有意义。如果无效,直接判定cache缺失。

上面的例子中,cache size是64 Bytes并且cache line size是8 bytes。offset、index和tag分别使用3 bits、3 bits和42 bits(假设地址宽度是48 bits)。我们现在再看一个例子:512 Bytes cache size,64 Bytes cache line size。根据之前的地址划分方法,offset、index和tag分别使用6 bits、3 bits和39 bits。如下图所示。

组相连缓存(set associative cache)

图中地址是错误的。

我们可以看到,地址0x00-0x3f地址处对应的数据可以覆盖整个cache。0x40-0x7f地址的数据也同样是覆盖整个cache。我们现在思考一个问题,如果一个程序试图依次访问地址0x00、0x40、0x80,cache中的数据会发生什么呢?首先我们应该明白0x00、0x40、0x80地址中index部分是一样的。因此,这3个地址对应的cache line是同一个。所以,当我们访问0x00地址时,cache会缺失,然后数据会从主存中加载到cache中第0行cache line。当我们访问0x40地址时,依然索引到cache中第0行cache line,由于此时cache line中存储的是地址0x00地址对应的数据,所以此时依然会cache缺失。然后从主存中加载0x40地址数据到第一行cache line中。同理,继续访问0x80地址,依然会cache缺失。这就相当于每次访问数据都要从主存中读取,所以cache的存在并没有对性能有什么提升。访问0x40地址时,就会把0x00地址缓存的数据替换。这种现象叫做cache颠簸(cache thrashing)。针对这个问题,我们引入多路组相连缓存。我们首先研究下最简单的两路组相连缓存的工作原理。

两路组相连缓存(Two-way set associative cache)

我们依然假设64 Bytes cache size,cache line size是8 Bytes。什么是路(way)的概念。我们将cache平均分成多份,每一份就是一路。因此,两路组相连缓存就是将cache平均分成2份,每份32 Bytes。如下图所示。

cache被分成2路,每路包含4行cache line。我们将所有索引一样的cache line组合在一起称之为组。例如,上图中一个组有两个cache line,总共4个组。我们依然假设从地址0x0654地址读取一个字节数据。由于cache line size是8 Bytes,因此offset需要3 bits,这和之前直接映射缓存一样。不一样的地方是index,在两路组相连缓存中,index只需要2 bits,因为一路只有4行cache line。上面的例子根据index找到第2行cache line(从0开始计算),第2行对应2个cache line,分别对应way 0和way 1。因此index也可以称作set index(组索引)。先根据index找到set,然后将组内的所有cache line对应的tag取出来和地址中的tag部分对比,如果其中一个相等就意味着命中。

因此,两路组相连缓存较直接映射缓存最大的差异就是:第一个地址对应的数据可以对应2个cache line,而直接映射缓存一个地址只对应一个cache line。

我们依然考虑直接映射缓存一节的问题“如果一个程序试图依次访问地址0x00、0x40、0x80,cache中的数据会发生什么呢?”。现在0x00地址的数据可以被加载到way 1,0x40可以被加载到way 0。这样是不是就在一定程度上避免了直接映射缓存的尴尬境地呢?在两路组相连缓存的情况下,0x00和0x40地址的数据都缓存在cache中。试想一下,如果我们是4路组相连缓存,后面继续访问0x80,也可能被被缓存。

因此,当cache size一定的情况下,组相连缓存对性能的提升最差情况下也和直接映射缓存一样,在大部分情况下组相连缓存效果比直接映射缓存好。同时,其降低了cache颠簸的频率。从某种程度上来说,直接映射缓存是组相连缓存的一种特殊情况,每个组只有一个cache line而已。因此,直接映射缓存也可以称作单路组相连缓存。

全相连缓存(Full associative cache)

既然组相连缓存那么好,如果所有的cache line都在一个组内。岂不是性能更好。是的,这种缓存就是全相连缓存。我们依然以64 Byts大小cache为例说明。

由于所有的cache line都在一个组内,因此地址中不需要set index部分。因为,只有一个组让你选择,间接来说就是你没得选。我们根据地址中的tag部分和所有的cache line对应的tag进行比较(硬件上可能并行比较也可能串行比较)。哪个tag比较相等,就意味着命中某个cache line。因此,在全相连缓存中,任意地址的数据可以缓存在任意的cache line中。所以,这可以最大程度的降低cache颠簸的频率。但是硬件成本上也是更高。

一个四路组相连缓存实例问题

考虑这么一个问题,32 KB大小4路组相连cache,cache line大小是32 Bytes。请思考以下2个问题:

  1. 多少个组?
  2. 假设地址宽度是48 bits,index、offset以及tag分别占用几个bit?

总共4路,因此每路大小是8 KB。cache line size是32 Bytes,因此一共有256组(8 KB / 32 Bytes)。由于cache line size是32 Bytes,所以offset需要5位。一共256组,所以index需要8位,剩下的就是tag部分,占用35位。这个cache可以绘制下图表示。

Cache分配策略(Cache allocation policy)

cache的分配策略是指我们什么情况下应该为数据分配cache line。cache分配策略分为读和写两种情况。

读分配(read allocation)

当CPU读数据时,发生cache缺失,这种情况下都会分配一个cache line缓存从主存读取的数据。默认情况下,cache都支持读分配。

写分配(write allocation)

当CPU写数据发生cache缺失时,才会考虑写分配策略。当我们不支持写分配的情况下,写指令只会更新主存数据,然后就结束了。当支持写分配的时候,我们首先从主存中加载数据到cache line中(相当于先做个读分配动作),然后会更新cache line中的数据。

Cache更新策略(Cache update policy)

cache更新策略是指当发生cache命中时,写操作应该如何更新数据。cache更新策略分成两种:写直通和回写。

写直通(write through)

当CPU执行store指令并在cache命中时,我们更新cache中的数据并且更新主存中的数据。cache和主存的数据始终保持一致。

写回(write back)

当CPU执行store指令并在cache命中时,我们只更新cache中的数据。并且每个cache line中会有一个bit位记录数据是否被修改过,称之为dirty bit(翻翻前面的图片,cache line旁边有一个D就是dirty bit)。我们会将dirty bit置位。主存中的数据只会在cache line被替换或者显示的clean操作时更新。因此,主存中的数据可能是未修改的数据,而修改的数据躺在cache中。cache和主存的数据可能不一致。

实例

假设我们有一个64 Bytes大小直接映射缓存,cache line大小是8 Bytes,采用写分配和写回机制。当CPU从地址0x2a读取一个字节,cache中的数据将会如何变化呢?假设当前cache状态如下图所示(tag旁边valid一栏的数字1代表合法。0代表非法。后面Dirty的1代表dirty,0代表没有写过数据,即非dirty)。

根据index找到对应的cache line,对应的tag部分valid bit是合法的,但是tag的值不相等,因此发生缺失。此时我们需要从地址0x28地址(请注意cacheline大小对齐)加载8字节数据到该cache line中。但是,我们发现当前cache line的dirty bit置位。因此,cache line里面的数据不能被简单的丢弃,由于采用写回机制,所以我们需要将cache中的数据0x11223344写到地址0x0128地址(这个地址根据tag中的值及所处的cache line行计算得到)。这个过程如下图所示。

当写回操作完成,我们将主存中0x28地址开始的8个字节加载到该cache line中,并清除dirty bit。然后根据offset找到0x52返回给CPU。

cache控制器查找数据以及判断是否命中的规则:通过index查找对应的cacheline,通过tag判断是否命中cache。

VIVT/PIPT/VIPT

Cache组织方式

我们应该清楚CPU发出对某个地址的数据访问,这个地址其实是虚拟地址,虚拟地址经过MMU转换成物理地址,最终从这个物理地址读取数据。因此cache的硬件设计既可以采用虚拟地址也可以采用物理地址甚至是取两者地址部分组合作为查找cache的依据。

虚拟高速缓存(VIVT)

我们首先介绍的是虚拟高速缓存,这种cache硬件设计简单。在cache诞生之初,大部分的处理器都使用这种方式。虚拟高速缓存以虚拟地址作为查找对象。如下图所示。

虚拟地址直接送到cache控制器,如果cache hit。直接从cache中返回数据给CPU。如果cache miss,则把虚拟地址发往MMU,经过MMU转换成物理地址,根据物理地址从主存(main memory)读取数据。由于我们根据虚拟地址查找高速缓存,所以我们是用虚拟地址中部分位域作为索引(index),找到对应的的cacheline。然后根据虚拟地址中部分位域作为标记(tag)来判断cache是否命中。因此,我们针对这种index和tag都取自虚拟地址的高速缓存称为虚拟高速缓存,简称VIVT(Virtually Indexed Virtually Tagged)。另外,我们复习下cache控制器查找数据以及判断是否命中的规则:通过index查找对应的cacheline,通过tag判断是否命中cache。 虚拟高速缓存的优点是不需要每次读取或者写入操作的时候把虚拟地址经过MMU转换为物理地址,这在一定的程度上提升了访问cache的速度,毕竟MMU转换虚拟地址需要时间。同时硬件设计也更加简单。但是,正是使用了虚拟地址作为tag,所以引入很多软件使用上的问题。 操作系统在管理高速缓存正确工作的过程中,主要会面临两个问题。歧义(ambiguity)和别名(alias)。为了保证系统的正确工作,操作系统负责避免出现歧义和别名。

歧义(ambiguity)

不同进程,相同虚拟地址映射不同物理地址。tag问题

歧义是指不同的数据在cache中具有相同的tag和index。cache控制器判断是否命中cache的依据就是tag和index,因此这种情况下,cache控制器根本没办法区分不同的数据。这就产生了歧义。什么情况下发生歧义呢?我们知道不同的物理地址存储不同的数据,只要相同的虚拟地址映射不同的物理地址就会出现歧义。例如两个互不相干的进程,就可能出现相同的虚拟地址映射不同的物理地址。假设A进程虚拟地址0x4000映射物理地址0x2000。B进程虚拟地址0x4000映射物理地址0x3000。当A进程运行时,访问0x4000地址会将物理地址0x2000的数据加载到cacheline中。当A进程切换到B进程的时候,B进程访问0x4000会怎样?当然是会cache hit,此时B进程就访问了错误的数据,B进程本来想得到物理地址0x3000对应的数据,但是却由于cache hit得到了物理地址0x2000的数据。操作系统如何避免歧义的发生呢?当我们切换进程的时候,可以选择flush所有的cache。flush cache操作有两种: - 使主存储器有效。针对write back高速缓存,首先应该使主存储器有效,保证已经修改数据的cacheline写回主存储器,避免修改的数据丢失。 - 使高速缓存无效。保证切换后的进程不会错误的命中上一个进程的缓存数据。

因此,切换后的进程刚开始执行的时候,将会由于大量的cache miss导致性能损失。所以,VIVT高速缓存明显的缺点之一就是经常需要flush cache以保证歧义不会发生,最终导致性能的损失。VIVT高速缓存除了面对歧义问题外,还面临另一个问题:别名(alias)。

别名(alias)

不同虚拟地址映射到相同的物理地址。index问题

当不同的虚拟地址映射相同的物理地址,而这些虚拟地址的index不同,此时就发生了别名现象(多个虚拟地址被称为别名)。通俗点来说就是指同一个物理地址的数据被加载到不同的cacheline中就会出现别名现象。 考虑这样的一个例子。虚拟地址0x2000和0x4000都映射到相同的物理地址0x8000。这意味着进程既可以从0x2000读取数据,也能从地址0x4000读取数据。假设系统使用的是直接映射VIVT高速缓存,cache更新策略采用写回机制,并且使用虚拟地址的位<15...4>作为index。那么虚拟地址0x2000和虚拟地址0x4000的index分别是0x200和0x400。这意味同一个物理地址的数据会加载到不同的cacheline。假设物理地址0x8000存储的数据是0x1234。程序先访问0x2000把数据0x1234加载到第0x200(index)行cacheline中。接着访问0x4000,会将0x1234再一次的加载到第0x400(index)行cacheline中。现在程序将0x2000地址数据修改成0x5678。由于采用的是写回策略,因此修改的数据依然躺在cacheline中。当程序访问0x4000的时候由于cache hit导致读取到旧的数据0x1234。这就造成了数据不一致现象,这不是我们想要的结果。可以选择下面的方法避免这个问题。

针对共享数据所在页的映射方式采用nocache映射。例如上面的例子中,0x2000和0x4000映射物理地址0x8000的时候都采用nocache的方式,这样不通过cache的访问,肯定可以避免这种问题。但是这样就损失了cache带来的性能好处。这种方法既适用于不同进程共享数据,也适用于同一个进程共享数据。 如果是不同进程之间共享数据,还可以在进程切换时主动flush cache(使主存储器有效和使高速缓存无效)的方式避免别名现象。但是,如果是同一个进程共享数据该怎么办?除了nocache映射之外,还可以有另一种解决方案。这种方法只针对直接映射高速缓存,并且使用了写分配机制有效。在建立共享数据映射时,保证每次分配的虚拟地址都索引到相同的cacheline。这种方式,后面还会重点说。

物理高速缓存(PIPT)

基于对VIVT高速缓存的认识,我们知道VIVT高速缓存存在歧义和名别两大问题。主要问题原因是:tag取自虚拟地址导致歧义,index取自虚拟地址导致别名。所以,如果想让操作系统少操心,最简单的方法是tag和index都取自物理地址。物理的地址tag部分是独一无二的,因此肯定不会导致歧义。而针对同一个物理地址,index也是唯一的,因此加载到cache中也是唯一的cacheline,所以也不会存在别名。我们称这种cache为物理高速缓存,简称PIPT(Physically Indexed Physically Tagged)。PIPT工作原理如下图所示。

CPU发出的虚拟地址经过MMU转换成物理地址,物理地址发往cache控制器查找确认是否命中cache。虽然PIPT方式在软件层面基本不需要维护,但是硬件设计上比VIVT复杂很多。因此硬件成本也更高。同时,由于虚拟地址每次都要翻译成物理地址,因此在查找性能上没有VIVT方式简洁高效,毕竟PIPT方式需要等待虚拟地址转换物理地址完成后才能去查找cache。顺便提一下,为了加快MMU翻译虚拟地址的速度,硬件上也会加入一块cache,作用是缓存虚拟地址和物理地址的映射关系,这块cache称之为TLB(Translation Lookaside Buffer)。当MMU需要转换虚拟地址时,首先从TLB中查找,如果cache hit,则直接返回物理地址。如果cache miss则需要MMU查找页表。这样就加快了虚拟地址转换物理地址的速度。如果系统采用的PIPT的cache,那么软件层面基本不需要任何的维护就可以避免歧义和别名问题。这是PIPT最大的优点。现在的CPU很多都是采用PIPT高速缓存设计。在Linux内核中,可以看到针对PIPT高速缓存的管理函数都是空函数,无需任何的管理。

物理标记的虚拟高速缓存(VIPT)

使用虚拟地址对应的index位查找cache,与此同时(硬件上同时进行)将虚拟地址发到MMU转换成物理地址。当MMU转换完成,同时cache控制器也查找完成,此时比较cacheline对应的tag和物理地址tag域,以此判断是否命中cache。

有两个2同步运行。分别是使用虚拟地址对应的index位查找cache,将虚拟地址发到MMU转换成物理地址。

3进行比较。物理地址的tag和虚拟地址的tag。

VIPT Cache的别名问题

如何解决VIPT Cache别名问题

总结

VIVT Cache问题太多,软件维护成本过高,是最难管理的高速缓存。所以现在基本只存在历史的文章中。现在我们基本看不到硬件还在使用这种方式的cache。现在使用的方式是PIPT或者VIPT。如果多路组相连高速缓存的一路的大小小于等于4KB,一般硬件采用VIPT方式,因为这样相当于PIPT,岂不美哉。当然,如果一路大小大于4KB,一般采用PIPT方式,也不排除VIPT方式,这就需要操作系统多操点心了。

多核Cache一致性

问题背景

首先我们假设2个CPU的系统,并且L1 Cache的cache line大小是64 Bytes。两个CPU都读取0x40地址数据,导致0x40开始的64 Bytes内容分别加载到CPU0和CPU1的私有的cache line。

CPU0执行写操作,写入值0x01。CPU0私有的L1 Cache更新cache line的值。然后,CPU1读取0x40数据,CPU1发现命中cache,然后返回0x00值,并不是CPU0写入的0x01。这就造成了CPU0和CPU1私有L1 Cache数据不一致现象。

按照正确的处理流程,我们应该需要以下方法保证多核Cache一致性:

  • CPU0修改0x40的时候,除了更新CPU0的Cache之外,还应该通知CPU1的Cache更新0x40的数据。
  • CPU0修改0x40的时候,除了更新CPU0的Cache之外,还可以通知CPU1的Cache将0x40地址所在cache line置成invalid。保证CPU1读取数据时不会命中自己的Cache。不命中自己的cache之后,我们有两种选择保证读取到最新的数据。a) 从CPU0的私有cache中返回0x40的数据给CPU1;b) CPU0发出invalid信号后,将写入0x40的数据写回主存,CPU1从主存读取最新的数据。

以上问题就是一个简单的不一致性现象。我们需要保证多核一致性,就需要办法维护一致性。可以有2种方法维护一致性,分别是软件和硬件。软件维护一致性的方法,现在基本没有采用。因为软件维护成本太高,由于维护一致性带来的性能损失抵消一部分cache带来的性能提升。所以现在的硬件会帮我们维护多核Cache一致性,并且对软件是透明的。感兴趣的朋友可以继续往下了解硬件是如何维护多核Cache一致性。

Bus Snooping Protocol

继续以上面的例子说明bus snooping的工作机制。当CPU0修改自己私有的Cache时,硬件就会广播通知到总线上其他所有的CPU。对于每个CPU来说会有特殊的硬件监听广播事件,并检查是否有相同的数据被缓存在自己的CPU,这里是指CPU1。如果CPU1私有Cache已经缓存即将修改的数据,那么CPU1的私有Cache也需要更新对应的cache line。这个过程就称作bus snooping。如下图所示,我们只考虑L1 dCache之间的一致性。

这种bus snooping方法简单,但要需要每时每刻监听总线上的一切活动。我们需要明白的一个问题是不管别的CPU私有Cache是否缓存相同的数据,都需要发出一次广播事件。这在一定程度上加重了总线负载,也增加了读写延迟。针对该问题,提出了一种状态机机制降低带宽压力。这就是MESI protocol(协议)。

MESI Protocol

MESI是现在一种使用广泛的协议,用来维护多核Cache一致性。我们可以将MESI看做是状态机。我们将每一个cache line标记状态,并且维护状态的切换。cache line的状态可以像tag,modify等类似存储。继续以上面的例子说明问题。

  1. 当CPU0读取0x40数据,数据被缓存到CPU0私有Cache,此时CPU1没有缓存0x40数据,所以我们标记cache line状态为Exclusive。Exclusive代表cache line对应的数据仅在数据只在一个CPU的私有Cache中缓存,并且其在缓存中的内容与主存的内容一致。
  2. 然后CPU1读取0x40数据,发送消息给其他CPU,发现数据被缓存到CPU0私有Cache,数据从CPU0 Cache返回给CPU1。此时CPU0和CPU1同时缓存0x40数据,此时cache line状态从Exclusive切换到Shared状态。Shared代表cache line对应的数据在"多"个CPU私有Cache中被缓存,并且其在缓存中的内容与主存的内容一致。
  3. 继续CPU0修改0x40地址数据,发现0x40内容所在cache line状态是Shared。CPU0发出invalid消息传递到其他CPU,这里是CPU1。CPU1接收到invalid消息。将0x40所在的cache line置为Invalid状态。Invalid状态表示表明当前cache line无效。然后CPU0收到CPU1已经invalid的消息,修改0x40所在的cache line中数据。并更新cache line状态为Modified。Modified表明cache line对应的数据仅在一个CPU私有Cache中被缓存,并且其在缓存中的内容与主存的内容不一致,代表数据被修改。
  4. 如果CPU0继续修改0x40数据,此时发现其对应的cache line的状态是Modified。因此CPU0不需要向其他CPU发送消息,直接更新数据即可。
  5. 如果0x40所在的cache line需要替换,发现cache line状态是Modified。所以数据应该先写回主存。

以上是cache line状态改变的举例。我们可以知道cache line具有4中状态,分别是Modified、Exclusive、Shared和Invalid。取其首字母简称MESI。当cache line状态是Modified或者Exclusive状态时,修改其数据不需要发送消息给其他CPU,这在一定程度上减轻了带宽压力。

总结

多核Cache一致性由硬件保证,对软件来说是透明的。因此我们不用再考虑多核Cache一致性问题。另外,现在CPU硬件采用的一致性协议一般是MESI的变种。例如ARM64架构采用的MOESI Protocol。多一种Owned状态。多出来的状态也是为了更好的优化性能。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Pentium处理器中的缓存是一种高速存储器,用于存储经常访问的数据和指令。缓存的目的是加快处理器对内存的访问速度,从而提高处理器的性能。 Pentium处理器中的缓存分为一级缓存和二级缓存。一级缓存是处理器内部的缓存,通常被称为L1缓存。它位于处理器核心内部,速度非常快,用于存储处理器经常访问的指令和数据。二级缓存通常是位于处理器芯片上的高速存储器,通常被称为L2缓存。它比L1缓存大,但速度比L1缓存慢一些。 当处理器需要读取数据或指令时,它首先检查L1缓存。如果L1缓存中有所需的数据或指令,处理器直接从L1缓存中读取。如果L1缓存中没有所需的数据或指令,处理器会检查L2缓存。如果L2缓存中有所需的数据或指令,处理器从L2缓存中读取。如果L2缓存中也没有所需的数据或指令,处理器将从主存中读取。 当处理器执行写操作时,它首先将数据写入L1缓存中。然后,如果L1缓存被标记为“脏”的,处理器将把数据写入L2缓存中。如果L2缓存也被标记为“脏”的,数据将被写回到主存中。 缓存的工作原理是通过缓存命中和缓存未命中来实现的。缓存命中是指所需的数据或指令已经存在于缓存中,处理器可以直接从缓存中读取。缓存未命中是指所需的数据或指令不存在于缓存中,处理器必须从主存中读取。缓存的命中率是衡量缓存性能的重要指标之一,通常应该尽可能地提高缓存命中率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值