指令调度基本概念

概述

为了提高处理器执行指令的并行度,处理器将计算机指令处理过程拆分为多个阶段,并通过多个硬件处理单元,将不同指令处理的前后阶段重叠并行执行,形成流水线(pipeline)

处理器的流水线结构是处理器微架构最基本的要素,对处理器微架构的其他方面有重要影响。典型的MIPS处理器5级流水线包括取指、译码、执行、访存和写回

首先,在取指阶段,指令被从内存中读出。然后,在译码阶段得到指令需要的操作数寄存器索引,并通过索引从通用寄存器中将操作数读出

如果此时输入操作数和处理器功能单元可用,接下来便可将不同类型的指令分发到不同功能单元执行

  • 例如,如果是算法指令,则分发到算术逻辑单元(Arithmetic Logical Unit, ALU)
  • 如果是访存指令,则分发到加载存储单元,将数据从内存中读出,或者将数据写入内存
  • 在写回阶段,指令执行的结果被写回通用寄存器
  • 如果是计算指令,该结果来自执行阶段的计算结果
  • 如果是内存读指令,该结果来自访存阶段从内存中读取的数据

在处理器流水线上执行的代码序列隐含指令之间的依赖关系,这种依赖关系使得指令流中的指令可能无法在指定的时钟周期执行,引发流水线冲突

为了检测流水线冲突引入的流水线互锁机制,由导致流水线停顿

可见,这种指令间的依赖关系是指令高效执行的主要障碍。为减少冲突,对于无法用旁路解决的数据冲突,一种解决办法是通过处理器的分发逻辑,在运行时由处理器对指令动态重新排序。这意味着必须增加分发逻辑的重排序缓存,以便其能处理更多的指令,并将指令乱序地分发到处理器的功能单元,这称为乱序执行,简称OOO(Out-Of-Order)

这种方法会显著提高硬件复杂度,增加芯片面积和功耗。另一种消除数据冲突,提高指令级并行度(Instruction Level Parallelism , ILP) 的方法是通过在编译阶段,令编译器对指令重排序,并利用流水线停顿造成的空闲时钟周期执行其他指令

编译器重新排列后的指令流馈送到顺序多发射处理器执行。编译器对指令重排序的过程为静态指令调度或编译时指令调度,这是编译器后端优化中的一个重要阶段

指令调度可在基本块内或者跨基本块重拍指令,即将指令从其原先所在基本块(即源基本块)向另一个基本块(即目标基本块)移动

源基本块和目标基本块可以是同一个基本块,也可以是不同的基本块

如果指令能在其所在同一个基本块内移动,则称为局部调度。如果指令可在不同基本块移动,则称为全局调度

指令调度可以在寄存器分配之前和/或之后执行。寄存器分配前的指令的调度有更大的自由度,而寄存器分配后的指令调度优点在于,此时指令序列中已经包含寄存器溢出相关指令,编译器处理的指令序列相对更完整,因此可以充分利用处理器资源,得到更有效的指令调度结果

指令调度基本原理

假设有如下计算

e = (a + b) + c * d

根据AST 生成 汇编指令如下

load r1, a
load r2, b
add r3, r1, r2
load r4, c
load r5, d
mul r6, r4, r5
add r7, r3, r6
store e, r7

基于处理器资源特性模型,编译器可以建立对上述各条指令延迟的估计

假设load、store操作需要4个时钟周期,mul操作需要3个时钟周期,add操作需要1个时钟周期。注意,此处在估计内存操作指令延迟(如load、store)时,假设不会出现缓存未命中

一旦出现缓存未命中,内存操作指令的延迟将可能达到数百个时钟周期。另外,为了简化概念,此处还假设,如果指令间没有依赖关系,单发射处理器可以在每个时钟周期发射一条指令

显然,上述汇编指令序列不是最优的指令序列。因为指令 “add r3, r1, r2” 需要等待之前的两个load指令完成变量a和b的加载后才能开始计算,这中间的停顿时间完全可以用来执行其他没有依赖关系的指令,如后继的"load r4, c" 和 “load r5, d” 指令

经过如此改进的指令序列无疑可以提高指令级并行度,但是通过寄存器活跃性(liveness) 分析可知,改进后的指令序列在执行"load r5, d" 指令时需要的物理寄存器最大数量将达到4个,大于改进前指令序列的最大物理寄存器需求量(3个)

因此,指令调度提高指令并行度是以增加寄存器压力为代价的。编译器如何在二者之间保持平衡取决于后端硬件架构

