AUTOPHASE:在随机森林中用深度强化学习来处理HLS Phase Ordering问题 --论文翻译

AutoPhase: Juggling HLS Phase Orderings in Random Forests with Deep Reinforcement Learning

摘要

编译器生成的代码的性能取决于它应用优化pass的顺序。选择一个好的顺序–通常被称为phase-odering问题,是一个NP-hard问题。因此,现有的解决方案依赖于各种启发式方法。在本文中,我们评估了一种解决phase-ordering问题的新技术:深度强化学习。为此,我们实现了AutoPhase:一个框架,它采用一个程序,并使用深度强化学习来寻找一个最小化其执行时间的编译pass。在不丧失通用性的前提下,我们在LLVM编译器工具链的背景下构建了这个框架,并以高级合成程序为目标。我们使用随机森林来量化给定程序的有效性和程序的特征之间的相关性。这有助于我们通过避免不太可能提高特定程序性能的phase orderings来减少搜索空间。我们将AutoPhase的性能与解决phase-ordering问题的最先进的算法进行比较。在我们的评估中,我们表明,与使用-O3编译器标志相比,AutoPhase提高了28%的电路性能,并且与最先进的解决方案相比,取得了具有竞争力的结果,同时需要更少的样本。此外,与现有的最先进的解决方案不同,我们的深度强化学习解决方案在对一百个随机生成的程序进行训练后,在对实际基准和12,874个不同的随机生成的程序进行泛化方面显示出令人鼓舞的结果。

1 介绍

高级合成(HLS)将从高级语言编写的算法中创建数字硬件电路的过程自动化。现代HLS工具(Xilinx,2019;In- tel,2019;Canis等人,2013)使用与传统软件编译器相同的前端。他们依靠传统的软体编译器技术来优化输入程序的中间表示(IR),并以RTL代码的形式产生电路。因此,编译器前端优化的质量直接影响到HLS生成电路的性能。

程序优化是一项众所周知的困难任务。一个程序必须是 “正确的形式”,以便编译器能够识别优化机会。这是一项程序员可能很容易完成的任务,但对编译器来说往往是困难的。尽管在开发复杂的优化算法方面已经进行了十年的研究,但在HLS生成的代码和专家手工优化的代码之间仍然存在着性能差距。

在本文中,我们以LLVM编译器(Lattner & Adve, 2004)为基础。然而,我们的技术可以广泛适用于任何使用一系列优化pass的编译器。在这种情况下,HLS程序的优化包括应用一连串的分析和优化阶段,其中每一个阶段都会消耗前一个阶段的输出,并为下一个阶段生成程序的修改版本。不幸的是,这些阶段不是互换的,这使得这些阶段的应用顺序对输出的性能至关重要。

考虑图1中的程序,该程序将一个向量归一化。在没有任何优化的情况下,规范函数将需要Θ(n2)来规范一个向量。然而,一个聪明的编译器会实现循环不变代码运动(LICM)(Muchnick, 1997)的优化,这使得它可以将对mag的调用移到循环之上,从而形成图2中左列的代码。这一优化将运行时间降低到Θ(n)–这是一个很大的速度提升。编译器可以进行的另一项优化是(函数)内联(Muchnick,1997)。通过内联,对一个函数的调用被简单地替换为函数的主体,减少了函数调用的开销。对代码进行内联将导致图2右列的代码。
请添加图片描述
请添加图片描述请添加图片描述
现在,考虑以相反的顺序应用这些优化通道:先内联,再LICM。经过内联,我们得到了图3左边的代码。尽管我们的运行时间仍然是Θ(n2),但我们再次得到了适度的加速,因为我们已经消除了n个函数调用。如果编译器之后试图应用LICM,我们会发现图3右边的代码。LICM能够成功地将和的分配移到循环之外。然而,它无法将设置sum=0的指令移到循环之外,因为这样做将意味着除第一次之外的所有迭代都会以sum的垃圾值结束。因此,内部循环将不会被移出。

正如这个简单的例子所说明的,优化阶段的应用顺序可能是程序运行在Θ(n2)和Θ(n)之间的区别。因此,确定最佳的阶段顺序以最大限度地提高电路速度是至关重要的。不幸的是,这不仅是一项困难的任务,而且最佳的phase ordering可能因程序而异。此外,事实证明,寻找优化阶段的最佳顺序是一个NP-hard问题,详尽地评估所有可能的序列在实践中是不可行的。例如,在这项工作中,搜索空间扩展到 2 247 2^{247} 2247个以上的阶段排序。

