当前位置: 首页 > news >正文

基于 FPGA的HLS技术与应用

1、hls简介

        HLS ( high level synthesis )即高层次综合,主要是利用高级编程语言实现算法。 

2、循环优化

        约束语法:

                        #pragma HLS unroll        

                        #pragma HLS PIPELINE II=1

        绝大多数循环都以串行的方式执行,这种执行方式比较浪费时间。对于串行的循环有两种优化方式,转为 并行( Unroll ) 或者是 管道( Pipeline )。

        并行分为以下几种:

                数据并行:对不同的数据处理。

                线程并行:多线程并发处理。

                指令并行:同一时间执行多条指令。

                管道并行:多条指令同时执行,但不同时间执行指令的不同部分。

        其中,数据并行为最理想的循环执行方式;不过大多数时候数据存在复杂的依赖关系,常采用管道并行的循环执行方式。

3、性能度量

        在软件开发领域,通过使用算法复杂度 O(n)进行度量;

        在FPGA中,使用启动时间间隔( Initiation Interval ,II )进行度量;

                1、II 表示每次迭代之间的时间间隔

                2、理想情况下,II = 1 

                3、如果 II 非常大,说明 对应的代码不能在FPGA中被展开或者pipeline。

        循环依赖

                在循环过程中存在内存依赖或者数据依赖都会导致操作延时,例如下面代码就存在内存4、依赖

for( ... )
{A[x] = A[y]    ;
}

        这样的代码会导致 II 比较大,应为 A[x] 依赖于 A[y] ,对应的硬件必须等待对应的依赖关系完成之后才能完成。

        4.1、        消除依赖

                消除依赖是指通过算法优化或者一些技巧对 内存依赖 或者 数据依赖 进行消除,从而减小 II。

                先看一段未经优化的代码:外层for每个 clk都会启动,而内层for需要外层的sum,导致循环变成串行结构。

int sum = 0    ;
for( i = 0;i < N;i++ )
{for( j = 0;j < N;j++ ){sum += A[i*N+j]    ;}sum += B[i]    ;
}

                 修改如下:对于内层的for增加一个sum2,使内层for和外层for之间没有依赖,从而使串行变成 unroll or pipeline执行流程,降低代码的 II 。

int sum = 0    ;
for( i = 0;i < N;i++ )
{int sum2    =    0    ;    for( j = 0;j < N;j++ ){sum2 += A[i*N+j]    ;}sum += sum2    ;sum += B[i]    ;
}

                4.2、        将 依赖放宽

        先看一段未经优化的代码:假如执行一个乘的 II 为 6 ,该例存在数据依赖,消耗时间为 6N

float    mul = 1.0f    ;
for( i = 0 ;i < N ; i++ )
{mul    =    mul * A[i]    ;
}

                修改如下:

#include	"learn_for.h"#define		M	6
#define		N	12void	learn_for(uint32		A[10])
{int		 i ,j			  ;float    mul = 1.0f       ;float    mul_copies[M]    ;loop_initialized:for( i = 0 ; i < M ; i++ ){mul_copies[i] = 1.0f    ;}loop_assign_mul_cur:for( i = 0 ; i < N ; i++ ){float cur = mul_copies[M-1] * A[i]    ;loop_assign_copies:for( j = M - 1 ; j > 0 ; j-- ){#pragma HLS unrollmul_copies[j] =  mul_copies[j-1]    ;}mul_copies[0]    =    cur    ;}loop_assign_mul:for( i = 0 ; i < M ; i++ ){#pragma HLS unrollmul = mul * mul_copies[i]    ;}
}

       

         循环展开的优点:

                1、直接利用FPGA硬件,对循环内部逻辑进行复制

                2、编译器会重新分析所有的依赖,允许编译器进行最大程度的代码优化

                3、降低模块的延迟

                4、提高资源的利用率

5、设置端口为bram端口

#pragma HLS BIND_STORAGE variable=out_data type=ram_1p impl=bram
#pragma HLS BIND_STORAGE variable=in_data type=ram_1p impl=bram
#pragma HLS INTERFACE mode=bram port=out_data
#pragma HLS INTERFACE mode=bram port=in_data

 6、嵌套循环

        编写嵌套循环时,需要注意的事项:

                        1、内层循环通常是影响性能的关键部分

                        2、通常情况下,大多数工作要置于内层循环

                        3、因 尽可能将内层循环的 II 接近 1 

        HLS代码优化的总体原则:

                1、避免指针别名

                2、最小化内存依赖

                3、将嵌套循环改为单层循环

                说明如下:

                        1、指针别名:是指多个不同的指针指向相同的内容。

注:

        ARRAY_PARTITION :用于优化数组的存储和访问,将一个大数组分割成多个小数组,以提高并行处理能力和减少访问延迟。

 


http://www.mrgr.cn/news/95393.html

相关文章:

  • 可发1区的超级创新思路:基于注意力机制的DSD-CNN时间序列预测模型(功率预测、交通流量预测、故障检测)
  • VLAN综合实验报告
  • Mybatis—01
  • C 语 言 --- 操 作 符 2
  • 第十五次CCF-CSP认证(含C++源码)
  • 【蓝桥杯—单片机】IAP15F2K61S2专项 | 真题整理、解析与拓展 | 省赛题(更新ing...)
  • 【C++指南】内存管理完全手册:new/delete
  • 【MySQL】索引
  • 二分查找上下界问题的思考
  • 第一讲 | 解锁C++编程能力:基础语法解析
  • java使用Apache POI 操作word文档
  • 【STM32】SPI通信协议W25Q64Flash存储器芯片(学习笔记)
  • 【初探数据结构】二叉树的顺序结构——堆的实现详解(上下调整算法的时间复杂度分析)
  • 【人工智能】LM Studio 的 GPU 加速:释放大模型推理潜能的极致优化
  • 使用PlotNeuralNet绘制ResNet50模型
  • 大数据 Spark 技术简介
  • 善用批处理的for命令倍增效率(附彩蛋:windows官方bug)
  • node-ddk, electron组件, 自定义本地文件协议,打开本地文件
  • Json的应用实例——cad 二次开发c#
  • C++ 语法之数组指针