当前位置: 首页 > Linux

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

时间:2023-04-06 19:46:13 Linux

一般我们开发同学都知道自己的机器有多少CPU核心,多少内存。而对程序性能影响较大的CPU内部的缓存却知之甚少。有的开发同学的电脑缓存都是L1、L2、L3的,但是比较细的问题,可能很少有同学能回答完整。如果您能脱口而出以下问题,请跳过本节。例如:缓存到底在哪里?L1有多少种?您的缓存有多少级,它们有多大?你的24核机器,一级、二级、三级缓存分别是多少,有分享吗?其实缓存对计算机程序的性能影响很大,但是在开发同学心目中的存在感没有内存那么高。要知道CPU缓存和缓存算法的设计是现代CPU设计的核心任务之一。飞哥觉得宝藏们一定很难过。IntelCPU架构在286之前的时代其实是没有缓存的,因为那时候CPU和内存速度的差距没有现在这么大,CPU直接访问内存。但是到了386时代,CPU和内存的速度不匹配,第一次出现了缓存。并且最早的缓存并没有放在CPU模块中,而是放在了主板上。以后CPU的速度会越来越快,现在CPU的速度比内存快了一百多倍,所以L1、L2、L3的三级缓存结构也逐渐演变而来,并且都集成到CPU芯片中,进一步提高了访问速度。.让我们看一下现代IntelCPU架构的基本结构。L1距离CPU最近,速度最快,但容量最小。通常,现代CPU的L1分为两个,一个用于缓存数据,另一个用于缓存代码。这是因为代码和数据的更新策略不同,而且由于CISC变长指令,代码缓存需要特别优化。一般每个核都有自己独立的数据L1和代码L1。你走得越低,速度越慢,容量越大。L2一般也可以独立于每个核心。但是L3一般是整个CPU共享的。UEFIBlog提供了更好的物理解剖图,更好的展示:上面介绍的实际视图只是一个大概的概念。但是每个CPU的缓存都不一样,“纸上谈兵”,我觉得还需要进行下一步的实机探索。Linux内核的开发者定义了一套框架模型来完成这个目的,这就是CPUFreq系统。CPUFreq提供的sysfs接口可以让我们看到比/proc/cpuinfo更详细的CPU细节。#cd/sys/devices/system/cpu/;lldrwxr-xr-x7rootroot0Apr1515:29cpu0drwxr-xr-x7rootroot0Apr1515:29cpu1......L1one级别缓存查看:#catcpu0/cache/index0/level1#catcpu0/cache/index0/size32K#catcpu0/cache/index0/typeData#catcpu0/cache/index0/shared_cpu_list0,12#catcpu0/cache/index1/level1#catcpu0/cache/index1/size32K#catcpu0/cache/index1/typeInstruction#catcpu0/cache/index1/shared_cpu_list0,12从上面的level接口可以看出,这两个index0而index1是一级缓存,只不过一个是Data数据缓存,一个是Instruction,也就是代码缓存。等等,上面说了每个Core都是一个独立的L1缓存,为什么shared_cpu_list显示有共享呢?对了,我们这里看到的cpu0并不是物理核心,而是逻辑核心,是通过超线程技术虚拟出来的。实际上cpu0和cpu12属于一个物理Core,所以每一个DataL1和Instruction都是这两个逻辑core共享的。在我的电脑中,一共有12个DataL1和12个InstructionL1,大小都是32K。二级缓存查看:#catcpu0/cache/index2/size256K#catcpu0/cache/index2/typeUnified#catcpu0/cache/index2/shared_cpu_list0,12二级缓存比一级缓存大很多。有256K,但是Data和Instruction没有区别。另外,L2和L1一样,一共有12个,每两个逻辑核心共用一个L2。L3三级缓存查看:#catcpu0/cache/index3/size12288K#catcpu0/cache/index3/typeUnified#catcpu0/cache/index3/shared_cpu_list0-5,12-17#catcpu6/cache/index3/shared_cpu_list6-11、18-23L3达到了12M。当你购买CPU时,你在产品中看到的缓存属性一般都会告诉你这个L3属性。因为L3看起来比L2和L1大很多,所以更能激发你的购买欲望。但实际上,我的电脑里只有两个L3,每个CPU一个,不像很多L2和L1。逻辑核心0-5、12-17共享一个L3,因为它们位于一个物理CPU上。6-11、18-23又分享了一个。另外Linux上还有一个dmidecode命令,也可以查看CPU缓存的一些信息。有兴趣的朋友可以试试#dmidecode-tcache可能有同学会问,我用的操作系统是windows啊,你觉得呢?打开cmd命令行,输入以下命令试试看,飞哥在windows上就知道这么多了,有兴趣的可以自己google一下。#wmiccpugetL2CacheSize,L3CacheSize扩展知识CacheLine:我们只介绍了每一级的缓存,但是这里有一个很重要的概念就是CacheLine,它是本级缓存从下一级缓存取数据时的基本单位层。可以通过以下方式查看:#cd/sys/devices/system/cpu/;ll#catcpu0/cache/index0/coherency_line_size64#catcpu0/cache/index1/coherency_line_size64#catcpu0/cache/index2/coherency_line_size64#catcpu0/cache/index3/coherency_line_size64可以看到L1、L2、L3的CacheLine大小都是64字节(注意是字节)。也就是说,CPU每次从内存中取数据,都是在这个单元中完成的。即使你只取一个bit,CPU也会为你取一个CacheLine放到各级缓存中存储。请记住这个概念,我们将在以后的文章中使用它。练内功专用CPU:1、你以为你的多核CPU是真核生物吗?多核“错觉”2、听说你只知道内存,不知道缓存?CPU表示很伤心!3.TLB缓存是个鬼,如何查看TLBmiss?4、进程/线程切换需要多少开销?5、协程比线程好在哪里?6.softirq会吃掉多少CPU?7、一次系统调用的开销是多少?8、一个简单的php请求redis的开销是多少?9、函数调用过多会不会有性能问题?我的公众号是“练内功练功”。在这里,我不是简单地介绍技术理论,也不是只介绍实践经验。而是理论联系实际,用实践加深对理论的理解,用理论提高技术实践能力。欢迎关注我的公众号,分享给你的朋友吧~~~