本文的目标是提供一种机制,自动确定HLS程序的良好phase ordering,以优化电路速度。为此,我们旨在利用最近在深度强化学习(RL)方面的进展(Sutton & Barto, 1998; Haj-Ali et al., 2019b)来解决相序问题。通过RL,一个软件代理通过采取行动不断与环境互动。每个行动都可以改变环境的状态,并产生一个 “奖励”。RL的目标是学习一个策略,即观察到的环境状态和一组行动之间的映射,以最大化累积奖励。一个使用深度神经网络来接近策略的RL算法被称为深度RL算法。在我们的例子中,来自环境的观察可以是程序和/或到目前为止应用的优化过程。行动是接下来要应用的优化通道,奖励是应用该通道后电路性能的改善。在理解如何在RL框架内制定phase ordering优化问题方面存在重大挑战。

在本文中,我们考虑了三种方法来表示环境的状态。第一种方法是直接使用程序中的突出特征。第二种方法是从我们应用的优化序列中得出特征,同时忽略程序的特征。第三种方法结合了前两种方法。我们通过实现一个框架来评估这些方法,该框架将一组程序作为输入,并迅速找到一个与最先进的解决方案相竞争的阶段性排序。我们的主要贡献是:

  • 扩展之前的工作(Huang等人,2019),利用深度RL来解决phase ordering问题。
  • 使用随机森林对特征进行重要性分析,以显著减少状态和行动空间。
  • AutoPhase:一个将目前的HLS编译器基础设施与深度RL算法整合在一起的框架。
  • 我们可以看到,AutoPhas在九项真实的基准测试中比-O3提高了28%。与所有最先进的方法不同,深度RL展示了在对一百个程序进行训练后,有可能将其推广到数千个不同的程序。在对一百个程序进行训练后,可以推广到成千上万的不同程序。

2 背景

2.1 编译器 Phase-ordering

编译器执行优化程序,将程序转化为更有效的形式,以便在各种硬件目标上运行。为了方便起见,各组优化通常被打包成 “优化级别”,如-O0和-O3。虽然这些优化级别为开发者提供了一套简单的选择,但它们是由编译器设计者精心挑选的,通常对某些基准程序组最为有利。编译器社区试图通过在每个程序或每个目标的基础上为软件选择一组特定的编译器优化来解决这个问题(Triantafyllis等人,2003;Almagor等人,2004;Pan & Eigenmann,2006;Ansel等人,2014)。

由于phase ordering的搜索空间太大,无法进行穷举搜索,许多启发式方法已经被提出来,通过机器学习来探索这个空间。Huang等人试图通过使用改进的贪心算法来解决HLS应用的这一挑战(Huang等人,2013;2015)。它在CHstone基准(Hara等人,2008)上取得了16%的改进,与-O3相比,我们在本文中使用了这一基准。在(Agakov等人,2006)中,非依赖模式和马尔科夫模式都被应用于自动瞄准优化搜索空间的迭代方法以改善搜索结果。在(Stephenson等人,2003)中,遗传算法被用来调整三个编译器优化通道的启发式优先函数。Milepost GCC(Fursin等人,2011年)根据对程序特征的静态分析,使用机器学习来确定适用于一个给定程序的程序集。在MiBench程序套件中,ARC可重构处理器的执行时间比-O3提高了11%。在(Kulkarni和Cavazos,2012)中,挑战被模拟为马尔可夫过程,并根据当前程序状态,使用监督学习来预测下一个优化。OpenTuner(Ansel等人,2014)使用AUC-Bandit-Meta技术指导的算法集合选择来自动调整程序。它目前选择编译器优化通道的机制不考虑顺序或支持重复优化。Wang等人(Wang & OBoyle, 2018)提供了一份关于在编译器优化中使用机器学习的调查,他们还描述了使用程序特征可能是有帮助的。NeuroVectorizer(Haj-Ali等人,2020;2019a)使用深度RL来自动调整编译器原理,如矢量化和交织因子。NeuroVectorizer在广泛的基准上实现了97%的oracle性能(粗暴的搜索)。

2.2 强化学习算法

