fbpx
维基百科

指令调度

指令调度(instruction scheduling)是一种代码优化手段,常见于优化编译器,其主要功能在于通过加强指令层级的并行运行,使得程序在拥有指令流水线中央处理器上能够高效运行。换句话说,此手段力求以不改变程序运算结果的方式,完成以下任务:

  • 通过重组指令的运行顺序,减少或阻止流水线停顿的发生;
  • 阻止非法操作(即未定义行为)的产生,例如涉及流水线时序、非互锁资源的等等操作。

其中流水线停顿主要由结构型冒险(受处理器的资源所限)、数据型冒险以及控制流型冒险导致。

数据型冒险

指令调度一般在某基础块(basic block)上执行。为了确保指令的运行顺序在重组后,其运算结果依旧不变,编译器的开发者们必须要认识到数据依赖这种概念。数据型冒险总共有三种,其性质恰恰与数据型冒险相符,这三种数据冒险分别是:

  1. 写入后读取(RAW, Read After Write) - I1 的输出值之后会被 I2 使用。
  2. 读取后写入(WAR, Write After Read) - I1 的输入位置之后会被 I2 使用并覆盖。
  3. 写入后写入(WAW, Write After Write) - I1 以及 I2 皆将结果写入同一个位置上。

其中 I1 以及 I2 是两个在不同时间点上执行的指令。

对于这三种冒险,指令 I1 都必须执行于 I2 被执行前,否则其运算结果是不被定义的(具体结果视该机器的硬件实现而定)。对于冒险1,这是因为 I2 依赖着 I1 的数据;对于冒险2,则是因为 I1 依赖着即将被 I2 所覆盖的数据;对于冒险3,则是因为在 I1I2 之间所运行的指令可能会使用到 I1 的输出结果。为了确保这些数据依赖所需的运行顺序得到保证,编译器首先需要建立一幅依赖图,即一幅顶点是指令,而是依赖性的有向图。最终,这幅图的任何一种拓扑排序都可以是有效的指令调度表。

算法

寻找拓扑排序最简单且常见的算法是列表调度法,其基本概念是不断将依赖图的某个源抽出,并将其添加到现有指令调度表上。在此过程中变成源的其他顶点,也会如前面所言被抽出并进行调度。当这幅依赖图为空时,算法便会结束。

在这种算法里,为了优化指令调度表的有效性,以减少流水线停顿等现象的发生频率,该算法所选择用于调度的下一条指令尤为重要。为此常用的启发式有:

  • 将已调度指令所占用的处理器资源记录下来,若候选指令同样会占用这些资源,则降低其优先度。
  • 若前指令的延迟(latency)高于前指令与候选指令的距离(即二者的周期差),则降其优先度。
  • 当某候选指令坐落在依赖图中的某关键路径时,则提高其优先度。这使得这个算法拥有部分向前探查的功能,而不再寻找局部最优解。
  • 如果候选指令能创造大量新源,则提高其优先度。这项启发式一般能提供调度器更多的调度自由。

执行次序

指令调度可以在寄存器配置之前或之后进行,也可以在寄存器配置之前和之后进行。在寄存器配置前执行指令调度的好处是可以最大化程序的并行性,然而这种做法会有一定的代价,即代码的寄存器需求量可能会有所增加,而当这个需求量大于处理器所拥有的寄存器时,寄存器溢出便会随之产生,造成性能影响。

如果该处理器架构不允许某些特定的指令序列组合(一般由于缺乏跨指令互锁),则指令调度须在寄存器配置发生后才能执行。这种配置法同时也有助于寄存器溢出问题。

如果指令调度在寄存器配置后发生,指令排序可能因寄存器配置器产生的假依赖性而受到一定限制。

类型

指令调度有几种类型,其中包括了:

  1. 本地(基本块)调度:指令仅能在其所在基础块内移动。
  2. 全局调度:指令能在各基础块内移动。
  3. 模算调度:属于一种软件流水线的生成算法,通过交叉运行不同的循环达到指令层级并行的效果。
  4. 跟踪调度:第一种真正实用的全局调度方法,编译器尽力优化最常被运行的代码控制流路。
  5. 超块(superblock)调度: 跟踪调度的简化版。

