CPU流水线竞争解决方案

简介: 增加资源,通过添加指令缓存和数据缓存,让我们对于指令和数据的访问可以同时进行。帮助CPU解决取指令和访问数据之间的资源冲突。

增加资源,通过添加指令缓存和数据缓存,让我们对于指令和数据的访问可以同时进行。帮助CPU解决取指令和访问数据之间的资源冲突。

就像是在软件开发过程,发现效率不够,于是研发负责人说:“我们需双倍研发资源。”

直接等待。通过插入NOP这样的无效指令,等待之前的指令完成。这样我们就能解决不同指令之间的数据依赖问题。

好比你在提需求时,研发负责人告诉你说:“来不及做,你只能等我们需求排期。”

“堆资源”、“等排期”这种解决方案,并不能提高效率,只是避免和现有任务冲突。


解决流水线冒险问题,还有更高效解决方案吗?既不用简单花钱加硬件电路这样“堆资源”,也不纯粹等待之前任务完成。

有的,操作数前推。


1 NOP操作和指令对齐

MIPS体系结构下的R、I、J三类指令

8.png


五级流水线“取指令(IF)-指令译码(ID)-指令执行(EX)-内存访问(MEM)-数据写回(WB) ”。

7.png


MIPS体系结构下,不同类型指令,会在流水线的不同阶段进行不同操作。


如MIPS的:


LOAD,从内存读取数据到寄存器的指令,需经历5个完整流水线

STORE这种从寄存器往内存里写数据的指令,无需写回寄存器的操作,即无数据写回的流水线阶段

ADD、SUB加减法指令,所有操作都在寄存器完成,无实际的内存访问(MEM)操作

6.png

有些指令无对应流水线阶段,但并不能跳过对应阶段直接执行下一阶段。不然,若先后执行一条LOAD、一条ADD,就会发生LOAD指令的WB阶段和ADD指令的WB阶段,在同一时钟周期发生。相当于触发一个结构冒险事件,产生资源竞争。


所以实践中,各指令不需要的阶段,并不会直接跳过,而是运行一次NOP。插入一个NOP使后一条指令的每个Stage,一定不和前一条指令的同Stage在一个时钟周期。就不会发生先后两个指令,在同一时钟周期竞争相同的资源,产生结构冒险。

2 操作数前推

通过NOP对齐,在流水线里,就不会遇到资源竞争产生的结构冒险。


NOP也是流水线停顿插入的对应操作。但插入过多NOP,意味CPU总在空转。如何尽量少插NOP呢?


如下有两条先后发生的ADD指令


# 把 s1 和 s2 寄存器里面的数据相加,存到 t0 寄存器

add $t0, $s2,$s1

# 把 s1 和 t0 寄存器里面的数据相加,存到 s2 寄存器

add $s2, $s1,$t0


后一条 add 指令,依赖 t0 值。而 t0 值又来自前一条指令的计算结果。所以后一条指令,需等待前一条指令的数据写回阶段完成后,才能执行。

要在第二条指令的译码阶段后,插入NOP,直到前一条指令的数据写回完成,才继续执行。


这虽解决数据冒险,但也浪费两个时钟周期。第2条指令其实就多花2个时钟周期,两次空转NOP。

5.png


第二条指令未必要等待第一条指令写回完成,才能进行。若第一条指令的执行结果,能直接传给第二条指令的执行阶段,作为输入,那第二条指令就不用再从寄存器里把数据再单独读出来一次,才执行代码。


可在第一条指令的执行阶段完成后,直接将结果数据传输给到下一条指令的ALU。然后,下一条指令不需要再插入两个NOP阶段,就可继续正常走到执行阶段。

4.png

这就叫操作数前推(Operand Forwarding)或操作数旁路(Operand Bypassing)。应该叫操作数转发。Forward就是写Email时的“转发”(Forward)。教材翻译都叫“前推”。


转发,逻辑含义,即在第1条指令的执行结果,直接“转发”给第2条指令的ALU作为输入

旁路(Bypassing),硬件含义

在CPU硬件,需再单独拉一根信号传输的线路出来,使ALU计算结果重新回到ALU的输入。这条线路就是“旁路”。它越过(Bypass)写入寄存器,再从寄存器读出的过程,节省2个时钟周期。

