首页 > 其他分享 >HLS - 循环优化

HLS - 循环优化

时间:2023-06-29 16:36:55浏览次数:39  
标签:body int HLS ++ 循环 pragma 优化


1. 单个循环延迟优化

1.1 循环展开(Unroll)

  • 将一个循环展开成多个循环,复制多个循环电路,并行执行;消耗更多的资源换取加速效果。
  • 例子如下
for (int i = 0; i < 4; i++)
{  
#pragma HLS unroll factor=2  
    a[i] = b[i] + c[i];  
}
\\等效于
for (int i = 0; i < 4; i=i+2)
{    
    a[i] = b[i] + c[i];  
}
for (int i = 1; i < 4; i=i+2)
{  
    a[i] = b[i] + c[i];  
}
  • 这个优化要求循环边界为常数,才可以确定unroll factor设置为多少。
  • 对于循环次数较大的,展开后可能资源不足,导致unroll 失败;此时需要根据芯片实际资源数量,以及报错信息对factor进行调整。

1.2 循环展平(Flatten)

  • 相当于将内层循环合并到外层循环上,节省从内层循环过渡到外层循环时条件判断的延迟。
for (int i = 0; i < M; i++)
    for (int j = 0; j < N; j++)
    {
#pragma HLS loop_flatten
        // Loop body
    }
}
//等效于
for (int i = 0; i < M*N; i++)
    // Loop body
  • Flatten要求循环是完美循环/半完美循环。
    • 完美循环:循环的边界是常数,且循环体只出现在最内层循环。
    • 半完美循环:外循环的边界可以是变量,但内循环边界必须是常数;且循环体只能出现在最内层循环。

2. 多个循环的并行优化

2.1 循环合并

  • 即使多个循环之间完全独立,在RTL中默认是顺序执行,共要消耗A+B个周期。但是若将两种循环合并,那么只需要消耗max(A,B)个周期。
