一、CPU Cache

1、CPU Cache简介

CPU Cache是位于CPU与内存之间的临时存储器,容量比内存小但交换速度却比内存要快得多。Cache的出现主要是为了解决CPU运算速度与内存读写速度不匹配的矛盾,因为CPU运算速度要比内存读写速度快很多,会使CPU花费很长时间等待数据到来或把数据写入内存。在Cache中的数据是内存中的一小部分,但是CPU短时间内即将访问的,当CPU调用大量数据时,就可避开内存直接从Cache中调用,从而加快读取速度。Cache对CPU的性能影响很大,主要是因为CPU的数据交换顺序和CPU与Cache间的带宽引起的。

Cache工作原理是当CPU要读取一个数据时,首先从Cache中查找,如果找到就立即读取并送给CPU处理;如果没有找到,就用相对慢的速度从内存中读取并送给CPU处理,同时把数据所在的数据块调入Cache中,可以使得以后对整块数据的读取都从Cache中进行,不必再调用内存。

CPU读取Cache的命中率非常高(大多数CPU可达90%左右),大大节省了CPU直接读取内存的时间,也使CPU读取数据时基本无需等待。

按照数据读取顺序和与CPU结合的紧密程度,CPU Cache可以分为L1 Cache、L2 Cache、L3 Cache,每一级Cache中所储存的全部数据都是下一级Cache的一部分,三种Cache的技术难度和制造成本是相对递减的,所以其容量也是相对递增的。当CPU要读取一个数据时,首先从L1 Cache中查找,如果没有找到再从L2 Cache中查找,如果还是没有就从L3 Cache或内存中查找。通常每级Cache的命中率大概都在80%左右,即全部数据量的80%都可以在L1 Cache中找到,只剩下20%的总数据量才需要从L2 Cache、L3 Cache或内存中读取,因此L1 Cache是CPU Cache架构中最为重要的部分。

2、CPU Cache结构

Intel CPU中,8086、80286时代CPU是没有Cache的,因为当时CPU和内存速度差异并不大,CPU直接访问内存。但80386开始,CPU速度要远大于内存访问速度,第一次出现了Cache,而且最早的Cache并没有放在CPU模块,而放在主板上。CPU Cache的材质SRAM比内存DRAM贵很多,大小以MB为单位,因此现代计算机在CPU和内存之间引入了高速Cache,作为CPU和内存之间的通道。经过长期发展演化,逐步演化出了L1、L2、L3三级缓存结构,而且都集成到CPU芯片。

L1 Cache最接近于CPU,速度最快,但容量最小。现代CPU的L1 Cache会分成两个:数据Cache和指令Cache,指令和数据的更新策略并不相同,而且因为CISC的变长指令,指令Cache要做特殊优化。每个CPU核都有自己独立的L1 Cache和L2 Cache,但L3 Cache通常是整颗CPU共享。

3、CPU Cache查看

Linux内核开发者定义了CPUFreq系统查看CPU详细信息,/sys/devices/system/cpu目录保存了CPU详细信息。

L1 Cache查看

L2 Cache查看

L3 Cache查看

CPU Cache查看命令如下:


  1. dmidecode -t cache
  2. getconf -a | grep CACHE

CPU只有3级Cache,L4为0,L1 Cache数据缓存和指令缓存分别为32KB,L2 Cache为256KB,L3 Cache为3MB,Cache Line为64字节。ASSOC表示主存地址映射到缓存的策略,L1、L2是8路组相联,L3是12路组相联。

L1 Cache中数据Cache和指令Cache是物理CPU核共享的,因此,超线程技术虚拟出来的逻辑CPU核CPU0和CPU1共享L1 Cache。

4、Cache Line

Cache Line是CPU Cache中的最小缓存单位,是本级Cache向下一层取数据时的基本单位。目前主流的CPU Cache的Cache Line大小都是64Bytes,即当程序需要从内存中读取一个字节的时候,相邻的63字节同时会从内存中加载到CPU Cache中,当CPU访问相邻的数据的时候,并不会从内存中读取数据,而从CPU Cache中即可访问到数据,提高了速度。

L1、L2、L3的Cache Line大小都是64字节,可以通过如下查看:

cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size

CPU寄存器、Cache、内存的性能指标参考

CPU要访问的数据在Cache中有缓存,称为hit(命中),反之则称为miss(缺失)。