操作数前推可单独使用,还可和流水线冒泡一起使用。有时,虽可把操作数转发到下条指令,但下条指令仍需停顿一个时钟周期。

3.png

如先执行一条LOAD,再执行ADD。LOAD指令在访存阶段才能把数据读出来,所以下条指令的执行阶段,需在访存阶段完成后才能进行。


操作数前推,比流水线停顿更进一步。流水线停顿像游泳比赛接力。下一名运动员,需在前一个运动员游玩全程,触碰到游泳池壁才能出发。


操作数前推,像短跑接力赛。后一个运动员可提前抢跑,而前一个运动员会多跑一段主动把交接棒传递给他。


3 总结

操作数前推或叫操作数旁路。在硬件层面制造一条旁路,让一条指令的计算结果,直接传输给下一条指令,不再需要“指令1写回寄存器,指令2再读取寄存器“这多此一举。直接传输的好处是后面指令可减少甚至消除原本需通过流水线停顿,才能解决的数据冒险。

不仅可单独使用,还可以和流水线冒泡结合。因为有时,操作数前推并不能减少所有“冒泡”,只能去掉一部分。仍需通过插入一些“气泡”解决冒险。


通过操作数前推,我们进一步提升了CPU的运行效率。那么,我们是不是还能找到别的办法,进一步地减少浪费呢?毕竟,看到现在,我们仍然少不了要插入很多NOP的“气泡”。那就请你继续坚持学习下去。下一讲,我们来看看,CPU是怎么通过乱序执行,进一步减少“气泡”的。


参考


《计算机组成与设计:硬件/软件接口》的4.5~4.7章

目录
相关文章
|
运维 监控 Java
内存溢出+CPU占用过高:问题排查+解决方案+复盘(超详细分析教程)
全网最全的内存溢出CPU占用过高排查文章,包含:问题出现现象+临时解决方案+复现问题+定位问题发生原因+优化代码+优化后进行压测,上线+复盘
2300 5
|
6月前
|
Java 关系型数据库 MySQL
服务器cpu 100%解决方案
服务器cpu 100%解决方案
99 0
|
6月前
|
NoSQL 关系型数据库 MySQL
热点数据更新导致CPU100%的解决方案
热点数据更新导致CPU100%的解决方案
75 0
IDEA 出现问题:严重占用CPU 长时间在90~100%解决方案
IDEA 出现问题:严重占用CPU 长时间在90~100%解决方案
3110 0
IDEA 出现问题:严重占用CPU 长时间在90~100%解决方案
CPU流水线越大越好吗?
流水线技术是提升性能的银弹吗?它通过把一条指令的操作切分成更细的多步,可避免CPU“浪费”。每个细分的流水线步骤都很简单,单个时钟周期时间就可设得更短,变相让CPU主频提升很快。
201 0
|
存储 内存技术
CPU设计(单周期和流水线)
CPU设计(单周期和流水线)
249 0
CPU设计(单周期和流水线)
|
Kubernetes Cloud Native 安全
Koordinator 0.6:企业级容器调度系统解决方案,引入 CPU 精细编排、资源预留与全新的重调度框架
经过社区多位成员的贡献,Koordinator 0.6 版本正式发布。相较于上一个版本 0.5,新版本进一步完善了 CPU 精细化编排能力,更好的兼容原生用法;支持了资源预留的能力(Reservation),补齐了调度原子语意缺失;发布了全新的重调度框架,支持用户灵活的扩展自定义插件。这些特性源自于阿里巴巴内部的生产实践,并结合上游社区规划思考,为用户带来标准、强大、灵活的调度解决方案。
1063 0
Koordinator 0.6:企业级容器调度系统解决方案,引入 CPU 精细编排、资源预留与全新的重调度框架
|
Cloud Native Linux KVM
关于kvm安装Linux时的CPU soft lockup报错解决方案
关于kvm安装Linux时的CPU soft lockup报错解决方案
474 0
关于kvm安装Linux时的CPU soft lockup报错解决方案
CPU的流水线指令设计(下)
CPU的流水线指令设计
197 0
CPU的流水线指令设计(下)
CPU的流水线指令设计(上)
CPU的流水线指令设计
458 0
CPU的流水线指令设计(上)