Control-Flow Decoupling

2023-12-11 06:39
文章标签 control flow decoupling

本文主要是介绍Control-Flow Decoupling,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Control-Flow Decoupling

  1. 摘要

    • 问题:论文在四个基准测试套件(spec2006,NU-MineBench3.0 BioBench,cBench-1.1)中发现,MPKI中的三分之一的指令是可分离分支。可分离分支是论文提出的一个概念,表示那些分支的控制相关区域很大(不适合if-conversion转换),并且这些分支的向后切片代码(backward slice)不依赖于其控制相关指令或者具有短暂的依赖关系
    • 解决:论文提出了控制流解耦和(control flow decoupling)的方法消除可分离分支的错误预测
      • 思想:将包含分支的循环分离为两个循环,第一个循环只包含分支的谓词计算,第二个循环包含分支和与该分支有控制相关的指令。第一个循环通过微结构上的队列将分支结果传递给第二个循环
      • CFD的循环转换可以由于程序员或者编译器控制
      • 结果:在类似Intel的sandy bridge core的微架构上,CFD可以提高43%的性能,能耗降低41%
  2. 介绍:

    • 论文比较了一个完美的分支预测器和一个当时最新的分支预测器(ISL-TAGE)之间的性能和功耗对比
      在这里插入图片描述

    • 可分离分支的两个特点

      • 这种分支的控制相关区域非常大,不适合使用if-conversion的方法进行转换
      • 这种分支不依赖于本身的控制相关指令(由循环携带的数据相关带来的相关)(完全可分离分支),或者只依赖于它的控制相关指令的一个短的循环携带的相关(部分可分离分支)
    • 对于完全可分离的分支,分支的谓词计算完全独立于该分支及其控制相关区域,因此可以先生成谓词向量,然后使用该向量驱动取值或者跳过控制相关的区域的连续动态实例

    • 对于部分可分离分支:分支的断言计算依赖于一些分支的控制相关指令,即在计算断言的循环中需要将这些控制相关的分支和该分支本身拷贝一份。这种拷贝可以最终转换为if-conversion的形式,因此此时控制相关的指令已经非常的少,可以进行断言转换

  3. 控制流分类:四类

    • Hammock(吊床):只有很小并且简单的控制相关区域,可以使用if-conversion进行转换。(可能会增加store指令的数量)
    • Separable(分离的):具有很大并且复杂的控制相关区域,但是分支的后向切片(谓词计算)和分支指令以及其控制相关的指令可以完全分离或者部分分离
    • inseparable(不可分离的):具有很大并且复杂的控制相关区域,但是分支的向后切片(谓词计算)包含了太多分支的控制相关指令。这种情况下,分离分支的谓词计算不会产生好处
    • Not Analyzed(未分析的):对整体的分支错误预测之后很小的贡献的分支
  4. 控制流解耦和示例
    在这里插入图片描述

    • 图a是一个在循环中的完全可分离的分支。分支切片(branch slice)用于计算分支的谓词。分支根据谓词计算的结果决定是否执行之后的指令。当前示例中,分支的控制相关之后都不在其后向切片中(下一次的谓词计算切片),即在和分支相关的指令和分支之间不存在循环携带的数据相关性。(部分可分离分支则是一小部分的控制相关指令在分支切片中,即有一条从控制相关指令指向分支切片的后向边)
    • 图b则是利用CFD转换之后的循环。此时循环变成两个循环,循环的判断条件相同。第一个循环只包括分支切片,并且将断言的计算结果压入BQ(branch queue),压入操作使用新的指令Push_BQ。第二个循环包括控制相关指令,使用另一个新的指令Branch_on_BQ,将断言结果从BQ中弹出,然后用于分支判断
    • 对于部分可分离分支,转换之后的第一个循环中不仅包括分支切片和Push_BQ指令,还包括分支指令以及一些必须的控制相关指令。分支和控制相关指令将会利用条件move指令,转换为if-conversion的形式
  5. CFD的ISA支持

    • 分支队列BQ(branch queue)的体系结构说明
      • BQ有一个特定的大小,并且对软件有一定的影响
      • 每个BQ表项包含一个标志位,用于指示taken/not taken。同时表项中也会包含一些其它的体系结构状态,但是这些对软件不可见,ISA中也没有指定
      • 使用一个长度寄存器指示当前BQ的占用情况,软件只能够看到这个寄存器的值
      • ISA提供了将BQ状态(队列内容和长度寄存器)保存和恢复到内存的机制,从而保证BQ也可以在上下文切换时可用(论文推荐使用专用的寄存器完成这个任务)
    • Push_BQ指令:有一个源寄存器号(也是通用寄存器),如果寄存器内容为非零,则将1压入队列,否则压入1
    • Branch_on_BQ:一条新的分支指令,也通过PC相对偏移得到目标地址,但是没有显示的源寄存器要求。执行时该指令会从BQ中弹出谓词,确定是否跳转
    • ISA要求软件必须遵守push和pop的使用规则:
      • push必须在pop之前
      • 连续的N次push之后,必须按照压栈的顺序,连续的进行N次pop
      • N不能够超过BQ的大小
  6. CFD的软件支持

    • ISA中为了支持CFD要求循环的次数不能够超过BQ的大小。如果超过会影响性能,因为BQ在溢出之后需要保存到内存中,因此会降低性能
    • 解决:将原本的循环转换为两层嵌套循环,保证内层的循环次数不超过BQ的大小。然后再对内层循环进行CFD转换
  7. CFD的硬件支持

    • BQ使用循环缓冲区实现,每个BQ表项包括的微结构状态:push位,pop位和检查点id
    • 提前push(early push)
      • 当push指令被取值时,会在BQ的尾部分配一个表项,此时push位和pop位都被清零。并且push指令会记录分配在BQ中的表项位置(索引)
      • 当push指令最终被执行时,检查pop位,如果仍旧为0,意味着pop操作尚未执行,此时将断言的结果写入BQ表项中,并且设置push位
      • 当遇到pop指令时,检查当前对应的BQ中的表项的push位,如果为1,则使用表项的结果进行判断
    • Late push(延后push):pop指令在push指令执行之前取值
      • pop指令取值时,检查对应的BQ表项中的push位,发现仍旧为0,意味着表项中没有断言计算的结果
      • 两种解决方法:暂停取值,直到push完成执行;使用分支预测器进行分支预测
      • 论文使用第二种解决方案,称之为推测pop。当推测pop指令到达重命名阶段时,将使用检查点保存状态,并且会将预测的结果和检查点id写入对应的BQ表项,并且设置pop位。等待push操作完成之后判断是否需要进行恢复操作
      • 论文发现,在经验中,延迟push非常少见,因为在软件中会使得pop和push之间很多间隔指令
    • BQ长度(占用率):使用两个组件的和表示
      • net_push_ctr:表示push和pop操作个数之差。当发生push指令提交时,该计数器增加,当pop指令提交时,计数器减少
      • pending_push_ctr:在指令窗口中push指令的个数(已经取值但是尚未提交的push的个数)。当push被取值时,计数器增加,当push提交时,计数器减少
      • 如果BQ长度等于BQ大小,并且取到了push指令,此时取值单元必须停止
    • BQ的恢复(recovery)
      • 为错误分支预测恢复的准备:每个分支检查点都增加了将BQ恢复到程序执行中的该检查点所需要的状态,即需要对BQ的头指针和尾指针进行快照
      • 为异常恢复的准备:需要维护提交的BQ的头尾指针版本
      • 当出现回滚时,BQ头尾指针将从引用的检查点或者提交的版本中恢复,并且清除恢复的头尾之间所有的pop位。pending_push_ctr需要根据尾指针的变化情况进行减少