指令调度, 此條目没有列出任何参考或来源, 2020年4月24日, 維基百科所有的內容都應該可供查證, 请协助補充可靠来源以改善这篇条目, 无法查证的內容可能會因為異議提出而移除, instruction, scheduling, 是一种代码优化手段, 常见于优化编译器, 其主要功能在于通过加强指令层级的并行运行, 使得程序在拥有指令流水线的中央处理器上能够高效运行, 换句话说, 此手段力求以不改变程序运算结果的方式, 完成以下任务, 通过重组指令的运行顺序, 减少或阻止流水线停顿的发生, 阻止非法操作, 即未定义. 此條目没有列出任何参考或来源 2020年4月24日 維基百科所有的內容都應該可供查證 请协助補充可靠来源以改善这篇条目 无法查证的內容可能會因為異議提出而移除 指令调度 instruction scheduling 是一种代码优化手段 常见于优化编译器 其主要功能在于通过加强指令层级的并行运行 使得程序在拥有指令流水线的中央处理器上能够高效运行 换句话说 此手段力求以不改变程序运算结果的方式 完成以下任务 通过重组指令的运行顺序 减少或阻止流水线停顿的发生 阻止非法操作 即未定义行为 的产生 例如涉及流水线时序 非互锁资源的等等操作 其中流水线停顿主要由结构型冒险 受处理器的资源所限 数据型冒险以及控制流型冒险导致 目录 1 数据型冒险 2 算法 3 执行次序 4 类型数据型冒险 编辑指令调度一般在某基础块 basic block 上执行 为了确保指令的运行顺序在重组后 其运算结果依旧不变 编译器的开发者们必须要认识到数据依赖这种概念 数据型冒险总共有三种 其性质恰恰与数据型冒险相符 这三种数据冒险分别是 写入后读取 RAW Read After Write I1 的输出值之后会被 I2 使用 读取后写入 WAR Write After Read I1 的输入位置之后会被 I2 使用并覆盖 写入后写入 WAW Write After Write I1 以及 I2 皆将结果写入同一个位置上 其中 I1 以及 I2 是两个在不同时间点上执行的指令 对于这三种冒险 指令 I1 都必须执行于 I2 被执行前 否则其运算结果是不被定义的 具体结果视该机器的硬件实现而定 对于冒险1 这是因为 I2 依赖着 I1 的数据 对于冒险2 则是因为 I1 依赖着即将被 I2 所覆盖的数据 对于冒险3 则是因为在 I1 和 I2 之间所运行的指令可能会使用到 I1 的输出结果 为了确保这些数据依赖所需的运行顺序得到保证 编译器首先需要建立一幅依赖图 即一幅顶点是指令 而边是依赖性的有向图 最终 这幅图的任何一种拓扑排序都可以是有效的指令调度表 算法 编辑寻找拓扑排序最简单且常见的算法是列表调度法 其基本概念是不断将依赖图的某个源抽出 并将其添加到现有指令调度表上 在此过程中变成源的其他顶点 也会如前面所言被抽出并进行调度 当这幅依赖图为空时 算法便会结束 在这种算法里 为了优化指令调度表的有效性 以减少流水线停顿等现象的发生频率 该算法所选择用于调度的下一条指令尤为重要 为此常用的启发式有 将已调度指令所占用的处理器资源记录下来 若候选指令同样会占用这些资源 则降低其优先度 若前指令的延迟 latency 高于前指令与候选指令的距离 即二者的周期差 则降其优先度 当某候选指令坐落在依赖图中的某关键路径时 则提高其优先度 这使得这个算法拥有部分向前探查的功能 而不再寻找局部最优解 如果候选指令能创造大量新源 则提高其优先度 这项启发式一般能提供调度器更多的调度自由 执行次序 编辑指令调度可以在寄存器配置之前或之后进行 也可以在寄存器配置之前和之后进行 在寄存器配置前执行指令调度的好处是可以最大化程序的并行性 然而这种做法会有一定的代价 即代码的寄存器需求量可能会有所增加 而当这个需求量大于处理器所拥有的寄存器时 寄存器溢出便会随之产生 造成性能影响 如果该处理器架构不允许某些特定的指令序列组合 一般由于缺乏跨指令互锁 则指令调度须在寄存器配置发生后才能执行 这种配置法同时也有助于寄存器溢出问题 如果指令调度在寄存器配置后发生 指令排序可能因寄存器配置器产生的假依赖性而受到一定限制 类型 编辑指令调度有几种类型 其中包括了 本地 基本块 调度 指令仅能在其所在基础块内移动 全局调度 指令能在各基础块内移动 模算调度 属于一种软件流水线的生成算法 通过交叉运行不同的循环达到指令层级并行的效果 跟踪调度 第一种真正实用的全局调度方法 编译器尽力优化最常被运行的代码控制流路 超块 superblock 调度 跟踪调度的简化版 取自 https zh wikipedia org w index php title 指令调度 amp oldid 66868751, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。