美文网首页开发者内功修炼
听说你只知内存,而不知缓存?CPU表示很伤心!

听说你只知内存,而不知缓存?CPU表示很伤心!

作者: yanfeizhang | 来源:发表于2019-08-07 12:29 被阅读0次

    一般我们的开发同学们都知道自己机器的CPU是几核、内存是多大。但是对于CPU内部对程序性能影响较大的缓存却是一知半解。有些开发同学都是计算机的缓存有L1、L2、L3,但是再详细一点的问题,可能就很少有同学能答的完整了。如果下面这几个问题你能脱口而出,请跳过本节。例如:

    • 缓存究竟在哪里?
    • L1有几种?
    • 你的缓存有几级,分别是多大?
    • 你的24核的机器,一二三级缓存分别有几个,存在共享的情况吗?

    其实缓存对计算机程序运行性能影响极大,但是他们在开发同学心目中的存在感却不如内存高。要知道CPU缓存以及缓存算法的设计是现代CPU设计的核心任务之一。飞哥觉得缓存们一定感到很伤心。

    Intel CPU体系结构

    其实在286之前的时代的CPU本是没有缓存的,因为当时的CPU和内存速度差异没有现在这么大,CPU直接访问内存。但是到386时代,CPU和内存的速度不匹配了,第一次出现了缓存。而且最早的缓存并没有放在CPU模块里,而是放在主板上的。再往后CPU越来越快,现在CPU的速度比内存要快百倍以上,所以就逐步演化出了L1、L2、L3三级缓存结构,而且都集成到的CPU芯片里,以进一步提高访问速度。

    我们来看下现代Intel的CPU架构的基本结构。

    图1.png

    L1最接近于CPU,速度也最快,但是容量最小。一般现代CPU的L1会分成两个,一个用来cache data,一个用来cache code,这是因为code和data的更新策略并不相同,而且因为CISC的变长指令,code cache要做特殊优化。 一般每个核都有自己独立的data L1和code L1。
    越往下,速度越慢,容量越大。L2一般也可以做到每个核一个独立的。但是L3一般就是整颗CPU共享的了。
    UEFIBlog里提供了一个比较好的物理解剖图,比较好地展示了出来:

    图2.jpg

    实际查看

    上面介绍的只是笼统的概念。但是每个CPU的缓存都是不一样的,而且“纸上得来终觉浅”,我觉得我们还是有必要进行下一步的实机勘探工作。

    Linux的内核的开发者定义了一套框架模型来完成这一目的,它就是CPUFreq系统。
    CPUFreq提供的sysfs接口,可以让我们看到比/proc/cpuinfo更为详细的CPU详细信息。

    # cd /sys/devices/system/cpu/;ll
    drwxr-xr-x 7 root root    0 Apr 15 15:29 cpu0  
    drwxr-xr-x 7 root root    0 Apr 15 15:29 cpu1  
    ......
    
    • L1一级缓存查看:
    # cat cpu0/cache/index0/level  
    1  
    # cat cpu0/cache/index0/size  
    32K  
    # cat cpu0/cache/index0/type  
    Data  
    # cat cpu0/cache/index0/shared_cpu_list  
    0,12  
    # cat cpu0/cache/index1/level  
    1
    # cat cpu0/cache/index1/size  
    32K  
    # cat cpu0/cache/index1/type  
    Instruction  
    # cat cpu0/cache/index1/shared_cpu_list  
    0,12
    

    从上面的level接口可以看出index0和index1都是一级缓存,只不过一个是Data数据缓存,一个是Instruction也就是代码缓存。
    等等,上面提到的是每个Core是独立的L1缓存,为什么shared_cpu_list显示有共享?对了我们这里看到的cpu0并不是物理Core,而是逻辑核,都是超线程技术虚拟出来的。 实际上cpu0和cpu12是属于一个物理Core,所以每个Data L1和Instruction是这两个逻辑核共享的。
    我的这台电脑里,总共是有12个Data L1,12个Instrunction L1,大小都是32K。

    • L2二级缓存查看:
    # cat cpu0/cache/index2/size  
    256K  
    # cat cpu0/cache/index2/type 
    Unified  
    # cat cpu0/cache/index2/shared_cpu_list  
    0,12  
    

    二级缓存要比一级缓存大不少,有256K,但是不分Data和Instruction。另外L2和L1一样,也是总共有12个,每两个逻辑核共享一个L2。

    • L3三级缓存查看:
    # cat cpu0/cache/index3/size  
    12288K  
    # cat cpu0/cache/index3/type  
    Unified  
    # cat cpu0/cache/index3/shared_cpu_list  
    0-5,12-17  
    #cat cpu6/cache/index3/shared_cpu_list  
    6-11,18-23  
    

    L3达到了12M,你去买CPU的时候商品里能看到的缓存属性一般告诉你的就是这个L3属性。因为L3要比L2和L1看起来要大的多,能激发你购买的欲望。但实际上我的这台电脑里L3只有两个,每个CPU各一个,不像是L2、L1有很多。第0-5,12-17号逻辑核共享一个L3,因为它们是在一个物理CPU上。6-11,18-23共享另一个。

    另外,Linux上还有个dmidecode命令,也能查看到一些关于CPU缓存的信息,感兴趣的小伙伴们可以试试

    # dmidecode -t cache
    

    可能有的同学会问了,我用的操作系统是windows啊,怎么看?打开cmd命令行,输入以下命令试试吧,飞哥在windows上知道的就这么多了,感兴趣的话你自己google上搜搜吧。

    # wmic cpu get L2CacheSize,L3CacheSize
    

    扩展知识

    Cache Line:我们前面只介绍了各个级别的缓存,但是这里面有个很重要的概念就是Cache Line,就是本级缓存向下一层取数据时的基本单位。可以通过如下方式查看:

    # cd /sys/devices/system/cpu/;ll
    # cat cpu0/cache/index0/coherency_line_size
    64
    # cat cpu0/cache/index1/coherency_line_size
    64
    # cat cpu0/cache/index2/coherency_line_size
    64
    # cat cpu0/cache/index3/coherency_line_size
    64
    

    可以看到L1、L2、L3的Cache Line大小都是64字节(注意是字节)。就是说每次cpu从内存获取数据的时候,都是以该单位来进行的,哪怕你只取一个bit,CPU也是给你取一个Cache Line然后放到各级缓存里存起来。请大家牢牢记住这个概念,以后的文章中我们会用到。

    欢迎关注个人公众号“开发内功修炼”,打通理论与实践的任督二脉

    参考文件

    相关文章

      网友评论

        本文标题:听说你只知内存,而不知缓存?CPU表示很伤心!

        本文链接:https://www.haomeiwen.com/subject/tclodctx.html