这篇关于Control-Flow Decoupling的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/479780

相关文章

GNSS CTS GNSS Start and Location Flow of Android15

目录 1. 本文概述2.CTS 测试3.Gnss Flow3.1 Gnss Start Flow3.2 Gnss Location Output Flow 1. 本文概述 本来是为了做Android 14 Gnss CTS 的相关环境的搭建和测试,然后在测试中遇到了一些问题,去寻找CTS源码(/cts/tests/tests/location/src/android/locat

MFC中Spin Control控件使用,同时数据在Edit Control中显示

实现mfc spin control 上下滚动,只需捕捉spin control 的 UDN_DELTAPOD 消息,如下:  OnDeltaposSpin1(NMHDR *pNMHDR, LRESULT *pResult) {  LPNMUPDOWN pNMUpDown = reinterpret_cast(pNMHDR);  // TODO: 在此添加控件通知处理程序代码    if

2024年 Biomedical Signal Processing and Control 期刊投稿经验最新分享

期刊介绍 《Biomedical Signal Processing and Control 》期刊旨在为临床医学和生物科学中信号和图像的测量和分析研究提供一个跨学科的国际论坛。重点放在处理在临床诊断,患者监测和管理中使用的方法和设备的实际,应用为主导的研究的贡献。 生物医学信号处理和控制反映了这些方法在工程和临床科学的界面上被使用和发展的主要领域。期刊的范围包括相关的评论论文(review p

Understanding the GitHub Flow

这里看下Github的入门介绍    --链接 GitHub Flow is a lightweight, branch-based workflow that supports teams and projects where deployments are made regularly. This guide explains how and why GitHub Flow works

Versioned Staged Flow-Sensitive Pointer Analysis

VSFS 1.Introduction2.Approach2.1.相关概念2.2.VSFS 3.Evaluation参考文献 1.Introduction 上一篇blog我介绍了目前flow-sensitive pointer analysis常用的SFS算法。相比IFDS-based方法,SFS显著通过稀疏分析提升了效率,但是其内部依旧有许多冗余计算,留下了很大优化空间。 以

Salt Function Flow:深度解析复杂网关编排的优势与实践

系列文章索引: Salt Function Flow 系列文章 在业务流程编排中,处理条件逻辑、并行任务、以及复杂的流程分支是常见的挑战。对于需要高度灵活性和扩展性的项目,Salt Function Flow 提供了强大的网关编排能力,使开发者能够轻松定义和管理复杂的业务流程。本文将深入探讨Salt Function Flow中的复杂网关编排功能,展示其如何通过排他网关、并行执行等功能应对复杂的

Salt Function Flow 系列文章

Salt Function Flow 是一款Java开发、轻量级、内存级的业务流程编排框架,旨在帮助开发者通过函数式编程的方式定义和管理复杂的业务流程。它以高效、灵活的流程处理为核心,适用于多种业务场景,从简单任务自动化到复杂业务逻辑处理。 系列文章: Salt Function Flow:深度研发经验的沉淀,打造轻量级高效流程编排框架 Salt Function Flow:深度解析复杂网关编排

解决Vue请求 ‘No 'Access-Control-Allow-Origin' header is present on the requested resource’错误

如果我们用VueResouce直接请求,这样写(以豆瓣api为例): this.$http.get('https://api.douban.com//v2/movie/top250').then((response) => {this.movie = response.data;console.log(this.movie); }); 就会报错: 因为这是一个跨域的请求,不能直接

C# 窗体中Control以及Invalidate,Update,Refresh三种重绘方法的区别

在 C# 中,Control 类是 Windows Forms 应用程序中所有控件的基类。它提供了控件的基本功能和属性,这些功能和属性被所有继承自 Control 类的子类所共享。这意味着 Control 类是构建 Windows Forms 应用程序中用户界面元素的基础。 以下是 Control 类的一些关键特性和方法: 属性: Size:获取或设置控件的宽度和高度。Location:获

Kotlin 流 Flow

挂起函数可以异步地返回一个值,而对于返回多个值,可以使用流,使用 emit(x) 发射多个值, collect { } 来收集值。 默认 流是冷的,只有 收集(collect) 时才会执行。 1. 流的创建 flow {} 生成流,emit(x) 来发射值;xxx.asFlow() 集合转成Flow;flowOf(1, 2, 3) 生成固定值的流。 1.1 flow {} flow {}