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

HLS基础(1):循环展开与存储分块

目录

两个向量对应元素相加

实验概述

实验步骤

使用Vits HLS新建工程

使用自有开发板型号:xc7z020clg400-2 

编写vector_add头文件

编写vector_add源文件 

设置顶层函数为“vector_add” 

进行HLS综合

数据类型对生成电路有影响吗?

使用int变量 

使用ap_fixed变量

总结 

如何加速?

优化目标与理论预期

实际优化效果

性能瓶颈分析

改进方案建议

基本语法

分区类型(type)

(1) complete(完全分区)​​

(2) block(块分区)​​

​​(3) cyclic(循环分区)​​


两个向量对应元素相加

实验概述

本实验基于Xilinx Zynq-7000系列xc7z020clg400-2开发板,使用Vitis HLS工具实现两个向量的元素级加法运算。通过对比不同数据类型的实现效果,评估HLS综合性能差异。

实验步骤

使用Vits HLS新建工程

使用自有开发板型号:xc7z020clg400-2 

编写vector_add头文件


#define MAXNUM 50000void vector_add(float A[MAXNUM],float B[MAXNUM],float C[MAXNUM]);

编写vector_add源文件 

#include "vector_add.h"void vector_add(float A[MAXNUM],float B[MAXNUM],float C[MAXNUM]){for(int i=0;i<MAXNUM;i++){C[i] = A[i] + B[i];}
}

设置顶层函数为“vector_add” 

进行HLS综合

从综合结果可以看出:

时序表现​​:

  • 目标周期:10.00 ns
  • 实际估计周期:6.329 ns(裕量3.671 ns)
  • 时序不确定性:2.70 ns

循环结构​​:

  • 循环总延迟:50,009周期(对应50006次迭代)
  • 迭代间隔:1周期(已流水线化)
  • 启动间隔(II)=1,但循环总延迟偏高

数据类型对生成电路有影响吗?

上文中我们使用的数据类型为float类型, 这里实验验证一下不同数据类型的结果差异。对float/int/ap_fixed三种数据类型进行对比测试:

使用int变量 


#define MAXNUM 50000void vector_add(int A[MAXNUM],int B[MAXNUM],int C[MAXNUM]);
#include "vector_add.h"void vector_add(int A[MAXNUM],int B[MAXNUM],int C[MAXNUM]){for(int i=0;i<MAXNUM;i++){C[i] = A[i] + B[i];}
}

使用ap_fixed变量

#include <ap_fixed.h>typedef ap_fixed<32,16,AP_RND,AP_SAT> D32;#define MAXNUM 50000void vector_add(D32 A[MAXNUM],D32 B[MAXNUM],D32 C[MAXNUM]);
#include "vector_add.h"void vector_add(D32 A[MAXNUM],D32 B[MAXNUM],D32 C[MAXNUM]){for(int i=0;i<MAXNUM;i++){C[i] = A[i] + B[i];}
}

总结 

  • 浮点运算会触发DSP硬核调用,增加布线延迟
  • 定点数(ap_fixed)在保持精度的同时,比float节省时序开销
  • 整型实现性能最优,但需考虑数值范围限制

如何加速?

优化目标与理论预期

我们尝试通过循环展开(UNROLL)技术对向量加法进行加速优化:

  • 原始循环延迟:50,000周期(每次迭代处理1个元素)
  • 展开因子(UNROLLNUM):50
  • 理论预期延迟:50,000/50 = 1,000周期

#include "vector_add.h"#define UNROLLNUM 50void vector_add(D32 A[MAXNUM],D32 B[MAXNUM],D32 C[MAXNUM]){for(int i=0;i<MAXNUM;i+=UNROLLNUM){for(int j=0;j<UNROLLNUM;j++){
#pragma HLS UNROLLC[i+j] = A[i+j] + B[i+j];}}
}

实际优化效果

实际综合结果显示:

  • 实测延迟:25,000周期
  • 加速比:仅2倍(未达预期的50倍)

性能瓶颈分析

造成此现象的根本原因是BRAM的端口访问限制:

​BRAM架构特性​​:

  • 每个BRAM模块仅支持:
    • 最多2个并发读端口
    • 1个写端口

​当前实现限制​​:

