赞
踩
照着wikipedia扒一遍,聊一聊如何设计一个缓存。
缓存是为了将dram的数据拿到离cpu更近的地方提高效率(temporal locality, spacial locality)。核心是要存数据(data)或者指令(instruction)。这篇文章中我们统称他们为数据。
-> 那么现在你有个DRAM, 有个比如16 entry的cache,如何选择拿一个{地址,数据}放到哪个entry里呢?->Associativity
Direct-mapped cache:将地址mod16,就存到那个entry里
two-way set associative cache:将地址mod8,存到对应的2个entry中的任何一个
-> 你存好了数据,下面就要开始继续读写了
就涉及到replacement policy,比如说LRU(用double linked list实现?)之类的
就涉及到了write through/ write back。这里就可以argue latency/ efficiency。writeback 可以搞个dirty bit,必须写再写回到memory。
就涉及到了write allocate/ non-allocate
-> 好了,我们再回头聊一下将dram的数据存到了一个entry里,当cpu要一个地址的数据的时候,我怎么知道他在不在cache里呢?
cpu最小索引单位是byte。那么entry(或称block)就需要6bit来分清是哪个byte。因为direct map,一共16个entry,所以index就是4bit。剩下的地址位都进tag,32-6-4=22bit tag。
当cpu request一个地址的数据的时候,中间4bit(index)表示这个数据可能在的位置,我们将高置位22位拿来与index中存的tag来比较,如果相同,就找到了这个数据。
简单来说当有set associative就要多比较几个存在entry里的tag。
当你有virtual address的时候你需要先把他翻译成physical address然后再按照上面的流程走一遍,就至少要两个cycle。如果完全用virtual address来索引可以避免address translation就快很多,但是会有homonym(同一个virtual addr对应两个physical addr)和synonym(两个virtual addr对应同一个physical addr)的问题。homonym可以考flush TLB来解决,synonym就必须要搞到正确的物理地址才可以。
最终的解决方案是VIPT,virtual index physical tag。也就是说用virtual index直接把{tag,数据}取出来,同一个cycle virtual tag翻译成physical tag,在下一个cycle比较tag,选择数据可用/不可用了。这里可以用virtual index的条件是(virtual index bit + block offset bit) < page size 同时 page size * set associativity = cache size。在这种条件下virtual index实际上就是physical index。因为虚拟地址映射到物理地址时是以page为单位的,所以一个page内的address直接为物理地址。
从课本上学的也就这样了吧,其他的奇技淫巧真的要工作中实践过才知道有用没用。下一篇来讲缓存一致性 (cache coherency)。
既然收藏了就点个赞咯,鞠躬
reference:https://en.wikipedia.org/wiki/CPU_cache
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。