当CPU试图从某地址load数据时,首先从L1 Cache中查询是否命中,如果命中则把数据返回给CPU。如果L1 Cache缺失,则继续从L2 Cache中查找。当L2 Cache命中时,数据会返回给L1 Cache以及CPU。如果L2 Cache、L3 Cache也缺失,需要从主存中load数据,将数据返回给L3 Cache、L2 Cache、L1 Cache及CPU。

5、多核Cache一致性

每个CPU核都有一个私有的L1 Cache,对于多核CPU,不同CPU核之间的L1 Cache需要保证一致性。

(1)Bus Snooping Protocol

当某个CPU核修改自己私有Cache时,硬件会广播通知到总线上其它所有CPU核。每个CPU核都有特殊的硬件监听广播事件,并检查是否有相同的数据被缓存在自己的Cache。

Bus Snooping需要时刻监听总线上的一切活动,在一定程度上加重了总线负载,增加了读写延迟。

(2)MESI协议

MESI协议是一种使用状态机机制降低带宽压力来维护多核Cache一致性的协议。

MESI协议名称来源于cache line的4种状态Modified、Exclusive、Shared、Invalid的简写。当cache line状态是Modified或者Exclusive状态时,修改其数据不需要发送消息给其它CPU,在一定程度上减轻了带宽压力。

多核Cache一致性由硬件保证,现代CPU硬件采用的一致性协议通常是MESI协议的变种,如ARM64架构采用MOESI协议。

二、TLB

1、MMU简介

MMU(Memory Management Unit)是一种通过段机制和页机制将虚拟地址转换为物理地址的硬件电路,通常集成在CPU芯片内。

MMU通过建立页表,完成虚拟地址到物理地址的转换。当需要访问内存中的一个数据,通过数据的虚拟地址查找页表,一旦在页表命中,就通过找到的物理地址寻址到内存中的数据。如果页表中没有命中,表示页表中没有建立数据虚拟地址到物理地址的映射,通过缺页异常,建立数据的页表映射项。

对于频繁使用的不变数据,每次都回进行查找数据和相应页表项,为了加快页表查找速度,减少不必要的重复,引入TLB。

2、TLB简介

TLB( Translation Look- aside Buffer)专门用于缓存内存中的页表项,通常集成在MMU内部。TLB是一个很小的Cache,TLB表项( TLB entry)数量比较少,每个TLB表项包含一个页面的相关信息,例如有效位、虚拟页号、修改位、物理页帧号等。当处理器要访问一个虚拟地址时,首先会在TLB中查询。如果TLB表项中没有命中,就需要访问页表来计算出相应的物理地址。如果TLB表项中命中,直接从TLB表项中获取物理地址。

TLB内部存放的基本单位是TLB表项,TLB容量越大,所能存放的TLB表项就越多,TLB命中率就越高。但是TLB容量是有限的,目前Linux内核默认采用4KB大小的小页面,如果一个程序使用512个小页面,即2MB大小,那么至少需要512个TLB表项才能保证不会出现TLB Miss。但如果使用2MB大小的大页,只需要一个TLB表项就可以保证不会出现TLB Miss。对于消耗内存以GB为单位的大型应用程序,还可以使用以1GB为单位的大页,从而减少TLB Miss的情况。

TLB本质是页表的Cache,TLB缓存了最近使用的数据的页表项(虚拟地址到物理地址的映射)。TLB的出现是为了加快访问内存数据的速度,减少重复的页表查找,不是必须的,但TLB可以提高访问内存数据的速度。

3、TLB原理

当CPU要访问一个虚拟地址/线性地址时,CPU会首先根据虚拟地址的高20位(X86架构)在TLB中查找。如果是表中没有命中,需要通过访问慢速RAM中的页表计算出相应的物理地址。同时,物理地址被存放在一个TLB表项中,以后对同一线性地址的访问,直接从TLB表项中获取物理地址即可。

TLB结构如下:

如果一个需要访问内存中的一个数据,给定数据的虚拟地址,查询TLB,发现有(hit),直接得到物理地址,在内存根据物理地址读取数据。如果TLB没有命中(miss),只能通过页表来查找。

4、TLB映射方式

TLB内部存放的基本单位是TLB表项,对应着RAM中存放的页表条目。页表条目的大小固定不变的,所以TLB容量越大,所能存放的页表条目越多,TLB命中越大。但TLB容量毕竟是有限的,因此RAM页表和TLB表项无法做到一一对应。