强化学习(RL)是一种机器学习方法,在这种方法中,代理人不断地与环境进行互动(Kaelbling等人,1996)。特别是,代理人观察环境的状态,并根据这种观察采取一种行动。然后,RL代理的目标是计算一个策略–环境状态和行动之间的映射–使长期的回报最大化。

RL可以被看作是解决马尔科夫决策过程(MDP)的随机优化方案(Bellman, 1957),当MDP不为人知时。一个MDP是由一个有四个元素的元组定义的: S , A , P ( s , a ) , r ( s , a ) S, A, P (s, a), r(s, a) S,A,P(s,a),r(s,a)其中 S S S是环境状态的集合, A A A描述了行动或状态间转换的集合, s ′ ∼ P ( s , a ) s′ ∼P (s, a) sP(s,a) 描述了鉴于当前状态和行动的下一个状态的概率分布, r ( s , a ) : S × A → R r(s,a):S×A→R r(s,a):S×AR是在状态 S S S做了动作 A A A的奖励. 鉴于MDP,代理人的目标是获得最大可能的总奖励。与MDP相关的RL算法的目标是找到一个决策策略 π ∗ ( a ∣ s ) : s → A π∗(a|s):s→A π(as)sA,为该MDP实现这一目标:
请添加图片描述
深度RL利用神经网络来学习策略(有时还有奖励函数)。例如,策略梯度(PG)(Sutton等人,2000年),通过区分公式1中的总奖励 E E E直接更新策略:
请添加图片描述
并按照梯度方向更新网络参数(权重):

请添加图片描述

请注意,PG是一种策略上的方法,因为它直接使用当前策略做出的决定来计算新策略。

在过去的几年里,人们提出了大量新的深度RL技术(Mnih等人,2016;Ross等人,2011)。在本文中,我们主要关注近似策略优化(PPO)(Schulman等人,2017),Asynchronous Advantage Actor-critic(A3C)(Mnih等人,2016)。

PPO是PG的一个变种,它可以实现多个小批量更新的epoch,以提高样本的复杂性。Vanilla PG对每个数据样本执行一次梯度更新,而PPO使用一个新的代用目标函数来实现多个epoch的小批量更新。它通过与环境的互动,在采样数据和使用随机梯度上升优化代用目标函数之间交替进行。它通过使用代用目标函数,执行最大化奖励函数的更新,同时确保与先前策略的偏差很小。PPO的损失函数定义为:
请添加图片描述

其中 r t ( θ ) r_t(θ) rt(θ)被定义为概率比 π θ ( a t ∣ s t ) π θ o l d ( a t ∣ s t ) \frac {π_θ(a_t|s_t)} {π_{θ_{old}} (a_t |s_t )} πθold(atst)πθ(atst),所以 r ( θ o l d ) = 1 r(θ_{old})=1 r(θold)=1。这个术语惩罚了使 r t ( θ ) r_t(θ) rt(θ)远离 r ( θ o l d ) r(θ_{old}) r(θold)的策略更新。 A t A_t At表示估计的优势,近似于 a t a_t at与平均水平相比有多好。最小函数中的第二项对将 r t r_t rt移出[1-ε,1+ε]范围的行为起抑制作用,其中ε是一个超参数。

A3C使用一个演员(通常是一个神经网络)与评价者互动,评价者是另一个网络,通过计算价值函数来评估行动。评价者告诉演员它的行动有多好,它应该怎样做。算法所进行的更新可以看作是 ∇ θ l o g π θ ( a i , t ∣ s i , t ) A ˆ t ∇_θ logπ_θ (a_i,t |s_i,t )Aˆt θlogπθ(ai,tsi,t)Aˆt

2.3 进化算法

进化算法是另一种技术,可用于搜索最佳的编译器通过排序。它包括一个基于种群的元启发式优化算法系列,其灵感来自于自然选择。这些算法的主要思想是对解决方案的群体进行抽样,并使用好的解决方案来指导未来基因的分布。两个常用的进化算法是遗传算法(GA)(Goldberg,2006)和进化策略(ES)(Conti等人,2018)。

GA通常需要一个搜索空间的遗传表示,其中解决方案被编码为整数向量。该算法从一个候选方案池开始,然后通过以下三种策略迭代进化,以包括具有更高适配性的方案:选择、交叉和混合。选择保留一个具有最高适配值的解决方案的子集。这些被选中的解决方案作为下一代的父代。交叉合并来自父代解决方案的配对,以产生新的后代。突变以低概率扰乱后代的解决方案。这个过程不断重复,直到找到一个达到目标适配度的解决方案,或经过一定数量的世代。