void func (...) {
#pragma HLS loop_merge
    L1: for (int i = 0; i < 8; i++) {
        // Loop body of L1

    L2: for (int i = 0; i < 4; i++)
        L3: for (int j = 0; j < 5; j++)
            // Loop body of L3

    L4: for (int i = 0; i < 13; i++)
        // Loop body of L4
}
//等效于
void func (...) {
    MERGED: for (int i = 0; i < 20; i++) {
        if (/* condition1 */)
            // Loop body of L1

        // Flattened loop body of L3

        if (/* condition4 */)
            // Loop body of L4
    }
}
  • 合并时应注意
    • 如果合并前,所有循环边界为常数,那么合并后的循环边界应该为常数间最大值。
    • 如果合并前,所有循环边界为变量,则循环边界必须相同。
    • 如果合并前,部分循环边界为变量,部分为常数,那么不能合并。

2.2 循环函数化

  • 如果两个循环的边界不同,则不能合并。但是可以将循环封装成子函数,实现并行。
  • 注意需要使用#pragma HLS inline off来防止内联。
    • HLS inline:去除子函数层次结构,使用内联操作使自身逻辑融入调用函数中。内联后的函数不能共享或重用。

2.3 数据流 Dataflow

  • 对于2个循环存在数据依赖关系时,不管循环合并或是循环函数化,都没有办法实现循环之间的并行;但是可以通过数据流实现。
  • 举例如下
    • 如果是非数据流执行方式,那么LOOP_2需要等待LOOP_1执行完成之后才能执行。
void func (int A[N], int C[N], int num) {
#pragma HLS dataflow
    int acc = 0;
    int B[N];

    LOOP_1: for (int i = 0; i < N; i++) {
#pragma HLS PIPELINE II=1
        acc += A[i];
        B[i] = acc;
    }

    LOOP_2: for (int i = 0; i < N; i++)
#pragma HLS PIPELINE II=1
        C[i] = B[i] * num;
}
  • Dataflow一般会在循环之间插入缓存,如果循环之间依靠变量传递数据,那么HLS会插入FIFO缓存;如果循环间依靠数组传数据,那么HLS会插入Ping-Pong RAM。
  • 由于存在循环到循环之间的缓存通路,所以只要LOOP_1中的数据输出就可以用于LOOP_2中的运算。多个任务间可以有交叠,降低延迟,提高数据吞吐率。
  • 注意
    • 循环之间数据只能顺序流动,不能有反馈回路。、
    • 数据流只能从一个循环流出到另一个循环,single-producer,single-consumer.
    • 循环不能在条件语句内。

3. 吞吐量优化:循环 - pipeline

#pragma HLS pipeline II=<int>
  • 对于下面左图中,RD距离下次RD间隔3个周期,即II=3;而右图II=1.若不指定,则默认为1.
    • 很明显,II = 1时,性能最好。但是代码中可能会因为数据依赖关系/存储器读写出现的冒险情况(具体可看流水线相关知识),而导致不满足设定的II;此时需要进行相应的优化,如消除依赖关系,数组划分等;后面有介绍。
  • 如果#pragma HLS pipeline 语句作用于嵌套循环的外层循环,那么需要将pragma下面所有的内层循环完全unroll。此时,如果循环边界为变量或展开后资源不够,那么展开会失败。
    • 若作用于函数,那么函数内所有循环都会被展开,同样存在导致展开失败的情况。

4. 吞吐量优化:循环 - DataFlow

  • "3"中介绍的是细粒度的流水线架构,而数据流可以实现粗粒度的流水线,具体实现与"2.3"相同。

  • pragma HLS loop_tripcount
    • 手动指定循环执行总的迭代次数,仅用于分析,不影响综合结果。
    • 可以指定max,min,average。

标签:body,int,HLS,++,循环,pragma,优化
From: https://www.cnblogs.com/qianbinbin/p/17514474.html

相关文章

  • 如何优化生鲜配送系统开发流程?
    为了满足人们对食品的安全和快速配送的需求,如何优化生鲜配送系统开发流程是一个值得开发者们去思考的问题。一个高效的生鲜配送系统不仅提高配送效率,还能减少成本、提升客户满意度,并为企业带来竞争优势。接下来,名锐讯动MRT将介绍一些开发的关键策略,助力优化生鲜配送系统的开发流程......
  • etcd 参数优化
    heartbeat-interval目前heartbeat-interval使用默认值即100, 较小的心跳间隔会导致发送频繁的消息,消耗CPU和网络资源。而较大的心跳间隔,又会导致检测到Leader故障不可用耗时过长,影响业务可用性。我们可以将其优化为300 election-timeout目前 election-timeout使用......
  • Java学习——循环结构
    循环结构while循环do...while循环for循环在Java5中引入了一种主要用于数组的增强型for循环breakcontinue一、while循环while(布尔表达式){ //循环内容只要布尔表达式为true,循环就会一直执行下去我们大多数情况是会让循环停止下来的,我们需要一个让表达式失......
  • m基于NB-IoT网络的SWAP资源分配优化算法matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:    2.算法涉及理论知识概要       NB-IoT是一种新兴的低功耗广域物联网(LPWAN)通信技术,它可以实现低功耗、低成本、大容量和广覆盖的特点,适用于物联网应用场景。在NB-IoT网络中,由于物联网设备的数量较大、通信频率较低......
  • 浅谈单调队列优化DP
    对于形如\[f_i=\max(f_{L≤j≤R}+w_i)\]的状态转移方程,也就是转移来自之前某个定长区间的最值,我们可以使用单调队列来维护区间最值,从而优化时间复杂度。烽火传递我们看到题目可以想到用\(f_i\)表示考虑到\(i\)这个烽火台,点第\(i\)个的合法方案中的最小代价那么可以想到......
  • Android ListView运行效率优化
    上篇介绍了ListView的用法,链接如下,这篇主要讲解如何提升ListView的效率Android定制ListView的界面1、使用缓存布局ListView如果不进行优化,其运行效率是很低的,因为在Adapter类的getView方法中,每次都将布局重新加载一遍,当ListView快速滚动时,这就会成为性能瓶颈。Adapter类的get......
  • 优化算法——拟牛顿法之DFP算法
    4、求解具体的优化问题  求解无约束优化问题function.py#coding:UTF-8'''Createdon2015年5月19日@author:zhaozhiyong'''fromnumpyimport*#fundeffun(x):return100*(x[0,0]**2-x[1,0])**2+(x[0,0]-1)**2......
  • 优化算法——拟牛顿法之BFGS算法
    一、BFGS算法简介  BFGS算法是使用较多的一种拟牛顿方法,是由Broyden,Fletcher,Goldfarb,Shanno四个人分别提出的,故称为BFGS校正。  同DFP校正的推导公式一样,DFP校正见博文“优化算法——拟牛顿法之DFP算法”。对于拟牛顿方程:。function.py#codin......
  • 优化算法——拟牛顿法之L-BFGS算法
    四、L-BFGS算法中的方向的计算方法五、实验仿真lbfgs.py#coding:UTF-8fromnumpyimport*fromfunctionimport*deflbfgs(fun,gfun,x0):result=[]#保留最终的结果maxk=500#最大的迭代次数rho=0.55sigma=0.4H0=eye(shape(x0)[0])......
  • 优化算法——截断梯度法(TG)
    一、L1正则的表达形式  在机器学习中,几乎无人不知无人不晓L1正则与L2正则,L1正则与L2正则都有参数控制的作用,对模型起到约束的作用,防止过拟合。但是L1正则与L2正则也有区别,L1正则更容易产生稀疏解,使得某些参数等于0,而L2正则却没有这样的优势,只能使得参数趋近于0。利用这样的优势......