第15课 for循环优化
例子中,循环(Loop Trip)一共执行了三次;每个循环有c1,c2,c3三个状态,占用了3个时钟周期;Loop Iteration Interval也为3;整个for循环的Latency是9;函数的Latency是10;Function Initial Interval为11(判断循环变量有没有超需要一个时钟周期)。相关结果也可以在设计报告中查看。
流水线操作(Pipeline)将串行操作转换成并行,可以对for循环进行优化。
这时Loop Iteration Interval减小为1,整个for循环的Latency减小为5。
for循环默认是折叠的,是同一个电路分时复用的思想,而展开的操作(Unrolling)是将电路复制了很多份,是一种面积换速度的思想。
可以将电路完全展开也可以将电路部分展开,上面的例子是将循环6次展开成了3份。
一般来讲,循环条件 i 的类型并不影响最后的结果。
第16课 for循环优化-循环合并
理想情况是两个循环放在一起执行,但实际情况是循环一执行完了再执行循环二。
HLS提供了这样一个方式:将两个for循环合并。这里引入一个概念:region区域,它说明了合并的范围在这个花括号之间。
综合后结果:
当两个循环的循环边界不一致的情况下,合并时以最大的作为合并边界。
当一个循环边界是常数或者变量,另一个循环边界是变量,无法合并。
不过也可以修改代码进行合并优化,变量要是相同的值。
第17课 for循环优化-数据流
TaskA,B,C中存在依赖关系,B需要等A的结果出来才能计算。这时候可以应用流水线的方法,但是不可以用合并的方法来进行优化。
Pipeline是循环内的流水线操作,而DATAFLOW可以理解为循环间的流水线操作。
相比Pipeline,DATAFLOW在这种情况下有着更低的Latency以及消耗更少的资源,同时循环之间的channel是pingpong RAM还是FIFO是可以配置的。
存在着不能使用DATAFLOW的情况。
Singel-producer-sonsumer Model:下面的例子中,temp1在两个循环中都使用,不能进行DATAFLOW。
要使用DATAFLOW 变量只能在一个for循环中使用,要使上面的例子可以使用DATAFLOW,可以将temp1[]分别赋给temp2和temp3,两个循环中分别使用temp2和temp3。
Bypass module:在下面的例子中,dout来自于temp3和temp2,而temp3来自于temp1。不能使用merge优化,也不能使用DATAFLOW优化。
没有条件,创造条件。将dout来自于temp4,而temp4来自于temp2,就可以使用DATAFLOW了。
第18课 for循环优化-嵌套的for循环
首先看看三种嵌套循环的分类:
Perfect loop nest:两个循环边界都是常数同时LOOP BODY只出现在最内侧的循环中。
Semi-Perfect loop nest:外侧的循环边界是变量,内侧的循环边界是常数,LOOP BODY只出现在最内侧的循环中。
Imperfect loop nest(1):两个循环边界都是常数同时LOOP BODY同时出现在两层循环中。
Imperfect loop nest(2):内侧的循环边界是变量,外侧的循环边界是常数,LOOP BODY只出现在最内侧的循环中。
对于Imperfect Loop我们希望通过代码优化的手段将其转化成Perfect loop or Semi-Perfect loop。
对外部for循环做流水,速度最快,相应的所需要的资源也最多。
Loop-FLATTEN允许嵌套for循环展开,它的要求是循环体是Perfect loop or Semi-Perfect loop。
下面一个例子,对最内层的循环product进行流水操作,由于Col对应的for循环和Product对应的for循环之间有个初始化,无法应用Flatten loop。
要对上一层的for循环做流水,下面的所有for循环都会被展开。
对中间的for循环col进行流水,Trip Count变为了9。
对最外层的for循环row进行流水, Trip Count变为了3。
三种优化效果比较。
如果对函数Function进行流水,它会将内部的三个循环都展开。
第19课 其他优化方法
在上面的例子中,Accumulator默认是串行执行的,ALLOCATION可以将两个函数并行执行,这里limit=2,意思是将函数复制了两份。
Rewind可以减小循环间等待的时间,但并不是所有的for循环都可以用Rewind。
当一个任务被流水线了,里面的循环会自动展开,循环边界是变量的情况除外。循环边界是变量的话,会导致设计的performance unknown。
处理循环边界是变量的情形:
1.使用Tripcount directive,限制循环次数的范围,并不做优化
2.将循环边界定义为ap_int类型,资源会比默认int类型要减少。
3.使用assert macro,作用相当于ap_int,可以改善综合结果。