【雪天鱼】Vitis HLS 学习笔记(1) Pipelining 流水线

news2024/11/17 3:34:49

文章目录

  • 1 自媒体账号
  • 2 Pipelining 流水线
    • 2.1 只对最内层的 LOOP_J 循环进行 pipeline
    • 2.2 对最外层的 LOOP_I 循环进行 pipeline
    • 2.3 对函数 loop_pipeline 进行 pipeline,并对数组A进行分组
    • 2.4 思考

1 自媒体账号

目前运营的自媒体账号如下:

  • 哔哩哔哩 【雪天鱼】: 雪天鱼个人主页-bilibili.com
  • 微信公众号 【雪天鱼】
    |550
  • CSDN 【雪天鱼】: 雪天鱼-CSDN博客

QQ 学习交流群

  • FPGA科研硕博交流群 910055563 (进群有一定的学历门槛,长期未发言会被请出群聊,主要交流FPGA科研学术话题)
  • CNN | RVfpga学习交流群(推荐,人数上限 2000) 541434600
  • FPGA&IC&DL学习交流群 866169462

菜鸡一枚,记录下自己的学习过程,可能后续有更新,也可能没有更新,谨慎参考。

2 Pipelining 流水线

示例代码链接:Vitis-HLS-Introductory-Examples/Pipelining/Loops/pipelined_loop at master · Xilinx/Vitis-HLS-Introductory-Examples · GitHub

GUI 图形化界面

  1. 创建 HLS 工程,复制 loop_pipeline.cpploop_pipeline.h 源文件到该工程 src目录(自己建一个)中并添加
  2. Project Settings -> Synthesis -> 选择要综合的 Top Function
  3. 运行 C综合,并进行结果分析

TCL 脚本操作

  1. 修改 set_part 命令后的芯片型号,确保可用,每次创建一个 solution 都要指定,所以都需要修改下

源文件 loop_pipeline.cpp:

#include "loop_pipeline.h"

dout_t loop_pipeline(din_t A[N]) {

    int i, j;
    static dout_t acc;

LOOP_I:
    for (i = 0; i < 20; i++) {
    LOOP_J:
        for (j = 0; j < 20; j++) {
            acc += A[j] * i;
        }
    }

    return acc;
}

该函数接收数组 A 作为输入,并通过两层嵌套循环计算一个累加表达式 sum(i * A[j]),其中 ij 都是从 0 到 19的整数。最终,函数返回这个累加的结果。接下来进行采用不同的优化指令的综合结果的分析。

2.1 只对最内层的 LOOP_J 循环进行 pipeline

  • 试了下对 LOOP_J 添加 set_directive_pipeline -off "loop_pipeline/LOOP_J" 编译指示也无法关闭对最内层循环的pipeline,说明 Vitis HLS 可能默认就会优化循环的 II,进行 pipeline .
  • C++ 综合报告:

image.png

基础概念在 UG1399 的 ch.15 分析综合的结果 章节的 小节 调度查看器中有
image.png

LOOP_J 循环单次迭代所需要的时钟周期数(对应报告中的是 Iteration Latency)是 5,然后两次迭代之间的启动时间间隔(对应报告中的 Interval) 是 1, 循环完成的总迭代数( Trip Count)是 400, 即 20x20,循环完成所有迭代所需的时钟周期数(Latency)为 403, 可以理解为 5 + (400 - 1)= 404 (这里不知道为什么少了一周期),即 Latency = Iteration Latency + (Trip Count - 1) x II

image.png|875
可以参考此图进行理解,无流水线化时 (A) 循环完成3次迭代需要 3x3=9 cycles, 循环流水打拍后(B) 需要 3 +(3-1)=5个周期

我们来把 II 设置为3时,看下结果,根据上面的式子得到 Latency = Iteration Latency + (Trip Count - 1) x II = 5 + 399 x 3 = 1202
(与 HLS 结果相比还是多了一个周期,猜测是HLS是从0计数导致?)

image.png|875

这里我们就可以看出来,对循环的总延迟影响比较大的是 Trip Count 和 II,而 Trip Count 在设计中一般是和实现的算法绑定的比较深的,能比较自由优化的往往是 II, II=3时,可以看到 LUT 是比 II=1时 少用了一些资源,说明当优化 II 时,可能会导致额外的资源开销。而迭代的延迟是和该循环每次迭代进行的具体操作有关,可以打开 Schedule Viewer 进行查看