ES的工作原理与GA类似。然而,在ES中,解决方案被编码为实数。此外,ES是自适应的。超参数,如步长或变异概率,对不同的解决方案是不同的。它们被编码在每个解决方案中,因此,好的设置会随着好的解决方案进入下一代。最近的工作(Salimans等人,2017)使用ES来更新RL的策略权重,并表明它是基于梯度的方法的一个很好的替代品。

3 自动phase ordering的AUTOPHASE 框架

我们利用现有的开源HLS框架LegUp(Canis等人,2013),将C程序编译成硬件RTL设计。在(Huang et al., 2013)中,我们设计了一种方法来快速确定硬件执行周期的数量,而不需要耗时的逻辑模拟。我们在LegUp提供的现有线束基础上开发了我们的RL模拟器环境,并通过耗时的逻辑模拟来验证我们的最终结果。AutoPhase接收一个程序(或多个程序),并智能地探索可能的参数空间,以找出一个最佳的参数序列来应用。表1列出了AutoPhase中使用的所有程序。图4说明了AutoPhase的工作流程。

请添加图片描述
请添加图片描述

3.1 HLS 编译器

AutoPhase将一组程序作为输入,并使用LLVM编译器的Clang前端将其编译为独立于硬件的中间代表(IR)。优化和分析过程作为IR的转换,将程序作为输入,并输出一个新的IR作为输出。HLS工具LegUp在编译器优化后被调用,作为后端程序,它将LLVM IR转化为硬件模块。

3.2 时钟周期剖析器

一旦硬件RTL生成,人们可以运行硬软件仿真来收集合成电路的周期数结果。这个过程相当耗时,阻碍了RL和所有其他优化方法。因此,我们使用LegUp(Huang等人,2013)中的剖析器来近似计算周期数,该剖析器利用软件跟踪,运行速度比硬件仿真快20倍。在LegUp中,生成电路的频率被设定为编译器的约束条件,指导HLS的调度算法。换句话说,HLS工具会一直尝试生成能够以某种频率运行的硬件。在我们的实验设置中,在不丧失一般性的情况下,我们将所有生成的硬件的目标频率设置为200MHz。我们也试验了更低的频率;改进是相似的,但是不同的算法所达到的周期数更好,因为更多的逻辑可以被安装在一个周期内。

3.3 IR 特征提取器

Wang等人(Wang & OBoyle, 2018)提出通过提取程序中的所有特征将程序转化为观察结果。同样,除了LegUp后台工具外,我们还开发了分析通道,从程序中提取56个静态特征,如基本块的数量、分支和各种类型的指令。我们将这些特征作为RL学习的部分可观察状态,并希望神经网络能够捕捉到这些特征的某些组合与某些优化的关联性。表2列出了所有使用的特征。

请添加图片描述

3.4 随机程序生成器

作为一种数据驱动的方法,如果我们在更多的程序上训练agent,RL的通用性会更好。然而,网上的开源HLS例子数量有限。因此,我们通过自动生成合成HLS基准来扩展我们的训练集。我们首先使用CSmith(Yang等人,2011)生成标准的C语言程序,这是一个随机的C语言程序生成器,最初是为了生成用于寻找编译器错误的测试案例。然后,我们开发脚本来过滤掉那些在CPU上运行超过5分钟或HLS编译失败的程序。

3.5 AutoPhase的整体流程

我们将编译工具整合到Python的模拟环境中,其API类似于OpenAI gym(Brockman等人,2016)。整体流程如下:

  1. 使用Clang/LLVM将输入的程序编译成LLVM IR。
  2. 运行IR特征提取器以提取明显的程序特征。
  3. LegUp将LLVM IR编译成硬件RTL。
  4. 时钟周期分析器为生成的电路估计一个时钟周期计数。
  5. RL agent将程序特征或以前应用passes的直方图以及时钟周期数的改进作为输入数据进行训练。
  6. RL agent预测要应用的下一个最佳优化pass。
  7. 新的LLVM IR是在应用新的优化序列后生成的。
  8. 机器学习算法通过步骤(2)-(7)进行迭代,直到收敛。