具体到GPU 后端,因为有更多物理寄存器,GPU编译器可以承受更大的寄存器压力以换取更高的指令并行度,即更快的执行速度

编译器对指令重排序时,应保证不改变已存在数据依赖关系指令间的执行顺序。 为此,编译器首先需要建立指令序列对应的数据依赖图(Data Dependence Graph, DDG), 这是调度算法的重要工具

例如,数据依赖图图表示为G={N,E},其中的节点集合N表示基本块的所有指令,有向边集合E表示指令之间的数据依赖约束,E中的每条边有一个表示延时的权重。该例对应的数据依赖图如下图

在这里插入图片描述

数据依赖图的任何一种拓扑排序方法都可以形成有效的指令调度,最简单且常见的方法是列表调度(list scheduling)。其实现方法是跟踪记录依赖图的就绪列表,并将就绪列表中的一条指令添加到指令调度表

例如,在上述数据依赖图所示,所有load指令在初始状态下已经准备执行就绪,此时,所有load指令都在就绪列表中

调度算法以何种方式选择调度的指令尤其重要,最典型的是关键路径优先调度算法. 关键路径是数据依赖图中节点的最长的路径。如上图的数据依赖图,最长关键路径是8个时钟周期,包括从指令"load r5, d"(或“load r4 c”) 、“mul r6, r4, r5” 到 “store e, r7” 在内的4个节点

这条路径上的延迟总和最大,因此,选择这条路径上的第一个节点"load r5, d" (或 “load r4 c”) 作为调度的第一条指令。依次类推,可以得到指令调度结果如下:

load r5, d
load r4, c
load r2, b
load r1, a
mul r6, r4, r5
add r3, r1, r2
add r7, r3, r6
store e, r7

上述调度算法从就绪列表中选择指令的标准的最小化关键路径上的指令序列执行时间,减少流水线停顿的发生频率。在实际实现中,可以增加其他优先级策略,如寄存器压力

随着就绪列表中的指令不断被调度,数据依赖图中的其他节点相继被加入就绪列表,并重复上述过程,直到所有节点都被调度,数据依赖图为空,调度过程结束

上述调度算法只考虑一个基本块内的指令重排序,因而属于局部指令调度。全局指令调度可以在基本块间重排指令,需要考虑的情况更为复杂,因而考虑的情况更为复杂,因而大部分编译器只实现局部指令调度,如LLVM

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/32849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据类型 运算符

基本数据类型与引用数据类型的区分 存储内容: 基本数据类型:直接存储实际的数据值,如整数、浮点数、字符等。引用数据类型:存储对象的引用(内存地址),而不是对象本身。 内存分配: 基…

本地离线模型搭建指南-本地运行显卡选择

搭建一个本地中文大语言模型(LLM)涉及多个关键步骤,从选择模型底座,到运行机器和框架,再到具体的架构实现和训练方式。以下是一个详细的指南,帮助你从零开始构建和运行一个中文大语言模型。 本地离线模型搭…

打印机状态显示错误是什么原因?这5个有效方法要记好!

打印机是现代办公中不可或缺的设备之一,但在使用过程中,打印机状态显示错误是一个常见的问题。本文将详细探讨打印机状态显示错误的原因及其解决方法。 摘要 打印机状态显示错误的原因及解决方法如下: 1、网络连接问题:原因&…

LLM agentic模式之reflection:SELF-REFINE、Reflexion、CRITIC

SELF-REFINE SELF-REFINE出自2023年3月的论文《Self-Refine: Iterative Refinement with Self-Feedback》,考虑到LLM第一次生成结果可能不是最好的输出,提出一种包括反馈(feedback)和改善(refinement)两个步骤的迭代方法来改进LLM的初始输出。 基本思路…

【Orange Pi 5与Linux系统编程】-POSIX消息队列

Linux系统中的POSIX消息队列编程 文章目录 Linux系统中的POSIX消息队列编程1、POSIX 消息队列2、Linux 中的 POSIX 消息队列命名3、POSIX 消息队列调用3.1 mq_open, mq_close3.2 mq_timed_send、mq_send、mq_timed_receive、mq_receive3.3 mq_notify3.4 mq_unlink3.5 mq_getatt…

【Java】已解决java.lang.FileNotFoundException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.lang.FileNotFoundException异常 在Java编程中,java.lang.FileNotFoundException是一个常见的异常,它通常表示程序试图打开一个不存在的文件、文…

使用Let‘s Encrypt 申请通配符证书

为什么不使用阿里云/腾讯云等公有云厂商提供的免费证书? 上篇介绍了从阿里云上面申请免费证书,有效期一年 为网站配置https证书 公有云提供的证书不支持通配符,只支持某个确定的解析。 不管是二级域名还是三级域名,只要是具体的确定的地址,都…

