cup缓存

  1. CPU缓存(CPU Cache)的目的是为了提高访问内存(RAM)的效率,这虽然已经涉及到硬件的领域,但它仍然与我们息息相关,了解了它的一些原理,能让我们写出更高效的程序,另外在多线程程序中,一些不可思议的问题也与缓存有关。
  2. 现代多核处理器,一个CPU由多个核组成,每个核又可以有多个硬件线程,比如我们说48线程,就是指有4个核,每个核2个线程,这在OS看来就像8个并行处理器一样。
  3. CPU缓存有多级缓存,比如L1, L2, L3等:
  4. L1容量最小,速度最快,每个核都有L1缓存,L1又专门针对指令和数据分成L1d(数据缓存),L1i(指令缓存)。
  5. L2容量比L1大,速度比L1慢,每个核都有L2缓存。
  6. L3容量最大,速度最慢,多个核共享一个L3缓存。
  7. 有些CPU可能还有L4缓存,不过不常见;此外还有其他类型的缓存,比如TLB(translation lookaside buffer),用于物理地址和虚拟地址转译,这不是我们关心的缓存。

下图展示了缓存和CPU的关系:

Linux用下面命令可以查看CPU缓存的信息:

  1. [root@sg-14 ~]# getconf -a | grep CACHE
  2. LEVEL1_ICACHE_SIZE 32768
  3. LEVEL1_ICACHE_ASSOC 8
  4. LEVEL1_ICACHE_LINESIZE 64
  5. LEVEL1_DCACHE_SIZE 32768
  6. LEVEL1_DCACHE_ASSOC 8
  7. LEVEL1_DCACHE_LINESIZE 64
  8. LEVEL2_CACHE_SIZE 262144
  9. LEVEL2_CACHE_ASSOC 4
  10. LEVEL2_CACHE_LINESIZE 64
  11. LEVEL3_CACHE_SIZE 6291456
  12. LEVEL3_CACHE_ASSOC 12
  13. LEVEL3_CACHE_LINESIZE 64
  14. LEVEL4_CACHE_SIZE 0
  15. LEVEL4_CACHE_ASSOC 0
  16. LEVEL4_CACHE_LINESIZE 0
  1. 上面显示CPU只有2级缓存,L3,L4都为0
  2. L1的数据缓存和指令缓存分别是32KBL22048KB,L36MB
  3. 在缓存和主存之间,数据是按固定大小的块传输的 该块称为缓存行(cache line),这里显示每行的大小为64Bytes
  4. ASSOC表示主存地址映射到缓存的策略,这里L1L28路组相联,L312路组相联,等一会儿再说是什么意思。

缓存结构

一块CPU缓存可以看成是一个数组,数组元素是缓存项(cache entry),一个缓存项的内容大概是这样的:

  1. +-------------------------------------------+
  2. | tag | data block(cache line) | flag |
  3. +-------------------------------------------+
  1. data block就是从内存中拷贝过来的数据,也就是我们说的cache line,从上面信息可知大小是64字节。
  2. tag 保存了内存地址的一部分,是用来验证是否缓存命中的。
  3. flag 是一些标志位,比如缓存是否失效,写dirty等等。
  4. 实际上LEVEL1_ICACHE_SIZE这个数据,是用data block来算的,并不包括tagflag占用的大小,比如64 x 512 = 32768,表示LEVEL1_ICACHE_SIZE可以缓存512cache line

缓存首先要解决的问题是:怎么映射内存地址和缓存地址?比如CPU要检查一个内存值是否已经缓存,那么它首先要能算出这个内存地址对应的缓存地址,然后才能检查。

为了解决这个问题,缓存将一个内存地址分成下面几个部分:

  1. +-------------------------------------------+
  2. | tag | index | offset |
  3. +-------------------------------------------+
  1. tag和缓存项中的tag对应,用来验证是否缓存命中的。
  2. index 缓存项数组中的索引。
  3. offset 缓存块(cache line)中的偏移,因为缓存块是64字节,而内存值可能只有4个字节,一个缓存块可以保存多个连续的内存值。这个offset实际上就是指明内存值在cache line中的位置。

直接映射缓存

现在我们举一个具体的例子,说明内存和缓存是如何映射的:

  • 假如缓存的大小是32768B(32KB),缓存块大小是64B,那么缓存项数组就有‭ 32768‬/64=512 个。

  • CPU要访问一个内存地址0x1CAABBDD‬,它首先检查这个内存地址是否在缓存中,检查过程是这样的:

  • 内存地址的二进制形式是(低位在前面):

    1. | tag | index | offset |
    2. 0 0 0 1 1 1 0 0 1 0 1 0 1 0 1 0 1 0 1 1 1 0 1 1 1 1 0 1 1 1 0 1
  1. 先计算内存在cache line中的偏移,因为缓存块是64字节,那么offset需要占6位(2^6=64),即offset=011101=29
  2. 接着要计算缓存项的索引,因为缓存项数组是512个,所以index需要占9位(2^9=512),即index=011101111=239
  3. 现在我们通过offsetindex已经找到缓存块的具体位置了,但是因为内存要远比缓存大很多,所以多个内存块是可以映射到同一个位置的,怎么判断这个缓存块位置存的就是这个内存的值呢?答案就是tag:内存地址去掉indexoffset的部分,剩下的就是tag=00011100101010101=0x3955
  4. 通过index找到缓存项,比较缓存项中的tag是否与内存地址中的tag相同,如果相同表示命中,就直接取缓存块中的值;如果不同表示未命中,CPU需要将内存值拷贝到缓存(替换掉老的)。
  5. 这种映射方式就称为直接映射(Direct mapped),它的缺点就是多个内存地址会映射到同一个缓存地址,拿上面的内存地址来看,只要offsetindex相同的内存地址,就一定会映射到同一个地方,比如:
  6. 00011100101010100 011101111 011101
  7. 00011100101010110 011101111 011101
  8. 00011100101010111 011101111 011101
  9. 如果同时访问上面3个地址,就会一直替换缓存的值,也就是一直出现缓存冲突,这可能比没有缓存还要慢,因为除了访问内存外,还多一个拷贝内存值到缓存的操作。