image.png
从图中可以看出来,一次迭代主要是加载 A[j] 数据,乘以 i, 以及 累加 acc这三步,所以单次迭代内进行的操作越复杂,所需要的延迟就越大。

2.2 对最外层的 LOOP_I 循环进行 pipeline

image.png
循环就直接没有迭代了,也就是说可以一次性把原先需要迭代 400 次的循环给计算完毕。这里查看如下的C++综合 log 可以发现对 LOOP_J 进行了 unroll 展开,并且是完全展开。可以在一次迭代中完成原先的 LOOP_J 所有计算,而 LOOP_I 没有过多的数据依赖, i 的值是已知的0~19, 所以猜测这里通过表达式优化,直接把所有循环都展开了。

这里的表达式优化是指:每个 A[j] 都会和 0~19都乘以一遍,可以直接求和 0~19,然后一起乘以A[j], 而由于 A[j] 与同一被乘数相乘,所以还可以累加所有的 A[j]

INFO: [XFORM 203-502] Unrolling all sub-loops inside loop 'LOOP_I' (loop_pipeline.cpp:5) in function 'loop_pipeline' for pipelining.
INFO: [HLS 200-489] Unrolling loop 'LOOP_J' (loop_pipeline.cpp:5) in function 'loop_pipeline' completely with a factor of 20.
INFO: [XFORM 203-11] Balancing expressions in function 'loop_pipeline' (loop_pipeline.cpp:5:26)...19 expression(s) balanced.
INFO: [HLS 200-111] Finished Loop, function and other optimizations: CPU user time: 0 seconds. CPU system time: 0 seconds. Elapsed time: 0.111 seconds; current allocated memory: 166.698 MB.
INFO: [HLS 200-111] Finished Architecture Synthesis: CPU user time: 0 seconds. CPU system time: 0 seconds. Elapsed time: 0.058 seconds; current allocated memory: 163.661 MB.
INFO: [HLS 200-10] Starting hardware synthesis ...
INFO: [HLS 200-10] Synthesizing 'loop_pipeline' ...

通过 Schedule Viewer 发现 0~9 每个时钟周期加载了两个 A[j]的值并存储,然后在此过程中不断的累加 A[j]i的值,在第10 ~ 11 完成两个累加结果最终相乘。在第 12 周期完成与 acc 初值的累加,在第 13 周期完成结果的写回。

2.3 对函数 loop_pipeline 进行 pipeline,并对数组A进行分组

编译指示:

set_directive_pipeline "loop_pipeline"
set_directive_array_partition -dim 0 -type complete "loop_pipeline" A

综合报告:
image.png

假设我们能在一个时刻而不是顺序依次读取所有 A[j],然后 DSP 的数量也足够,那么可以在一个周期内完成所有 A[j] 与 sum(0, 19)的累加值的相乘,查看 Schedule Viewer 发现 0~4周期用 17个 DSP 完成了所有乘法,第 0~6 周期完成所有加法,最后写入结果。

2.4 思考

  • 如何在对最外层的 LOOP_I 循环进行 pipeline 时,控制最内层的 LOOP_J 部分展开。
    尝试的方法:
  • 编译指示solution: 对最外层的 LOOP_I 进行 pipeline 的同时,设置 LOOP_J 按因数 factor = 10 展开 不可行
set_directive_pipeline "loop_pipeline/LOOP_I"
set_directive_unroll -factor 10 "loop_pipeline/LOOP_J"

但实际测试外层的pipeline 会强制完全展开内循环,相关 log 如下:

INFO: [HLS 214-188] Unrolling loop 'LOOP_J' (loop_pipeline.cpp:11:9) in function 'loop_pipeline' partially with a factor of 10 (loop_pipeline.cpp:3:0)
INFO: [XFORM 203-502] Unrolling all sub-loops inside loop 'LOOP_I' (loop_pipeline.cpp:5) in function 'loop_pipeline' for pipelining.
WARNING: [XFORM 203-503] Ignored partial unroll directive for loop 'LOOP_J' (loop_pipeline.cpp:5) because its parent loop or function is pipelined.
INFO: [HLS 200-489] Unrolling loop 'LOOP_J' (loop_pipeline.cpp:5) in function 'loop_pipeline' completely with a factor of 2.