请注意,AutoPhase使用的是LLVM编译器,所使用的程序列于表2。然而,在AutoPhase中为任何编译器或优化程序添加支持是非常容易和直接的。动作和状态的定义必须再次指定。

4 passes 和程序特征之间的关联

与许多深度学习方法的情况类似,可解释性是我们在将深度RL应用于phase ordering问题面临的主要挑战之一。为了分析和理解passes和程序特征的相关性,我们使用随机森林(Breiman, 2001)来学习不同特征的重要性。随机森林是多个决策树的集合体。每棵树所做的预测可以通过追踪每个节点的决策和计算不同特征对每个节点的决策的重要性来解释。这有助于我们确定有效的特征和使用的passes,并显示我们的算法是否学习了数据的信息模式。

对于每个pass,我们建立两个随机森林来预测应用它是否会提高电路性能。第一个森林以程序特征为输入,而第二个森林则以先前应用的pass的直方图为输入。为了收集森林的训练数据,我们在100个随机生成的程序上运行高探索参数的PPO,以产生特征-行动-奖励元组。该算法对影响最终预测的输入特征赋予更高的重要性。

4.1 程序特征的重要性

图5中的热力图显示了不同的特征对是否应该应用pass的重要性。数值越高,说明该特征越重要(每一行的数值之和为1)。随机森林是用随机程序产生的15万个样本来训练的。在表1和表2中可以看到特征和passes的索引映射(56个features、45个passes)。例如,对应于特征索引17和pass索引23的黄色像素反映了number-of-critical-edges是否应用*-loop-rotate*的决定有很大影响。控制流图中的关键边是指既不是唯一离开其源块的边,也不是唯一进入其目的块的边。临界边在循环中通常可以看作是后边,所以临界边的数量可能大致代表程序中循环的数量。转化pass-循环-旋转检测循环,将while循环转化为do-while循环,以消除循环体中的一条分支指令。应用该pass的结果是更好的电路性能,因为它减少了一个循环中FSM状态的总数。

请添加图片描述

在这个图中还观察到其他预期的行为。例如,分支的数量和*-loop-simplify*, -tailcallelism(转化了对当前函数的调用,即自我递归,接着是返回指令,并有一个分支到函数的入口,形成一个循环),-lowerswitch(用一连串的分支重写了开关指令)这些转换passes之间的关联性。其他有趣的行为也被捕获。例如,在具有常数操作数的二进制操作和-functionattrs之间的相关性,它将一个函数的不同操作数标记为只读(常数)。一些相关性更难解释,例如,BitCast指令的数量和*-instcombine*,它将指令合并成更少的简单指令。这实际上是*-instcombine减少了为铸造指针类型而调用bitcast指令的加载和存储的结果。另一个例子是内存指令的数量和 -sink ,其中 -sink基本上是将内存指令移到后续块中,并将内存的执行推迟到需要时。直观地说,是否应用-sink应该取决于程序中是否有任何内存指令。我们要展示的最后一个例子是常数0和-deadargelim的出现次数,其中-deadargelim*有助于消除死的/未使用的常数0参数。

总的来说,我们观察到,所有的通道都与一些特征相关,并且能够影响最终的电路性能。我们还观察到,多个特征在指导决策方面并不有效,用它们进行训练可能会增加变异,从而导致我们的结果的预测准确性降低。例如,指令的总数并不能直接说明应用一个通道是否有帮助。这是因为有时更多的指令可以提高性能(例如,由于循环展开),消除不必要的代码也可以提高性能。此外,在不同的基准中,功能的重要性也不同,这取决于它们所执行的任务。

4.2 先前已被应用的Passes的重要性

图6说明了以前应用的Passes对要应用的新Passes的影响。数值越大,拥有旧的Passes就越重要。从这个图中,我们了解到,对于我们训练过的程序,-scalarrepl, -gvn,-scalarrepl-ssa, -loop-reduce, -loop-deletion, -reassociate, -loop-rotate, -partial-inliner, -early-cse、 -adce, -instcombine, -simplifycfg, -dse, -loop-unroll, -mem2reg, and -sroa, 与其他的passes相比,无论它们在轨迹中的顺序如何,都对性能有更大的影响。第(23,23)点的重要性最高,这意味着-loop-rotate pass是非常有用的,如果之前没有应用,应该包括在内。通过检查数以千计的程序,我们发现*-loop-rotate确实大大减少了周期数。有趣的是,如果连续应用这个pass两次,并没有什么危害。然而,如果在两次pass之间有一些其他的pass,有时就会非常有害。我们的热图捕捉到的另一个有趣的行为是,在(不一定是连续的)第23个pass(-loop-rotate*)之后应用第33个pass(-loop-rotate)要比以相反的顺序应用这两次pass有用得多。