cup缓存基础知识的更多相关文章

  1. Django中的缓存基础知识

    由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5 ...

  2. 老司机带你玩转面试(1):缓存中间件 Redis 基础知识以及数据持久化

    引言 今天周末,我在家坐着掐指一算,马上又要到一年一度的金九银十招聘季了,国内今年上半年受到 YQ 冲击,金三银四泡汤了,这就直接导致很多今年毕业的同学会和明年毕业的同学一起参加今年下半年的秋招,这个 ...

  3. 【Java虚拟机4】Java内存模型(硬件层面的并发优化基础知识--缓存一致性问题)

    前言 今天学习了Java内存模型第一课的视频,讲了硬件层面的知识,还是和大学时一样,醍醐灌顶.老师讲得太好了. Java内存模型,感觉以前学得比较抽象.很繁杂,抽象. 这次试着系统一点跟着2个老师学习 ...

  4. JVM 基础知识

    JVM 基础知识(GC) 2013-12-10 00:16 3190人阅读 评论(1) 收藏 举报 分类: Java(49) 目录(?)[+] 几年前写过一篇关于JVM调优的文章,前段时间拿出来看了看 ...

  5. .NET面试题系列[1] - .NET框架基础知识(1)

    很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...

  6. Java基础知识(壹)

    写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...

  7. IOS开发基础知识碎片-导航

    1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...

  8. TCP/IP协议(一)网络基础知识

    参考书籍为<图解tcp/ip>-第五版.这篇随笔,主要内容还是TCP/IP所必备的基础知识,包括计算机与网络发展的历史及标准化过程(简述).OSI参考模型.网络概念的本质.网络构建的设备等 ...

  9. Oracle数据库基础知识

    oracle数据库plsql developer   目录(?)[-] 一     SQL基础知识 创建删除数据库 创建删除修改表 添加修改删除列 oracle cascade用法 添加删除约束主键外 ...

随机推荐

  1. 为何PostgreSQL即将超越SQL Server?

    DB-Engines 2021年10月份统计,PostgreSQL当月上升10.30点,总分是597.27:SQLServer当月大幅下降16.32,总分是954.29 .按照这样的速度,2年之内,P ...

  2. 【安全建设】日志监控的极品工具sysmon

    转载请注明出处:https://www.cnblogs.com/vitalemontea/p/16178048.html 1.前言 最近态势感知爆了某个同事有挖矿事件的告警,打开一看,就是会通过dns ...

  3. Docker 日志管理最佳实践

    开源Linux 回复"读书",挑选书籍资料~ Docker-CE Server Version: 18.09.6 Storage Driver: overlay2 Kernel V ...

  4. 为什么不建议给MySQL设置Null值?《死磕MySQL系列 十八》

    大家好,我是咔咔 不期速成,日拱一卒 之前ElasticSearch系列文章中提到了如何处理空值,若为Null则会直接报错,因为在ElasticSearch中当字段值为null时.空数组.null值数 ...

  5. svelte组件:svelte3.x自定义美化虚拟滚动条组件svelte-scrollbar

    基于svelte3.0自定义pc端虚拟滚动条组件svelteScrollbar. svelte-scrollbar:运用svelte3.x创建的桌面pc版自定义美化滚动条组件.支持是否原生滚动条.自动 ...

  6. GIL与普通互斥锁区别,死锁现象,信号量,event事件,进程池与线程池,协程

    GIL与普通互斥锁区别 GIL锁和互斥锁的异同点 相同: 都是为了解决解释器中多个线程资源竞争的问题 异: 1.互斥锁是Python代码层面的锁,解决Python程序中多线程共享资源的问题(线程数据共 ...

  7. 455. Assign Cookies - LeetCode

    Question 455. Assign Cookies Solution 题目大意:数组g的大小表示有几个小孩,每个元素表示小孩的食量,数组s的大小表示有多少个饼干,每个元素的大小表示每个饼干的大小 ...

  8. 【万字长文】使用 LSM Tree 思想实现一个 KV 数据库

    目录 设计思路 何为 LSM-Treee 参考资料 整体结构 内存表 WAL SSTable 的结构 SSTable 元素和索引的结构 SSTable Tree 内存中的 SSTable 数据查找过程 ...

  9. TENSEAL: A LIBRARY FOR ENCRYPTED TENSOR OP- ERATIONS USING HOMOMORPHIC ENCRYPTION 解读

    本文记录阅读该paper的笔记,这篇论文是TenSeal库的原理介绍. 摘要 机器学习算法已经取得了显著的效果,并被广泛应用于各个领域.这些算法通常依赖于敏感和私有数据,如医疗和财务记录.因此,进一步 ...

  10. MongoDB 分片集群

    每日一句 Medalist don't grow on trees, you have to nurture them with love, with hard work, with dedicati ...