C[i+j] = A[i+j] + B[i+j];  // 需要同时读取A和B各1个元素
  • 每次迭代需要:
    • 2个读操作(A和B各1个)
    • 1个写操作(C)
  • 实际每周期最多只能完成:
    • 读取2个A元素 + 2个B元素
    • 即每次处理2组加法运算

改进方案建议

调整展开因子匹配硬件限制。

这里ARRAY_PARTITION的参数介绍一下:

在Vivado HLS中,ARRAY_PARTITION指令用于优化数组的存储方式,通过改变数组在硬件中的实现结构来提高并行性和访问效率。

基本语法

#pragma HLS ARRAY_PARTITION variable=<数组名> type=<分区类型> factor=<分区因子> dim=<维度>
  • variable​: 要分区的数组名(必需)
  • type​: 分区类型(completeblockcyclic,必需)
  • factor​: 分区因子(指定分区数量,可选,默认为2)
  • dim​: 多维数组的分区维度(从1开始,可选)

分区类型(type)

(1) complete(完全分区)​
  • ​作用​​:将数组完全拆分为独立的寄存器。
  • ​硬件实现​​:每个数组元素都变成单独的寄存器。
  • ​适用场景​​:小型数组(元素数量≤64),需最大化并行访问。
(2) block(块分区)​
  • ​作用​​:将数组连续元素分组到不同存储单元。
  • ​硬件实现​​:按块分配到多个BRAM或寄存器。
  • ​适用场景​​:需要按块顺序访问的数组。
  • 示例​​(分4块):
    int buffer[128];
    #pragma HLS ARRAY_PARTITION variable=buffer type=block factor=4
    • 分区后:
      • buffer[0:31] → 存储单元0
      • buffer[32:63] → 存储单元1
      • ...以此类推 
​(3) cyclic(循环分区)​
  • ​作用​​:轮询分配元素到不同存储单元。
  • ​硬件实现​​:元素按轮询方式分布(类似交织)。
  • ​适用场景​​:需要同时访问非连续元素(如循环展开)。
  • int buffer[128];
    #pragma HLS ARRAY_PARTITION variable=buffer type=cyclic factor=4
    示例​​(分4块):
    • 分区后:
      • buffer[0,4,8,...] → 存储单元0
      • buffer[1,5,9,...] → 存储单元1
      • ...以此类推
type=cyclicUNROLL配合循环展开实现并行访问
type=block+ 顺序访问模式适合按块顺序处理的算法(如卷积核)

成功将周期从50000降到1000!!

http://www.lryc.cn/news/580215.html

相关文章:

  • 深入剖析MYSQL MVCC多版本并发控制+ReadView视图快照规避幻读问题
  • Kuberrnetes 服务发布
  • AI领域新趋势:从提示(Prompt)工程到上下文(Context)工程
  • Spring Boot + 本地部署大模型实现:优化与性能提升
  • 【排序算法】
  • 模型部署与推理--利用libtorch模型部署与推理
  • 前端捕获异常的全面场景及方法
  • MYSQL 服务正在启动或停止中,请稍候片刻后再试一次。
  • Java 与 MySQL 性能优化:MySQL全文检索查询优化实践
  • 在 Ubuntu 22.04 上使用 Minikube 部署 Go 应用到 Kubernetes
  • 微服务架构下的抉择:Consul vs. Eureka,服务发现该如何选型?
  • 本地部署Dify并结合ollama大语言模型工具搭建自己的AI知识库
  • 软件反调试(4)- 基于IsDebuggerPresent的检测
  • Docker学习笔记:Docker网络
  • LDO VS DCDC
  • Redis的缓存击穿和缓存雪崩
  • [C++] C++多重继承:深入解析复杂继承关系
  • 每周资讯 | Krafton斥资750亿日元收购日本动画公司ADK;《崩坏:星穹铁道》新版本首日登顶iOS畅销榜
  • 小架构step系列04:springboot提供的依赖
  • XION:玩转您的第一个智能合约
  • WPS中配置MathType教程
  • Linux入门篇学习——Linux 帮助手册
  • 三、jenkins使用tomcat部署项目
  • 【开源品鉴】FRP源码阅读
  • LangChain 全面入门
  • 数据结构入门:链表
  • 服务器的IO性能怎么看?
  • 数据库11:MySQL 库的操作、库的说明与表的操作、表的说明
  • 电机转速控制系统算法分析与设计
  • 微信小程序如何实现再多个页面共享数据