5 问题建模

5.1 RL环境的定义

假设要应用的最佳pass数为N,并且总共有K个转换pass可供选择,我们对phase-ordering问题的搜索空间S是 [ 0 , K N ] [0, K^N] [0,KN]。考虑到M个程序特征和已经应用的pass的历史,深度RL的目标是学习下一个最佳优化passa,使生成的硬件电路的长期周期数最小。请注意,在这种情况下,优化状态s是部分可观察的,因为M个程序特征不能完全捕获程序的所有属性。

动作空间–我们将我们的行动空间A定义为 a ∈ Z : a ∈ [ 0 , K ) {a∈Z:a∈[0,K)} aZa[0,K),其中K是变换通道的总数。

观察空间–在我们的评估中包含两种类型的输入特征:1. 程序特征 o f ∈ Z M o_f ∈ Z^M ofZM在表2列出。2. 动作历史,它是以前应用的pass o a ∈ Z K o_a∈Z^K oaZK的柱状图。在每个应用pass i的RL步骤之后,我们调用我们环境中的特征提取器来返回新的 ,并将动作直方图元素 o a i o_{a_i} oai更新为 o a i + 1 o_{a_i} + 1 oai+1

奖励–生成的电路的周期数由时钟周期分析器在每次RL迭代时重新分析。我们的奖励定义为 R = c p r e v − c c u r R = c_{prev} - c_{cur} R=cprevccur,其中 c p r e v c_{prev} cprev c c u r c_{cur} ccur分别代表生成电路的前一个和当前的周期数。可以为不同的目标定义不同的奖励。例如,奖励可以被定义为优化区域的负值,因此RL代理将对面积进行优化。也可以通过定义不同目标的组合来共同优化多个目标(例如,面积、执行时间、功率等)。

5.2 每个动作应用多个Passes

上述行动表述的一个替代方案是在每次RL迭代中评估一个长度为N的完整的passes序列,而不是单一的行动a。在开始训练一个新的episode时,RL agent将所有的pass索引 p ∈ Z N p∈Z^N pZN重置为索引$ \frac K 2 . 对于在下标为 .对于在下标为 .对于在下标为i$的pass p i p_i pi,接下来要采取的行动是改变到一个新的pass或不改变。通过允许每个p的正负索引更新,我们减少了遍历所有可能的通行指数所需的总步骤。因此,每个pass的子行动空间 a i a_i ai被定义为[-1, 0, 1]。总的行动空间A被定义为 [ − 1 , 0 , 1 ] N [-1, 0, 1]^N [1,0,1]N。在每一步,RL代理预测更新 [ a 1 , a 2 , . . . , a N ] [a_1 , a_2 , ..., a_N] [a1,a2,...,aN]到N个pass,当前的优化序列 [ p 1 , p 2 , . . . , p N ] [p_1, p_2, ..., p_N] [p1,p2,...,pN]被更新为 [ p 1 + a 1 , p 2 + a 2 , . . . , p N + a N ] [p_1 +a_1,p_2 +a_2,..., p_N +a_N] [p1+a1,p2+a2,...,pN+aN]

5.3 泛化技术

