内存和缓存的如何聊天

本文将首先介绍缓存的基本概念,然后详细描述内存的结构与工作原理,最后阐述缓存和内存之间的数据通信方式。

不做特殊说明的话,本文涉及到的内容都基于x86体系

说说缓存

为什么需要缓存

延迟对比中看,2020年的设备延迟对比如下:

名称延迟对比
寄存器1滴答如果是2GHz主频的CPU,则时间为1/2G=0.5ns
L1缓存1ns
L2缓存4ns与L1缓存相比,差不多是声速(1224km/h)和高铁(300km/h)的差异, 4倍
Memory100ns与L2缓存相比,差不多是高铁(300km/h)和跑步(12km/h)的差别,25倍
SSD150μs与内存相比,慢了1500倍,差不多是跑步蜗牛的区别
HDD10ms与内存相比, 慢了10万倍,差不多是战斗机(2500km/h)和乌龟(20m/h)的区别;与SSD相比,慢了60倍,差不多是高铁走路的区别

可以看出,如果没有L1、L2等缓存的话,CPU的绝大多数时间将耗费在等待内存传输数据上。为了解决这一问题并提高处理速度,各种层次的缓存被引入到系统中,以减少延迟。

直观感受一下Linux的缓存

Linux下Cache Line的信息在/sys/devices/system/cpu/cpu[0-N]/cache/index[0-3]这个目录下,目录下的信息如下表所示:

文件名解释
coherency_line_size每个缓存行的大小
size缓存总大小
level缓存等级
type缓存类型(Data、Instruction、Unified)
shared_cpu_list哪几个CPU共享该缓存
number_of_sets缓存的组数
ways_of_associativity每组有多少路

每个CPU对应4个level的cache,一级缓存的指令和数据缓存,二级缓存和三级缓存。如果number_of_sets=64,ways_of_associativity=12,coherency_line_size=64,则size应该等于number_of_sets * ways_of_associativity * coherency_line_size = 64 * 12 * 64 = 48K。
这里需要特别提出的是,通常情况下,L1、L2、L3使用的是Inclusive方式(如下图所示),但是有的架构设计采用的是Non-Inclusive方式,即两层之间互相不包含数据,比如Intel Skylake的L3 Cache就不包含L2 Cache的数据,这里取决于架构设计。在这里插入图片描述

Inclusive
在这里插入图片描述

Non-Inclusive

说说内存(以DDR内存为例)

名词解释
  • DDR SDRAM: Double Data Rate Synchronous Dynamic Random-Access Memory
    • Double Data Rate的意思是可以在时钟周期的上沿和下沿传递两次数据
    • Dynamic的意思是因为电容的原因需要不停地充电
    • Random-Access就是支持随机访问,如同数组一样可以随机访问,比如树形结构就不支持随机访问
    • Synchronous的意思是,内存控制器(目前已嵌入到了CPU中,早期计算机是放在北桥芯片中)和内存条之间使用相同的时钟新号进行数据传输,确保他们在时序上协同工作
  • DIMM(Dual-Inline-Memory-Modules) 双列直插式存储模块,就是内存条本身,两面都有颗粒
  • SIMM(Single-Inline-Memory-Module) 单列直插式内存模块,也是内存条,单面有颗粒
  • 通道,就是CPU与内存之间的通路,有单通道、三通道、双通道、四通道等,每个通道都有独立的总线
  • Cell: 最小的存储单元,存储一个bit的信息,DRAM的一个cell由一个Transistor和一个Capacitor组成,SRAM则最少需要6个Transistor
  • Supercell: 若干个cell组成一个supercell,可能是8bit、16bit等,它是内存寻址的最小单元, 注意工业领域并没有看到Cell和Supercell相关的称呼
  • Rank: 提供64位数据能力,这就是内存的1R或者2R
  • Bank: 一个基本的数据矩阵管理单元,我查看了金士顿的相关产品,服务器使用的内存颗粒使用了多bank,台式机/笔记本上内存大多数是一个bank
DRAM内部寻址过程
  • 在这里插入图片描述
    , 该动画描述了一个行地址和列地址都是2bit,输出结果为8bit的存储模块的执行过程,图中每个格子是一个supercell

  • 如果要输出64bit的数据,只需要将多个这样的模块串联即可。在这里插入图片描述

  • 在实际中,需要看一个Chip提供多少位的数据

  • 举例子金士顿的一款台式机内存条,摘录以下片段来看

