vivado HLS 优化总结以及相关流程

HLS优化

  • 一、for 循环优化之pipeline
  • 二、for 循环优化之unroll
  • 三、for 循环优化之merge
  • 四、for 循环优化之数据流DataFlow
  • 五、for 循环优化之嵌套循环优化
  • 六、数组优化 - - 数组分割
  • 七、函数层面优化
    • Inline
    • Allocation
    • Dataflow
  • 八、总结分析
    • 改善吞吐率( Throughput )
    • 改善时延( Latency)
    • 改善资源( Area)

一、for 循环优化之pipeline

vivado HLS 优化总结以及相关流程_第1张图片

二、for 循环优化之unroll

在默认情况下 for 循环是折叠的(rolled),可以理解为每次循环都使用同一套电路,每
次循环分时复用。如果展开,则循环电路被复制若干份,具体数量可以通过参数设置。这些
复制出的电路可以同时执行不同的数据。
vivado HLS 优化总结以及相关流程_第2张图片

三、for 循环优化之merge

vivado HLS 优化总结以及相关流程_第3张图片
在上图示例中,loop_region 是一个用花括号括起来的区域。这里因为两个 loop 都是对
a 和 b 两个数组进行计算,所以可以通过 LOOP_MERGE 指定进行合并优化。
在合并之前两个 Loop 分别为 8 个周期,再加上进入和退出循环的时间消耗,所以整个
过程消耗 2*(8+1)=18 个时钟周期。合并之后整个循环消耗 8 个时钟周期,整个函数消耗
9 个时钟周期。由此可见循环的合并可以在一定程度上降低 latency,这是因为在默认的情况
下 for 循环会创建额外的状态机,而额外的状态机会占用额外的时钟周期以及额外的资源,
所以导致 latency 和资源的用量会有所增加。因此合并之后这两个方面都会降低。

四、for 循环优化之数据流DataFlow

vivado HLS 优化总结以及相关流程_第4张图片
可以看出数组 A 通过 Task A 生成数组 x,数组 x 通过 Task B 生成数组 y,数组 y 通过
Task C 生成数组 C,其数据流向图如图 17-2 所示。所以 Task A、B、C 之间是有数据依赖关
系的,所以可以用 pipeline 进行优化,但是因为有数据依赖关系,所以不能进行合并优化。
vivado HLS 优化总结以及相关流程_第5张图片
在示例 1 的情况中,刚好可以用到 DATAFLOW 数据流优化方法。数据流优化就是在三
个循环之间插入 Channel(可以是 Ping-pong RAM、FIFO 或 Register)。
vivado HLS 优化总结以及相关流程_第6张图片
在没有使用 DATAFLOW 时,三个循环顺序执行,是没有交叠的。DATAFLOW 之后是的
在执行 Loop B 的时候并不需要等到 Loop A 完全执行完之后再开始,只要 A 有输出,就可
以利用这个输出去执行 Loop B。这样多个任务之间就可以有交叠,降低了 latency,提高了
数据吞吐率。
图 17-4 DATAFLOW 执行之前和之后对比

五、for 循环优化之嵌套循环优化

对内部循环 pipeline,则会自动对循环做 LOOP_FLATTEN 优化,即把所有的嵌套循
环展开(flatten)为一个大循环。

unroll 展开和 flatten 展开是不一样的概念。unroll 是将循环体展开为并行操作,而
flatten 是将嵌套循环展开为单一循环。

六、数组优化 - - 数组分割

数组最终都会以 memory 的形式实现(RAM、ROM 或 FIFO)。如果这个数组作为顶层
函数的形参,那么最终就会以相应的 memory 接口形式呈现,包括相应的读写地址和数据以
及读写使能。如果数组在设计内部,最终就会映射为真正的 block RAM,LUTRAM,UltraRAM
或者 register,具体类型取决于在设计中使用的优化方法。
用 memory 或 memory ports 实现的数组往往是设计中的性能瓶颈。
Vivado HLS 提供了 3 种对数组分割的方法,分别是 block,cyclic 和 complete。block 分
割就是将数组元素分割为指定块数,然后依次填满每一块。Cyclic 方法就是分割为指定块数
后先每块分配一个元素,然后每块分配第二个元素,直至分配完所有元素。Complete 方法
就是每个元素分配一个寄存器存储。如图 20-1 所示:
vivado HLS 优化总结以及相关流程_第7张图片
vivado HLS 优化总结以及相关流程_第8张图片