(1)全相连

全相连方式,TLB cache中的表项和线性地址之间没有任何关系,一个TLB表项可以和任意线性地址的页表项关联。全相连方式关联方式使得TLB表项空间的利用率最大,但延迟也可能很大,因为每次CPU请求,TLB硬件都把线性地址和TLB表项逐一比较,直到TLB命中或者所有TLB表项比较完成。随着CPU Cache越来越大,需要比较大量TLB表项,所以只适合小容量TLB。

(2)直接匹配

每一个线性地址块都可通过模运算对应到唯一的TLB表项,只需进行一次比较,降低了TLB内比较延迟,但产生冲突的很大,导致TLB miss的发生,降低了命中率。

(3)组相连

为了解决全相连内部比较效率低和直接匹配的冲突,引入了组相连。组相连把所有的TLB表项分成多个组,每个线性地址块对应的不再是一个TLB表项,而是一个TLB表项组。CPU做地址转换时,首先计算线性地址块对应哪个TLB表项组,然后在TLB表项组按顺序比对。按照组长度,可以分为2路、4路、8路。

经过长期工程实践,发现8路组相连是一个性能分界点。8路组相连的命中率和全相连命中率相当,超过8路,组内对比延迟带来的缺点会超过命中率提高的优势。

三、超线程技术

1、超线程技术简介

超线程(Hyperthreading)技术在一个物理核上模拟两个逻辑核,两个逻辑核具有各自独立的寄存器(eax、ebx、ecx、msr等)和APIC,但会共享使用物理核的执行资源,包括执行引擎、L1/L2 Cache、TLB和系统总线等等。

2、超线程对性能影响

超线程技术仅仅是在一个物理核心上使用了两个物理任务描述符,物理计算能力并没有增加。采用多worker设计应用,在超线程的帮助下,两个被调度到同一核心不同超线程的worker,通过共享Cache、TLB,大幅降低了任务切换开销。在某个worker不忙的时候,超线程允许其它的worker也能使用物理计算资源,有助于提升物理核整体的吞吐量。但由于超线程对物理核执行资源的争抢,业务的执行时延也会相应增加。

开启超线程后,物理核总计算能力是否提升以及提升的幅度和业务模型相关,平均提升在20%-30%左右

当超线程相互竞争时,超线程的计算能力相比不开超线程时的物理核会下降30%左右

3、超线程应用

超线程开启或关闭取决于应用模型,对于时延敏感型任务,在节点负载过高时会引发超线程竞争,任务执行时长会显著增加,应该关闭超线程;对于后台计算型任务,建议开启超线程提高整个节点的吞吐量。

四、NUMA技术

1、NUMA简介

NUMA架构出现前,CPU朝着高频率方向发展收到物理极限的挑战,转而向着多核心的方向发展。由于所有CPU Core都通过共享一个北桥来读取内存,随着CPU核数增加,北桥在响应时间上的性能瓶颈越来越明显。因此,硬件设计师把内存控制器从北桥中拆分出来,平分到每个CPU Core上,即NUMA架构。

NUMA(Non-Uniform Memory Access)起源于AMD Opteron微架构,同时被Intel Nehalem采用。

NUMA架构将整台服务器分为若干个节点,每个节点上有单独的CPU和内存。只有当CPU访问自身节点内存对应的物理地址时,才会有较短的响应时间(后称Local Access)。而如果需要访问其他节点的内存数据时,需要通过inter-connect通道访问,响应时间变慢(后称Remote Access)。所以NUMA(Non-Uniform Memory Access)就此得名。

在Node内部,使用IMC Bus进行不同核心间的通信;不同的Node 间通过QPI(Quick Path Interconnect)进行通信。

一个Socket(内存插槽)对应一个Node,QPI的延迟要高于IMC Bus,CPU访问内存存在远近(remote/local)。

2、NUMA缺陷

NUMA架构的内存分配策略对于进程或线程是不公平的。RHEL Linux中,localalloc是默认的NUMA内存分配策略,即从当前node上请求分配内存,会导致资源独占程序很容易将某个node的内存用尽。而当某个node的内存耗尽时,Linux刚好将CPU node分配给某个需要消耗大量内存的进程(或线程),此时将产生swap。

