当前位置:首页 > 知识百科

寄存器地址怎么理解(0x1000寄存器地址在哪定义)

2022-11-04 16:28:27

  一、缓存Cache

  我们看到CPU参数经常会提到1、2、3级缓存容量,有时还有L1$的标识,这是什么呢。

  TLB与两级缓存

  资料来源:互联网

  缓存(Cache)是指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,通常缓存不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。

  缓存的工作原理是当CPU要读取一个数据时,首先从CPU缓存中查找,找到就立即读取并送给CPU处理;没有找到,就从速率相对较慢的内存中读取并送给CPU处理,同时把这个数据所在的数据块调入缓存中,可以使得以后对整块数据的读取都从缓存中进行,不必再调用内存。正是这样的读取机制使CPU读取缓存的命中率非常高(大多数CPU可达90%左右),也就是说CPU下一次要读取的数据90%都在CPU缓存中,只有大约10%需从内存读取。这大大节省了CPU直接读取内存的时间,也使CPU读取数据时基本无需等待。总体而言,CPU读取数据的顺序是先缓存后内存。

  一级缓存即L1 Cache,因为Cache的发音与英语现金Cash的发音相同,因此有时写做L1$。一级缓存分指令和数据,二级缓存即L2 Cache,不分指令和数据。一级缓存是每个核独有,少量多核如12核以上二级缓存是4个或多个核共享,大部分二级缓存是每个核独有的,三级缓存即L3 Cache是通过总线与内核连接的,是多个核共用的。

  因为缓存使用SRAM,其晶体管密度低,所占面积大,这就意味着成本高,简单地说,缓存用的越多,成本就越高,性能就越强。Cache存储数据是固定大小为单位的,称为一个Cache entry,这个单位称为Cache line或Cacheblock。给定Cache容量大小和Cache line size的情况下,它能存储的条目个数(number of cache entries)就是固定的。因为Cache是固定大小的,所以它从DRAM获取数据也是固定大小。对于X86来讲,它的Cache line大小与DDR3、4一次访存能得到的数据大小是一致的,即64Bytes。通常L1 Cache离CPU核心需要数据的地方更近,而L2 Cache则处于边缓位置,访问数据时,L2 Cache需要通过更远的铜线,甚至更多的电路,从而增加了延时。

  L1 Cache分为ICache(指令缓存)和DCache(数据缓存),指令缓存ICache通常是放在CPU核心的指令预取单元附近的,数据缓存DCache通常是放在CPU核心的load/store单元附近。而L2 Cache是置于CPU pipeline之外的。还有L3缓存,通常是多核共享的缓存,容量更大。

  缓存是逐级的,1级缓存中找不到,就到2级缓存里找,然后是3级,最后是芯片外的存储器。

  由于内存种类多,需要引入内存管理单元,即MMU。MMU是硬件设备,它被保存在主存(main memory)的两级页表控制,MMU的主要作用是负责从CPU内核发出的虚拟地址到物理地址的映射,并提供硬件机制的内存访问权限检查。MMU使得每个用户进程拥有自己的地址空间,并通过内存访问权限的检查保护每个进程所用的内存不被其他进程破坏。

  处理器引入MMU后,读取指令、数据需要访问两次内存:首先通过查询页表得到物理地址,然后访问该物理地址读取指令、数据。为减少因MMU导致的处理器性能下降,引入了TLB,TLB是Translation Lookaside Buffer的简称,可翻译为“地址转换后缓冲器”,亦简称为“快表”。简单地说,TLB就是页表的Cache,其中存储了当前最可能被访问到的页表项,其内容是部分页表项的一个副本。只有在TLB无法完成地址翻译任务时,才会到内存中查询页表,这样就减少了页表查询导致的处理器性能下降。

  什么是页表(Page Table)这是操作系统里的一个术语,操作系统的一个主要任务是将程序彼此隔离。因此需要建立不同的内存空间,也就是需要给内存安排不同的地址。页表通常是操作系统决定的。对于32位操作系统,如果想支持32位的操作系统下的4GB进程虚拟地址空间,假设页表大小为4K,则共有2的20次方页面。如果采用速度最快的1级页表,对应则需要2的20次方个页表项。一个页表项假如4字节,那么一个进程就需要(1048576*4=)4M的内存来存页表项。这太大了,成本太高,因此需要分级,采用2级页表,则创建进程时只需有一个页目录就可以了,占用(1024*4)=4KB的内存。剩下的二级页表项只有用到的时候才会再去申请。若是64位,则需要4级页表,Linux在v2.6.11以后,最终采用的方案是4级页表,分别是:

  PGD:Page Global Directory(47-39),页全局目录

  PUD:Page Upper Directory(38-30),页上级目录

  PMD:Page Middle Directory(29-21),页中间目录

  PTE:Page Table Entry(20-12),页表项

  对于任何一条带有地址的指令,其中的地址应该认为是虚拟内存地址而不是物理地址。假设寄存器a0中是地址0x1000,那么这是一个虚拟内存地址。虚拟内存地址会被转到内存管理单元(MMU,Memory Management Unit)并翻译成物理地址。之后这个物理地址会被用来索引物理内存,并从物理内存加载,或者向物理内存存储数据。从CPU的角度来说,一旦MMU打开了,它执行的每条指令中的地址都是虚拟内存地址。为能够完成虚拟内存地址到物理内存地址的翻译,MMU会有一个表单,表单中,一边是虚拟内存地址,另一边是物理内存地址。

  分页技术的核心思想是将虚拟内存空间和物理内存空间视为固定大小的小块,虚拟内存空间的块称为页面(pages),物理地址空间的块称为帧(frames),每一个页都可以映射到一个帧上。每个page创建一条表单条目,所以每一次地址翻译都是针对一个page。而RISC-V中,一个page是4KB,也就是4096Bytes。对于虚拟内存地址,我们将它划分为两个部分,index和offset,index用来查找page,offset对应的是一个page中的哪个字节。当MMU在做地址翻译的时候,通过读取虚拟内存地址中的index可以知道物理内存中的page号,这个page号对应了物理内存中的4096个字节。之后虚拟内存地址中的offset指向了page中的4096个字节中的某一个,假设offset是12,那么page中的第12个字节被使用了。将offset加上page的起始地址,就可以得到物理内存地址。

  页表是存在内存里的。那就是一次内存I/O光是虚拟地址到物理地址的转换就要去内存查4次页表,再算上真正的内存访问,最坏情况下需要5次内存I/O才能获取一个内存数据,这太费时间,也导致功耗增加,于是TLB诞生了,TLB就是页表缓存。

  当CPU执行机构收到应用程序发来的虚拟地址后,首先到TLB中查找相应的页表数据,MMU从TLB中获取页表,翻译成物理地址,如果TLB中正好存放着所需的页表,则称为TLB命中(TLB Hit),接下来CPU再依次看TLB中页表所对应的物理内存地址中的数据是不是已经在一级、二级缓存里了,若没有则到内存中取相应地址所存放的数据。如果TLB中没有所需的页表,则称为TLB失败(TLB Miss),接下来就必须访问物理内存中存放的页表,同时更新TLB的页表数据。

  TLB也分指令和数据。

  典型架构Cortex-A78缓存指令流程

  图片来源:ARM

  MOP缓存是一些经过预处理指令的融合操作缓存。

  二、超标量

  早期的计算机都是串行计算,随着对吞吐量需求越来越高,并行计算出现了。常见的并行计算有三种指令并行、数据并行和任务并行。任务并行更多借助软件才能实现。对硬件来说有指令并行(ILP)、线程并行和数据并行三种。

  指令级并行是一种隐式并行,对用户来说是完全透明的,用户完全看不到也感觉不到,也就是写程序的人不需要关注,通过流水线和超标量,使得一个程序的指令序列中有多条同时乱序运行,顺序提交。这依赖寄存器重命名、多个执行单元、重排序缓冲和指令预测技术。

  线程级并行是一种显式并行,对用户来说不透明,也就是说程序员要写多线程程序。线程级并行主要指同时多线程(SMT)或超线程(HT)以及多核和多处理器。SMT是在指令级并行的基础上的扩展,可以在一个核上运行多个线程,多个线程共享执行单元,以便提高部件的利用率,提高吞吐量。SMT需要为每个线程单独保持状态,如程序计数器(PC)、寄存器堆、重排序缓冲等。

  数据级并行是一种显式并行,主要指单指令多数据(SIMD),比如a,b和c都是相同大小的数组,要进行的计算是a的每一个元素与b的响应元素进行运算,结果放入c的对应元素中。如果没有SIMD,就需要写一个循环执行多遍来完成,而SIMD中一条指令就可以并行地执行运算。线程的概念就是程序的执行序,每个执行序有执行上下文需要保存。

  传统的通用处理器都是标量处理器,一条指令执行只得到一个数据结果。但对于图像、信号处理等应用,存在大量的数据并行性计算操作,这些数据都具备方向,一般称为向量计算。

  超标量(Superscalar)是指在CPU中有一条以上的流水线,并且每时钟周期内可以完成一条以上的指令,这种设计就叫超标量技术。其实质是以空间换取时间。而超流水线是通过细化流水、提高主频,使得在一个机器周期内完成一个甚至多个操作,其实质是以时间换取空间。

  超标量CPU的工作流程如下:

  (1)Fetch(取指令):这部分负责从I-Cache中取指令,I-Cache负责存储最近常用的指令;分支预测器用来决定下一条指令的PC值。

  (2)Decode(解码):识别指令的类型

  (3)RegisterRenaming(寄存器重命名):解决WAW和WAR这两种“伪相关性”,需要使用寄存器重命名的方法,将指令集中定义的逻辑寄存器重命名为处理器内部使用的物理寄存器。物理寄存器的个数更多于逻辑寄存器,处理器可以调度更多可以并行执行的指令。将存在RAW的寄存器进行标记,后续通过旁路网络(bypassing network)解决存在的“真相关性”。

  (4)Dispatch(分发):被重命名之后的指令会按照程序中的规定顺序,写到发射队列(Issue Queue)、重排序缓存(ROB)和Store Buffer等部件中

  (5)Issue(发射):经过流水线的分发(Dispatch)阶段之后,指令被写到了发射队列(Issue Queue)中,仲裁(select)电路回从这个部件中挑选出合适的指令送到FU中执行。

  (6)RegisterFile Read(读取寄存器):被仲裁电路选中的指令需要从物理寄存器堆(Physical Register File,PRF)中读取操作数

  (7)Execute(执行):各种FU单元执行

  (8)Writeback(写回):将FU计算的结果写到物理寄存器(PRF)中,通过旁路网络将计算结果送到需要的地方。

  (9)Commit(提交):这个阶段起主要作用的部件是重排序缓存(ROB),它将乱序执行的指令拉回到程序中规定的顺序。

免责声明:本文由用户上传,如有侵权请联系删除!