微架构是指令集架构的一种实现或者设计.
1. fetch
从内存中获取指令
2. decode
将获取的指令解码为 uOp
//一般意义为将一条指令分解为多个内部操作
// 实际上 : 可能是 多条指令对应一个uOp , 也可能是1:1 , n:1
3. excute
执行指令
// 执行指令单元有很多个
// 加/减/乘/除/与/或/异或/非/branch
4. write back
存储计算结果到 寄存器 或者 内存
// 管道深度涉及到 每个阶段
将4个阶段中的每个阶段都扩展一下//
将fetch 扩展为 5个阶段
...
...
...
然后就形成了 深度为20的pipeline
管道阶段越多,每个阶段的专业化(设计越简单,更快)程度就越高,相对的也就越快,那么整个全部流程会越快 // 当然,不考虑阶段与阶段间的消耗
现代处理器大约有15-20个阶段 // 叫做 15级流水线
获取和解码阶段通常涉及到 6-10 个阶段,被称为微处理器的前端
执行和写回阶段也大约6-10个阶段,被称为 后端
cpu的流水线是同步的
// 预测属于 fetch 阶段
1.遇到分支指令如何预取下一条指令 // 遇到分支指令还会继续预取,而不是停下来等到分支指令的执行后再预取
2.分支指令可能会将流水线中的指令给清空
意思是 我们会预取一些不需要执行的指令
如果我们能将这个预取的不需要指令的指令数目降低,那么就会提高整体的运行速度.
现代处理器 会 根据预测 预取 // speculative execution
1.分支指令A执行后,会更新一些部件B
2.下次该分支指令A预取后, 这些部件B会选择 指令A 后的 其中一条路径的指令 来预取
分支预测器(只有一个)
能够记录 1000个分支的预测方向
预取器(只有一个)
预取指令 // 预取 分支预测器 预测的指令
cache
1-2 clocks // 内存 , 100 clocks
如果cache 为空 , 就会批量预取相邻指令到 cache 中,然后将他们交给解码器(解码器有很多个)
CPU管道前端的主要目标是确保使用有足够的指令可供后端执行
,避免因等待内存中的指令字节而出现空闲时间,
或因错误的分支预测导致获取的指令最终被丢弃,
因此浪费时间
// 最佳情况是,指令会一直在cache中,执行的速度完全不会被内存的速度耽搁
前端的第二部分是将程序指令解码为 微架构的内部操作(微操作Micro-Operations,简称uOps)
uOps 是指令集架构与微架构之间最牢固的联系
指令与 uOp的对应关系 比例
1:1 绝大多数
n(相邻指令):1 少数 // 例如 比较指令+跳转指令
1:n 少数
前端的工作始终是研究如何解码 和 准备这些指令,以确保高效执行
有些微架构会创建解码缓存,以便 将来遇到时,直接映射.
对指令进行解码,或从解码缓存中读取指令之后,uOp将被传递到管道后端
superscalar execution
简单的执行形式是算术逻辑单元,ALU(用来执行加减运算)
// level4 : ALU/寄存器/加法器/多路复用器/解码器/锁存器/触发器/计数器
// l3 : 与或非门
// l2 : 晶体管
// l1 : 硅原子
如果只有一个ALU,一次则只能执行一次加法运算,被称作标量执行
现代处理器可以有多个ALU,ALU并行计算,即超标量执行
可以并行执行的运算量(有多少个ALU)是衡量微处理器宽度的方法之一.
所有现代微处理器都属于超标量微处理器 // 这也增加了对前端的需求(即要求前端更块的提供uOp)
一个核心有1个预取器,6个ALU,宽度为6.
我把一个soc 中集成 4个核心, 宽度(超标量能力)就是 24 , 这个也叫作多流水线
我把一个soc 中继承 1个核心,并改造该核心为24个ALU,宽度(超标量能力)就是 24,这个还是单流水线
out of order
基本微架构中, uOp 按照编程顺序执行,被称作 In-Order Execution
但是,为了提供最佳的性能和参数, 乱序执行 效果更好
这样可以消除不必要的等待时间,从而加快代码执行
但是会导致 编码中A先B后,且B依赖A, uOpB先执行uOpA后执行的情况
乱序执行的第一步// 涉及2-4个阶段
后端乱选执行的第一步是获取前端提供的uOp,并确定他们的依赖关系
如果有依赖关系,则改关系会通过一个名为"寄存器重命名Rename"的流程进行跟踪
第二步 Allocation // 是确定微架构宽度的另一种方法 , 是 确定 瓶颈的一种方法
uOp 信息会别写到一个 "重排序缓冲区 Reorder Buffer"(ROB)的结构中,这个过程叫做 Allocation(分配)
虽然指令采用乱序执行,我们仍然需要一种方法让他们恢复顺序,就依赖 "重排序缓冲区"(ROB)
"重排序缓冲区"(ROB) 能让我们连接原始编程顺序
经过这两步的uOp 再
经过 Scheduler 把uOp 放到 可执行特定运算的执行单元(ALU或者JMP) 中 // 这里如果 Scheduler 到 执行单元 有 (大于1条通道) , 则叫做 多发射
同一个ALU可能有多个实例,ALU还有不同的类型,可以执行不同类型的运算
有些可以执行整数运算
有些可以执行浮点运算或基于十进制或小数的数学运算
有些可以同时对多个元素执行运算,这些匀速叫做矢量
分支操作也有自己的执行单元JMP
Scheduler 负责理清依赖关系
// A依赖B
// 则B先被Scheduler 发出来
// B执行完后被放到L2 Queue,然后通过 Scheduler
// A被 Scheduler 发出来
// A 被执行后被放到 L2 Queue
当某个uOp执行完毕并成为后端中(一批次)最晚的uOp时,ROB即确定可由安全的将这个uOp写回,这个过程被称为 Retirement ,(隐退) // 一批次是怎么定义的,TODO
我们可以通过并行,乱序执行其中的很多指令,从而提高cpu的性能,同时仍能做到保持响应的依赖关系,最终,我们会得到正确的答案和正确的结果.
执行的时候还可能访存,如果执行的uOp 说 操作数 在内存中, 就需要访存
文章浏览阅读1.5k次。兴趣是最好的老师,HelloGitHub 让你对编程感兴趣!简介分享 GitHub 上有趣、入门级的开源项目。https://github.com/521xueweihan/HelloGi..._开源 lexer
文章浏览阅读5.7k次。Code Review 即日常所说的代码评审或代码回顾,主要是在软件开发的过程中,对功能源代码进行评审,其目的是找出并修正软件开发过程中出现的错误的过程,提高和改进代码质量的过程。_code review怎么做
文章浏览阅读2.1k次。SSM项目的启动过程:ssm框架中,项目启动过程以及web.xml配置详解_菜鸟不会飞-程序员宅基地_ssm项目启动入口是什么本篇主要在基于SSM的框架,深入讲解web.xml的配置web.xml 每个javaEE项目中都会有,web.xml文件是用来初始化配置信息:比如Welcome页面、servlet、servlet-mapping、filter、listener、启动加载级别等。 web.xml配置文件内容如下:<!DOCTYPE web-app PUBLIC..._ssm框架 启动传参
文章浏览阅读1.6k次。登陆后不用重启!npm config set proxy http://工号:密码@代理服务器地址:80npm config set https-proxy http://工号:密码@代理服务器地址:80_npm config set disturl 失败
文章浏览阅读547次。今天写项目遇到一个问题,搞了好大一半天了,都想放弃了,在最后还是找到解决办法了我定义了一个基础dao和基础service,就是BaseService是一个泛型类,但是里面需要依赖注入泛型的基础类BaseDao,然后子类来继承父类的所有方法,但是在编译的时候报错,说找到多个dao,不知道要注入哪个,这个时候只需要在要注入的BaseDao改成抽象类,加上abstract即可..._springboot crud 泛型 service
文章浏览阅读837次。在日常python编程中,有很多遍历文件夹内文件的需求,而os.walk方法就是一个满足该需求的例子。不熟悉这个方法的同学,刚开始用os.walk的时候难免踩坑。因此本文采用源码分析的方式,讲述os.walk的机理,让大家对于这个方法有更加深入的理解。以python3为例,os.walk方法的源码如下:def walk(top, topdown=True, onerror=None, followlinks=False): """Directory tree generator. F_python os walk 源码
文章浏览阅读2.5w次,点赞2次,收藏4次。最近遇到如题所示弹框的问题,花了很长时间才解决,解决方法却很简单。故记录下来。解决方法:找到相同系统却没有该问题的情况(比如出问题的是64位的win7系统,那就找一个没有该问题的64位的win7系统)。将正常系统的api-ms-win-downlevel-shlwapi-l1-1-0.dll文件复制到出现该问题的电脑的相应位置。就可以解决了。但是同样有一些问题需要注意详细步骤:有一些dl..._api-ms-win-downlevel-shlwapi-l1-1-0.dll
文章浏览阅读325次。ResponseEntity:code:/*常用*/@GetMapping("/hello")public ResponseEntity<String> hello(){ return new ResponseEntity<>("hello word!",HttpStatus.OK);}/*设置HTTP头*/@GetMapping("/hello")pu..._responseentity json
文章浏览阅读712次。Spring Boot默认帮我们配置好了日志;1.在测试类中创建一个记录器;package com.myproject.springboot;import org.junit.Test;import org.junit.runner.RunWith;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import or..._springboot 如何修改默认的日志框架
文章浏览阅读963次。 以2001年2月《敏捷宣言》诞生为开端,由一群精英开发者所倡导的敏捷方法引发了一场软件开发大变革。今天,敏捷方法已经在全球范围内成为公认的主流软件开发方式,得到企业的广泛认同,产生了深远影响。在主要欧美国家,不仅小团队、中型企业基本上都完成了敏捷转型,超大型企业包括Google、微软、IBM等领导性互联网和软件公司也都纷纷在大范围应用敏捷方法开发核心产品,财富500强公司中的大部分软件研发团队甚至许多产品研发团队也已经在采用敏捷过程,并取得良好效果,有的团队超过万人。
文章浏览阅读242次。代码如下:背包类:package 背包;import java.util.Iterator;public class Bag<Item> implements Iterable<Item> { private Node first; private class Node{ Item item; Node next; } publi..._java定义一个背包(bag)类, 背包具备如下4个属性: a. 品牌(任意) b. 尺寸(10~17寸)
文章浏览阅读1.2k次。 我买的是开发板,不知道MTK的外围设备和GPIO的对应关系,所以找来datasheet,对应一下,方便我以后修改GPIO_CTRL_0 方向控制 GPIO0----GPIO31 GPIO_CTRL_1 方向控制GPIO32----GPIO63GPIO_CTRL_2 方向控制GPIO64----GPIO95GPIO_POL_0GPIO_POL_1GPIO..._mt7688 io 换算