可以看到 WARNING 报的信息是 由于父循环是被 pipelined,所有内循环的部分展开被忽略,强制按 factor = 10x2=20 完全展开

  • 编译指示solution: 对最外层的 LOOP_I 不进行 pipeline 的同时,设置 LOOP_J 按因数 factor = 10 展开,与此同时,由于可以同时进行内循环不同迭代的计算了,所以需要对 A数组进行分组,确保可以同时读取对应的A数组中的元素,否则 II 是没法正常优化为 1 的 可行
set_directive_unroll -factor 10 "loop_pipeline/LOOP_J"
set_directive_array_partition -dim 0 -type complete "loop_pipeline" A

image.png
Latency = 4 + (40-1) x 1 = 43, Trip Count = 20x20 / factor(10) = 40
而且这里自动给 II 优化为了 1, 相当于 pipeline 了

没有数组分组的综合报告:
image.png
最终优化后的 II 由于数组接口限制就没法达到 1,而是变为了 5

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1615277.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【uniapp】【uview2.0】【u-sticky】Sticky 吸顶

把pages.json文件中的 “navigationStyle"设置为"custom”, 出现的问题是&#xff0c;莫名奇妙多了个 一个高度 解决方法 /* 使用CSS的sticky定位 */ .sticky {/* #ifdef H5 */ position: -webkit-sticky;position: sticky;top: 0; /* 设置距顶部的距离 */z-ind…

《王者荣耀》Hello Kitty 小兵皮肤完整设置指南

王者荣耀与三丽鸥的联动活动上线了 Hello Kitty 小兵皮肤&#xff0c;让我们的峡谷小兵们也能穿上漂亮的衣服啦&#xff01;这款皮肤极具卡哇伊风格&#xff0c;引起了许多玩家的关注。许多小伙伴都想知道如何使用这款 Hello Kitty 小兵皮肤&#xff0c;今天小编将为大家整理出…

1081. 度的数量(@数位dp)

活动 - AcWing 求给定区间 [X,Y] 中满足下列条件的整数个数&#xff1a;这个数恰好等于 K 个互不相等的 B 的整数次幂之和。 例如&#xff0c;设 X15,Y20,K2,B2&#xff0c;则有且仅有下列三个数满足题意&#xff1a; 172420 182421 202422 输入格式 第一行包含两个整数 X…

恶意软件逆向工程:Ghidra 入门 -第三部分-分析 WannaCry 勒索软件

逆向工程是最受欢迎和最有价值的网络安全/信息安全技能之一。但很少有人能将自己的技能水平发展到精通这一备受追捧的技能。Ghidra 是美国间谍机构 NSA 提供的一种相对较新且免费的逆向工程工具。 在本教程中&#xff0c;我们将研究历史上最臭名昭著的一个恶意勒索病毒&#x…

使用docker部署数据可视化平台Metabase

目前公司没有人力开发数据可视化看板&#xff0c;因此考虑自己搭建开源可视化平台MetaBase。在此记录下部署过程~ 一、镜像下载 docker pull metabase/metabase:latest 运行结果如下&#xff1a; 二、创建容器 docker run -dit --name matebase -p 3000:3000\ -v /home/loc…

vulfocus靶场名称: apache-cve_2021_41773/apache-cve_2021_42013

Apache HTTP Server 2.4.49、2.4.50版本对路径规范化所做的更改中存在一个路径穿越漏洞&#xff0c;攻击者可利用该漏洞读取到Web目录外的其他文件&#xff0c;如系统配置文件、网站源码等&#xff0c;甚至在特定情况下&#xff0c;攻击者可构造恶意请求执行命令&#xff0c;控…

程序员缓解工作压力的小窍门

目录 1.概述 2.工作与休息的平衡 3.心理健康与自我关怀 4.社交与网络建设 1.概述 作为程序员&#xff0c;缓解工作压力是非常重要的。压力太大有可能会写很多bug。我们可以采取以下方法来保持高效和创新&#xff0c;同时维护个人健康和工作热情。 定时休息&#xff1a;保持…

手写Promise实现

手写Promise实现 一、前言二、代码三、测试四、测试结果 一、前言 阅读参考资料&#xff0c;本文整理出使用 构造函数 手撕出 Promise 的方法&#xff0c;在整理过程中不断添加注解以示思路。有错请指出哟&#xff0c;一起进步&#xff01;&#xff01;&#xff01;class 实现 …

【做一名健康的CSDNer】程序员哪几种行为最伤肾(程序员必看)

虽然没有专门针对程序员这一职业群体特有的伤肾行为的研究报道&#xff0c;但根据一般人群的健康风险和生活习惯&#xff0c;程序员由于其特殊的工作模式和环境&#xff0c;可能更容易出现如下伤肾的行为&#xff1a; 熬夜加班&#xff1a; 程序员由于项目进度、bug修复等原因&…