3、NUMA应用

(1)BIOS关闭NUMA

BIOS的Memory Setting菜单找到Node Interleaving项,设置为Disabled表示启用NUMA,非一致访问方式访问,是默认配置;设置为Enabled表示关闭NUMA,采用SMP方式启用内存交错模式。

(2)软件层次关闭NUMA

启动应用前使用numactl –interleave=all修改NUMA策略即可。

如果应用会占用大规模内存,应该选择关闭NUMA Node限制(或从硬件关闭NUMA);如果应用并不占用大内存,而要求更快的程序运行时间,应该选择限制只访问本NUMA Node方法来进行处理。

检查BIOS是否开启NUMA

grep -i numa /var/log/dmesg

检查当前系统的NUMA节点

numactl --hardware

lscpu

查看内存数据

numastat

当发现numa_miss数值比较高时,说明需要对分配策略进行调整,如将进程绑定到指定CPU上,从而提高内存命中率。

在开启NUMA支持的Linux中,Kernel不会将任务内存从一个NUMA node迁移到另一个NUMA node。

进程一旦启动,所在NUMA node就不会被迁移,为了尽可能的优化性能,在正常的调度之中,CPU的core也会尽可能的使用可以local访问的本地core,在进程的整个生命周期之中,NUMA node保持不变。

一旦当某个NUMA node负载超出另一个node一个阈值(默认25%),则认为需要在此node上减少负载,不同的NUMA结构和不同的负载状况,系统见给予一个延时任务的迁移——类似于漏杯算法。在这种情况下将会产生内存的remote访问。

NUMA node之间有不同的拓扑结构,不同node间的访问会有一个距离概念,可以使用numactl -H进行查看。

4、NUMA Node绑定

numactl [--interleave nodes] [--preferred node] [--membind nodes] [--cpunodebind nodes] [--physcpubind cpus] [--localalloc] command

--interleave=nodes, -i nodes用于设定内存的交织分配模式,系统在为多个节点分配内存空间时,将会以轮询分发的方式被分配给多个节点。如果在当前众多的交织分配内存节点中的目标节点无法正确的分配内存空间,内存空间将会由其它的节点来分配。
--membind=nodes, -m nodes从指定节点中分配内存空间,如果节点内存空间不足,分配操作将会失败。
--cpunodebind=nodes, -N nodes用于绑定进程到CPU Node。

--physcpubind, -C cpus用于把进程绑定到CPU核心上。
--localalloc , -l 启动进程,并在当前CPU节点分配内存。
--preferred=node用于指定优先分配内存空间的节点,如果无法在节点分配空间,会从其它节点分配。

numactl --cpubind=0 --membind=0 python param
numactl --show显示当前NUMA机制

numactl --hardware显示当前系统中有多少个可用的节点。
numactl [--huge] [--offset offset] [--shmmode shmmode] [--length length] [--strict]

创建共享内存段

文章知识点与官方知识档案匹配,可进一步学习相关知识
CS入门技能树Linux入门初识Linux30403 人正在系统学习中
量化IT技术交流群


QQ群名片