号外!号外!全网第一手Android P刘海屏适配大揭秘,唯一Kotlin算法

如下图所示: 4.2.适配刘海屏 在刘海屏调试打开之后,浏览应用的所有页面,测试所有遮挡问题,或者是下移导致的问题,对有问题的页面进行布局适配。适配方案如下: Google 提供的适配方案,可以设置…

使用VisualBox+Vagrant搭建Centos虚拟机环境

1.下载并安装VisualBox; 2.下载并安装Vagrant; 3.打开cmd窗口,执行命令vagrant init centos/7,初始化centos环境,该步骤受网络带宽影响,可能挂级30分钟到1个小时; 4.启动虚拟机:vagrant up&…

数据库理论大题与编译原理大题(笔记)

目录 数据库(求最小函数依赖) 数据库(求属性集的闭包和候选码) 编译原理(NFA ——> DFA) 编译原理(识别文法的活前缀 DFA 和 LR(0) 分析表) 哈哈!这是本人作者才…

WordPress强大多功能主题模板The7 v9.16.0

模板介绍 The7可以与WPBakery Page Builder(原Visual Composer)和Ultimate Addons的完全无缝集成。它也与大多数流行的插件完全兼容,例如WooCommerce,WPML,Yoast SEO,All in One WP Migration,…

Windows系统下安装RabbitMQ详细步骤

声明:原文参考链接出自: 如何在Windows系统下安装RabbitMQ_rabbitmq windows安装-CSDN博客 https://zhuanlan.zhihu.com/p/693160757 一、RabbitMQ安装软件资源准备 因为RabbitMQ是Erlang语言开发的,因此安装Erlang环境在进行安装RbbitMQ的…

无需破解,打开就是旗舰版!

在当今快节奏的工作环境里,有效的视觉沟通变得至关重要。流程图、思维导图、组织结构图等图表能够帮助我们以清晰、直观的方式传达复杂信息。而Wondershare Edraw Max正是这样一款强大的绘图工具,它能够帮助用户轻松创建各种专业图表。 软件链接&#x…

基于springboot websocket和okhttp实现消息中转

1、业务介绍 消息源服务的消息不能直接推给用户侧,用户与中间服务建立websocket连接,中间服务再与源服务建立websocket连接,源服务的消息推给中间服务,中间服务再将消息推送给用户。流程如下图: 此例中我们定义中间服…

解析PDF文件中的图片为文本

解析PDF文件中的图片为文本 1 介绍 解析PDF文件中的图片,由两种思路,一种是自己读取PDF文件中的图片,然后用OCR解析,例如:使用PyMuPDF读取pdf文件,再用PaddleOCR或者Tesseract-OCR识别文字。另一种使用第…

信息学奥赛初赛天天练-32-CSP-J2022基础题-中缀表达式、后缀表达式、哈夫曼编码、连通图、邻居矩阵、完全二叉树、数组存储

PDF文档公众号回复关键字:20240623 2022 CSP-J 选择题 单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项) 6.对表达式a(b-c)*d的前缀表达式为( ),其中 、- 、 * 是运算符。 A. * a - bcd B. a * - …

【从0实现React18】 (四) 如何触发更新 带你了解react触发更新的流程以及更新后如何触发render

常见的触发更新的方式 创建 React 应用的根对象 ReactDOM.creatRoot().render();类组件 this.setState();函数组件 useState useEffect; 我们希望实现一套统一的更新机制,他的特点是: 兼容上述触发更新的方式方便后续…

c++学习-----内存管理

1. C/C内存分布 我们先来看下面的一段代码和相关问题 答案揭晓: 这里很多人会误认为*char2在常量区,这其实是错误的 因为: 首先在内存字符常量区分配一块内存空间放下”abcd\0”,然后在栈中分配一块连续的内存空间,…

SQL-Python

师从黑马程序员 数据库介绍 数据库就是存储数据的库 数据组织:库->表->数据 数据库和SQL的关系 MySQL的基础命令 SQL基础 SQL语言的分类 SQL的语法特征 DDL-库管理 show DATABASES;use sys;SELECT database();CREATE DATABASE test CHARSET utf-8;SHOW D…

学习C++第二天

1.缺省参数 缺省参数的概念&#xff1a; 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时&#xff0c;如果没有指定实参则采用该形参的缺省值&#xff0c;否则使用指定的实参。 void show(int a 10) {cout << a << endl; }int main() {sho…