为了让已经训练好的RLagent可以在新的程序上工作,我们需要适当地规范程序特征和奖励,使它们在不同的程序中代表一种有意义的状态。在这项工作中,我们试验了两种技术:1. 取程序特征或奖励的对数;2 将原始输入程序的参数归一化,大致描述问题的规模。对于技术1,注意取程序特征的对数。程序特征的对数不仅降低了它们的大小,而且还在神经网络中以不同的方式将它们关联起来。因为, w 1 l o g ( o f 1 ) + w 2 l o g ( o f 2 ) = l o g ( o f 1 w 1 o f 2 w 2 w_1 log(o_{f1} ) + w_2 log(o_{f2} ) = log(o^{w_1}_{f_1} o^{w_2}_{f_2} w1log(of1)+w2log(of2)=log(of1w1of2w2 ),神经网络正在学习对特征的产物进行关联,而不是对它们进行线性组合。对于技术2,我们将程序特征规范化为输入程序中的总指令数( o f n o r m = o f o f 51 o_{f_norm}=\frac {o_f} {o_{f_{51}}} ofnorm=of51of)是表2中的特征51。

6 评估

为了运行我们的深度RL算法,我们使用RLlib(Liang等人,2017),这是一个用于强化学习的开源库,为各种应用提供高扩展性和统一的API。RLlib建立在Ray(Moritz等人,2018)之上,Ray是一个高性能的分布式执行框架,针对大规模机器学习和强化学习应用。我们在四核英特尔i7-4765T CPU和Tesla K20c GPU上运行该框架进行训练和推理。

我们将HLS中的频率约束设置为200MHz,并使用HLS分析器报告的时钟周期数作为电路性能指标。在(Huang et al., 2013)中,结果显示在一定的频率约束下,时钟周期数和实际的硬件执行时间之间有一对一的对应关系。因此,更好的时钟周期数将导致更好的硬件性能。

6.1 性能

为了评估各种算法解决相位排序问题的有效性,我们在九个真实的HLS基准上运行这些算法,并根据最终的HLS电路性能和样本效率与最先进的克服相位排序的方法进行比较,其中包括随机搜索、贪婪算法(Huang等人,2013)、OpenTuner(Ansel等人,2014)和遗传算法(Fortin等人,2012)。这些基准是根据CHStone(Hara等人,2008)和LegUp的例子改编的。它们是:adpcm、ais、blowfish、dhrystone、gsm、matmul、mpeg2、qsort和sha。在这次评估中,输入的特征/奖励没有被规范化,通过长度被设置为45,并且每个算法都是在每个程序的基础上运行。表3列出了所有深度RL算法中使用的动作和观察空间。

图7中的柱状图显示了在CHStone的九个真实基准上与-O3结果相比,电路性能的改进百分比。图7中蓝线上的点表示每个程序的总样本数,也就是算法调用模拟器收集周期数的次数。-O0和-O3是默认的编译器优化级别。RL-PPO1是PPO探索器,我们将所有奖励设置为0,以测试奖励是否有意义。RL-PPO2是PPO代理,它根据应用的通过直方图学习下一个通过。RL-A3C是A3C代理,基于程序特征进行学习。贪婪执行贪婪算法,它总是在当前序列中的最佳位置(在所有可能插入的位置中)插入实现最高速度的通证。RL-PPO3使用一个PPO代理和程序特征,但其行动空间在第5.2节中有说明。OpenTuner运行六种算法的集合,其中包括两个系列的算法:粒子群操作(Kennedy, 2010)和GA,每种算法有三种不同的交叉设置。RL-ES类似于A3C代理,它基于程序特征进行学习,但使用进化策略而不是反向propa-gation更新策略网络。Genetic-DEAP(Fortin等人,2012)是一个遗传算法的实现。随机一次生成45个pass的序列,而不是逐个采样。

从贪心中,我们看到,总是在当前序列中加入取得最高奖励的通证,会导致次优的电路性能。RL-PPO2比RL-PPO1取得了更高的性能,这表明深度RL在训练过程中捕获了有用的信息。使用应用pass的直方图会产生更好的样本效率,但使用具有更多样本的程序特征会使速度略微提高。例如,RL-PPO2以降低4%的速度为微小代价,实现了比OpenTuner多50倍的样本效率。对于像我们这样具有稀疏奖励的问题,使用ES来更新策略应该是更有效的样本,然而,我们的实验并没有从中受益。此外,多行动更新的RL-PPO3比其他单一行动的深度RL算法取得了更高的速度。其中一个原因是RL-PPO3有能力在每次编译中探索更多的通道,因为它在每次编译之间同时应用多个通道。另一方面,其他深度RL算法一次只应用一个通道。

6.2 泛化

在深度RL中,搜索应该受益于从其他不同程序中学习到的先前知识。这种知识应该可以从一个程序转移到另一个程序。例如,正如在第4节中所讨论的那样,应用pass -loop-rotate总是有益的,而*-loop-unroll应该在-loop-rotate*之前应用。请注意,黑盒搜索算法,如OpenTuner、GA和贪婪算法,不能泛化。对于这些算法,每一个新的程序都需要重新运行一个新的搜索,并进行多次编译,因为它们没有从程序中学习任何模式来指导搜索,可以被看作是一种智能随机搜索。

为了评估深层RL对不同程序的通用性以及任何先验知识是否有用,我们使用PPO对100个随机生成的程序进行训练。由于缺乏足够的基准,并且是最坏的情况,即它们与我们用于推理的程序非常不同,所以随机程序被用于转移学习。如果我们在与我们推理的程序相似的程序上进行训练,那么改进会更大。我们训练一个具有256×256个全连接层的网络,并使用先前应用的passes与程序特征相联系的直方图作为观察,passes作为动作。

如第5.3节所述,我们对程序特征进行了两种泛化实验:1. 取所有程序特征的对数, 2. 将程序特征与程序中的总指令数标准化。在每一个pass序列中,中间奖励被定义为应用每一个pass后的周期数的改进的对数。对数的选择是为了使RL agent不会对执行时间较长的程序的大奖励给予更大的权重。我们评估了三种方法:filtered-norm1使用过滤后的(基于第4节的分析,我们只保留重要的特征和通过)程序特征和第1节的pass,original-norm2使用所有的程序特征和通过,并使用规范化技术2,而filtered-norm2使用过滤后的程序特征和第4节的通过以及规范化技术2。过滤特征和通过可能并不理想,特别是当不同的程序有不同的特征和有影响的通过。然而,重新计算特征和pass的数量有助于减少所有程序之间的差异,大大缩小搜索空间。

图8显示了三种方法的episode奖励平均值与步骤的关系。我们观察到,过滤后的norm2和过滤后的norm1比原始norm2收敛得更快,并取得了更高的episode奖励平均值,后者使用了所有特征和pass了。在大约8,000步时,过滤后的norm2和过滤后的norm1已经达到了非常高的episode奖励平均值,在以后的步骤中略有改善。此外,即使我们让原始的norm2训练20倍的步骤(即16万步),过滤后的方法的episode奖励平均值仍然高于原始的norm2。这表明对特征和通pass的过滤大大改善了学习过程。所有这三种方法都学会了总是应用 “-loop-rotate”,并在 "-loop-rotate"之后应用 “-loop-unroll”。这三种方法学会应用的另一个有用的pass是 -loop-simplify,它执行几个转换,将自然循环转换为更简单的形式,以便进行后续分析和转换。

请添加图片描述

我们现在将filtered-norm2和filtered-norm1的泛化结果与其他黑盒算法进行比较。我们使用100个随机生成的程序作为训练集,使用CHStone的9个真实基准作为基于深度RL的方法的测试集。对于最先进的黑盒算法,我们首先寻找最佳的通过序列,使100个随机程序达到最低的聚合硬件周期数,然后直接应用于九个测试集程序。在图9中,柱状图显示了在九个真实基准上与-O3相比电路性能的改进百分比,蓝线上的点显示了每个推理对一个新程序所需的总样本数。

请添加图片描述

这一评估表明,基于深度RL的推理比最先进的黑盒算法产生的新程序的预定序列实现了更高的速度。对随机程序过度拟合的预定序列会导致在未见过的程序中表现不佳(例如,Genetic-DEAP的-24%)。另一方面,与泛化技术1相比,泛化技术2在深度RL泛化中的效果更好(4%对3%的速度提升)。这表明,将不同指令泛化为指令总数,即技术2中不同指令的分布代表了不同程序中更普遍的特征,而在技术1中采取的对数只支持了不同程序特征的值范围。此外,当我们使用其他12,874个随机生成的程序作为测试集,并使用filtered-norm2时,与-O3相比,速度提高了6%。

7 结论

在本文中,我们提出了一种基于深度RL的方法,通过优化编译器应用优化阶段的顺序来提高HLS设计的性能。我们使用随机森林来分析程序特征和优化passes之间的关系。然后,我们利用这种关系,通过识别最可能的优化阶段来减少搜索空间,以提高性能,给定程序特征。我们基于RL的方法在训练几分钟后,比用-O3标志编译的性能好28%,在训练不到一分钟后,性能提高24%。此外,我们还表明,与之前的工作不同,我们的解决方案显示出对各种程序的普及潜力。虽然在本文中我们将深度RL应用于HLS,但我们相信同样的方法可以成功应用于软件编译和优化。展望未来,我们设想使用深度RL技术来优化广泛的程序和系统。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值