【转帖】Linux性能优化(十四)——CPU Cache的更多相关文章

  1. Linux性能优化 第四章 性能工具:特定进程CPU

    4.1进程性能统计信息 4.1.1. 内核时间VS用户时间 一个应用程序所耗时间最基本的划分是内核时间与用户时间.内核时间是消耗在Linux内核上的时间,而用户时间则是消耗在应用程序或库代码上的时间. ...

  2. 深挖计算机基础:Linux性能优化学习笔记

    参考极客时间专栏<Linux性能优化实战>学习笔记 一.CPU性能:13讲 Linux性能优化实战学习笔记:第二讲 Linux性能优化实战学习笔记:第三讲 Linux性能优化实战学习笔记: ...

  3. Linux 性能优化之 IO 子系统 系列 图

    http://blog.sina.com.cn/s/articlelist_1029388674_11_1.html Linux 性能优化之 IO 子系统(一) 本文介绍了对 Linux IO 子系统 ...

  4. Linux 性能优化解析

    前情概述 进程调度 老板 cpu 任劳任怨的打工仔 线程 工作在做什么 可运行队列 拥有的工作清单 上下文切换 和老板沟通以便得到老板的想法并及时调整自己的工作 中断 部分工作做完以后还需要及时向老板 ...

  5. Linux 性能优化排查工具

    下图1为 Linux 性能优化排查工具的总结 图1 诊断 CPU 工具 查看 CPU 核数 总核数 = 物理CPU个数 X 每颗物理CPU的核数 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU ...

  6. Linux性能优化从入门到实战:01 Linux性能优化学习路线

      我通过阅读各种相关书籍,从操作系统原理.到 Linux内核,再到硬件驱动程序等等.   把观察到的性能问题跟系统原理关联起来,特别是把系统从应用程序.库函数.系统调用.再到内核和硬件等不同的层级贯 ...

  7. Linux性能优化-平均负载

    Linux性能优化-平均负载 目录 Linux性能优化-平均负载 平均负载的含义 平均负载为多少时合理 平均负载与 CPU 使用率 平均负载案例分析 场景一:CPU 密集型进程 场景二:I/O 密集型 ...

  8. Linux学习之十四、管线命令

    Linux学习之十四.管线命令 地址:http://vbird.dic.ksu.edu.tw/linux_basic/0320bash_6.php

  9. 如何学习Linux性能优化?

    如何学习Linux性能优化? 你是否也曾跟我一样,看了很多书.学了很多 Linux 性能工具,但在面对 Linux 性能问题时,还是束手无策?实际上,性能分析和优化始终是大多数软件工程师的一个痛点.但 ...

  10. Linux性能优化实战学习笔记:第四十三讲

    一.上节回顾 上一节,我们了解了 NAT(网络地址转换)的原理,学会了如何排查 NAT 带来的性能问题,最后还总结了 NAT 性能优化的基本思路.我先带你简单回顾一下. NAT 基于 Linux 内核 ...

随机推荐

  1. hiveSQL常见专题

    SQL强化 SQL执行顺序 --举例: select a.sex, b.city, count(1) as cnt, sum(salary) as sum1 from table1 a join ta ...

  2. Navicat 携手华为云GaussDB,联合打造便捷高效的数据库开发和建模工具方案

    本文分享自华为云社区<Navicat 携手华为云GaussDB,联合打造便捷高效的数据库开发和建模工具方案>,作者: GaussDB 数据库 . 近日, Navicat Premium顺利 ...

  3. ROMA Connect: 5大联接能力+4大集成能力,推进企业数字化转型

    摘要:ROMA Connect是一个全栈式的应用与数据集成平台,源自华为数字化转型集成实践,聚焦应用和数据连接,适配多种企业常见的使用场景. 本文分享自华为云社区<数据融合集成平台ROMA Co ...

  4. 云图说 | 华为云医疗智能体,智联大健康,AI药物研发

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:华为云医疗智能体面 ...

  5. 大力出奇迹,揭秘昇腾CANN的AI超能力

    摘要:CANN(Compute Architecture for Neural Networks)异构计算架构,是以提升用户开发效率和释放昇腾AI处理器极致算力为目标,专门面向AI场景的异构计算架构. ...

  6. 万字详解什么是生成对抗网络GAN

    摘要:这篇文章将详细介绍生成对抗网络GAN的基础知识,包括什么是GAN.常用算法(CGAN.DCGAN.infoGAN.WGAN).发展历程.预备知识,并通过Keras搭建最简答的手写数字图片生成案. ...

  7. 中国人的 Java 生态,Solon v2.5.3 发布

    Solon 是什么? 国产的 Java 应用开发框架.从零开始构建,有自己的标准规范与开放生态(历时五年,具备全球第二级别的生态规模).与其他框架相比,解决了两个重要的痛点:启动慢,费内存. 关键记事 ...

  8. PPT 难吗

    多看 http://www.zcool.com.cn/ http://www.huaban.com

  9. 智能制造之 SMT 产线监控管理可视化

    前言 随着<中国制造2025>的提出,制造业迎来了全新的发展机遇.更多的企业将制造业信息化技术进行广泛的应用,如 MES 系统.数字孪生以及生产管理可视化等技术的研究应用,已经成为社会各界 ...

  10. Jinfo 查看 jvm 配置及使用 Jstat 查看堆内存使用与垃圾回收

    本文为博主远传,未经允许不得转载: 1. Jinfo 查看正在运行的Java应用程序的扩展参数: 包含 JVM 参数与 java 系统参数 命令:  jinfo pid 2. 使用 jstat 查看堆 ...