七、函数层面优化

Inline

对函数的 inline 就是去除了函数的层次化,可以通过 INLINE 这个 directive 来实现。对
函数inlining的好处是可以改善资源消耗,因为inline之后就不再需要调用函数的相关逻辑。
对于一些小函数 Vivado HLS 会自动进行 inlining 处理,可以改善相应的 QoR(quality of
results)。如果不希望对某个函数自动 inline 的话可以通过 INLINE 这个 directive 中的-off 选
项实现。自动 inline 时在综合时的信息输出窗口中可以看到相应的输出信息。 Inlinin 之后
在综合后的 RTL 代码中相应的函数结构就没有了。

Allocation

Allocation 实际上是定义了函数和相应的 RTL module 之间的关系,也就是定义了在 RTL
代码中实现某个具体函数或者操作的实例数量。这个功能可以通过 ALLOCATION 这个
directive 来实现。
Allocation 的主要作用就是使相同函数被多次调用时可以有多个实例,这样可以使之并
行执行,能够改善 latency 并提高吞吐率,但是要占用更多的资源。

Dataflow

Dataflow 在 for 循环优化中用到过,在这里应用于函数。如图 23-1 所示,在默认情况
下,数据相关的函数之间是按顺序执行的,当 Dataflow 之后,顺序处理就变成了并行处理。
函数之间通过 Channel 连接,channel 可以时 ping-pong RAM 也可以是 FIFO。
vivado HLS 优化总结以及相关流程_第9张图片
DATAFLOW 可以作用于顺序执行的一些任务,这些任务可以是函数、循环或者两者都
有,DATAFLOW 就是把顺序处理机制变成了并行处理机制。上图中的 channel 表示后面的
任务并不需要等到前面的任务完全执行完了再执行,而是只需要前面的有数据输出到下一个
任务就可以开始执行了。所以 DATAFLOW 允许任务之间有交叠(overlap),这里的重叠就
是上述的并行处理(parallel process),这种机制可以降低 latency。
vivado HLS 优化总结以及相关流程_第10张图片

八、总结分析

改善吞吐率( Throughput )

常用于改善吞吐率的 directive 有 PIPELINE、ARRAY_PARTITION、UNROLL、DATAFLOW
等。
PIPELINE 可以作用于函数和循环,当作用于循环是有个 option,叫做 rewind,该选项
可以进一步改善吞吐率。
对于数组可以使用 ARRAY_PARTITION 来把数组分割成不同的部分,有 3 种分割方式。
对于循环还可以采用 UNROLL 来优化,这时有个选项 factor 用于控制循环被复制成几
份来并行执行。
DATAFLOW 可以作用于函数和循环,是一种 ping-pong 操作的方式。
可以看出提高吞吐率实际上就是通过提高吞吐率来实现的。
vivado HLS 优化总结以及相关流程_第11张图片

改善时延( Latency)

常用于改善时延的 directives 有 LATENCY、LOOP_MERGE、LOOP_FLATTEN 等。
LATENCY 既可以作用于函数也可作用于循环。
LOOP_MERGE 用于将顺序的 Loop 合并在一起。
LOOP_FLATTEN 用于将嵌套的循环展开为一个大的循环。
vivado HLS 优化总结以及相关流程_第12张图片

改善资源( Area)

常用于改善资源的方法是设置更精确的数据类型和位宽,还有一些 directives,如 INLINE、
ALLOCATE、ARRAY_MAP、ARRAY_RESHAPE、FUNCTION_INSTANTIATE 等。
vivado HLS 优化总结以及相关流程_第13张图片

你可能感兴趣的:(llvm)