1、opencv介绍与开发环境搭建

1、opencv介绍 OpenCV 是 Intel 开源计算机视觉库&#xff0c;是一个跨平台的开源计算机视觉和机器学习软件库。它由一系列 C 函数和少量 C 类构成&#xff0c;可用于开发实时的图像处理、计算机视觉以及模式识别程序。 该库有 2500 多种优化算法&#xff0c;其中包括一套全面…

HarmonyOS ArkUI实战开发-NAPI 加载原理(上)

笔者在前 6 小结讲述了NAPI 的基本使用&#xff0c;包括同步和异步实现&#xff0c;本节笔者从源码的角度简单讲解一下NAPI 的加载流程&#xff0c;源码版本为 ArkUI 4.0 Release 版本。 hap 工程结构 工程配置签名后打一个 hap 包出来&#xff0c;然后解压该 hap 文件&#…

重发布及路由策略实验

目录 一、实验拓扑 二、实验需求 1、按照图示配置 IP 地址&#xff0c;R1&#xff0c;R3&#xff0c;R4 上使用 loopback 口模拟业务网段 2、R2&#xff0c;R3 和R4运行 oSPF&#xff0c;各自协议内部互通 3、在 RIP 和 oSPF 间配置双向路由引入&#xff0c;要求除 R4 上的…

C++初阶学习第二弹——C++入门(下)

C入门&#xff08;上&#xff09;&#xff1a;C初阶学习第一弹——C入门&#xff08;上&#xff09;-CSDN博客 目录 一、引用 1.1 引用的实质 1.2 引用的用法 二、函数重载 三、内敛函数 四、auto关键字 五、总结 前言&#xff1a; 在上面一章我们已经讲解了C的一些基本…

【C语言】strstr函数刨析-----字符串查找

目录 一、strstr 函数介绍 ✨函数头文件&#xff1a; ✨函数原型&#xff1a; ✨函数解读 ✨功能演示 二、函数的原理以及模拟实现 ✨函数原理 ✨函数的模拟实现 三、strstr函数的注意事项 四、共勉 一、strstr 函数介绍 strstr函数是在一个字符串中查找另一个字符…

Leetcode 86. 分隔链表

题目链接&#xff1a; 86. 分隔链表 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/partition-list/description/ 题目&#xff1a; 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出…

CDN技术:全球化的数字内容快速分发系统

CDN技术&#xff1a;全球化的数字内容快速分发系统 在今天的互联网世界中&#xff0c;内容分发网络&#xff08;CDN&#xff09;技术起着至关重要的作用。它通过全球分布的服务器网络&#xff0c;快速、安全地将内容送达世界各地的用户&#xff0c;极大地提升了网页加载速度和…

SpringBoot+vue开发记录(二)

说明&#xff1a;本篇文章的主要内容为SpringBoot开发中后端的创建 项目创建: 1. 新建项目&#xff1a; 如下&#xff0c;这样简单创建就行了&#xff0c;JDK什么的就先17&#xff0c;当然1.8也是可以的&#xff0c;后面可以改。 这样就创建好了&#xff1a; 2. pom.xml…

【Android12】Bugreport实现原理

Bugreport实现原理 Bugreport Bugreport介绍 Android Bugreport是一个用于记录和收集 Android设备上系统信息、日志和调试信息的工具。 系统发生某些问题时&#xff0c;可以通过bugreport把系统当前时刻点&#xff08;运行BugRepot的时刻&#xff09;的系统相关的状态和信息…

Redis中BitMap在钉钉机器人中的应用

性能分析 数据库中有1000w用户&#xff0c;每个用户签到一次&#xff0c;对应两个字段 连续签到多少次 、签到时间。 签到时间字段占用10个字节&#xff0c;连续签到多少天 占用5个字节&#xff08;假设一个用户能活100年&#xff0c;每天都签到&#xff0c;一个用户最多签到3…

【爬取研招网指定学校专业信息】

前言 本文介绍了如何使用 Python 的 requests 库和 BeautifulSoup 库来爬取研究方向信息&#xff0c;并将其保存为 CSV 文件。爬取的网站为“中国研究生招生信息网”&#xff08;https://yz.chsi.com.cn/&#xff09;。代码从指定的专业目录页面爬取研究方向的相关信息&#x…