KVR64A52BD8-64 64GB 2Rx8 8G x 64-Bit PC5-6400 CL52 288-Pin CUDIMM
   This document describes ValueRAM's KVR64A52BD8-64 is a 8G x64-bit (64GB) DDR5-6400 CL52 Clocked Unbuffered DIMMs(CUDIMMs), 2Rx8, memory module, based on sixteen 4G x 8-bit
FBGA components and one Clock Driver (CKD). 

从该描述中可以看出,2Rx8 该内存条有个2个Rank,即可以提供两组64地址,8代表每个芯片颗粒是8bit,即最小寻址单元为8bit;8G x 64-bit是有8G个64bit的提供数据的能力,即864/8=64G;sixteen 4G x 8-bit
FBGA标识有16个内存颗粒,每个颗粒能提供4G
8bit=4GB的数据量,16*4=64GB。另外从2Rx8中也可以算出来16个颗粒,因为有2组,每组需要64/8个颗粒。

  • 前面提到了一些概念,他们之间的关系如下,一个内存条可能包含1-n个rank,一个rank中可能有bank或者没有bank,没有bank可以认为一个芯片是一个bank,bank内部是二维矩阵,内存寻址在bank中进行,寻址的最小单位就是supercell或者芯片的位宽。
  • 程序员眼中的8B(64bit)大概率上分布在不同的芯片中,除非使用了具有64bit位宽的内存颗粒。
地址如何转化为对内存的具体访问

它俩如何聊天

有了缓存之后,CPU和内存之间的物理拓扑大体如下:
在这里插入图片描述
,内存控制器已经被集成到CPU中,CPU直接通过内存总线或者说内存通道和内存通信。
我们知道物理地址是一个线性空间,而且比缓存要大很多,缓存如何与内存关联在一起呢,就是使用地址映射,具体如何映射呢,主要有以下三种方式。

映射机制
  • 直接映射
    • 一个内存地址只能被映射到特定缓存行中,这种方式缺点就是可能数据会被踢出太快,这也是最简单的方式,因为是1对1的
  • 完全关联缓存
    • 某一个内存地址可以被映射到任意一个缓存行,这种方式做数据替换很麻烦或者不现实,这个是1对N的
  • 组相联的方式
    • 某一个内存地址可以被映射到一组缓存, 这也是目前使用最多的缓存映射方式,具体应该如何映射,我们将物理地址分为Tag | Index | Offset四个部分,下图以16bit的地址为例,内存按照8个字节分组,Offset部分占用3bit,cache line一共4组,Index占用2bit,剩下的部分为Tag,头部追加valid字段,这样只要很少的空间代价(Tag+Valid)就能缓存8B的数据。在这里插入图片描述
最后但重要

目前,主流机器的总线宽度为64bit,而内存与CPU之间的最小传输单位是cache line(通常为64B)。即使需要访问一个字节的数据,CPU也会加载整个cache line到缓存中。以下几点需要特别注意:

  • L1缓存优先读取: CPU通常从L1缓存中读取数据。如果发生cache miss,数据会从较低级的缓存(如L2或L3)加载到L1缓存,或者直接绕过L1缓存加载到L2或更低级缓存。不过,绕过L1会增加布线复杂度。
  • 缓存行传输: 64B的数据需要通过64bit总线进行8次传输(每次8bit)。但并非必须等待8次传输完成才能通知CPU,具体取决于硬件设计。
  • 地址对齐: 传输到地址总线的地址通常会对齐到缓存行边界,Offset部分为0。在64bit总线中,地址的后6位必须为0,在32bit总线中,后5位为0。参见Intel® 64 and IA-32 Architectures Software Developer’s Manual
For Intel Core i7 processors and processors based on Intel Core, Intel Atom, and Intel NetBurst microarchitectures,Intel Core Duo, Intel Core Solo and Pentium M processors, the cache lines for the L1 and L2 caches (and L3 caches if supported) are 64 bytes wide. The processor always reads a cache line from system memory beginning on a 64-byte boundary. (A 64-byte aligned cache line begins at an address with its 6 least-significant bits clear.) 
The L1 and L2 cache lines in the P6 family and Pentium processors are 32 bytes wide, with cache line reads from system memory beginning on a 32-byte boundary (5 least-significant bits of a memory address clear.)

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值