Vitis HLS 学习笔记--scal 函数-探究

目录

1. Vitis HLS重器-Vitis_Libraries

2. 初识scal()

3. 函数具体实现

3.1 变量命名规则

3.2 t_ParEntries解释

3.3 流类型详解

3.4 双重循环

4. 总结


1. Vitis HLS重器-Vitis_Libraries

在深入探索Vitis HLS(High-Level Synthesis)的旅程中,我们不得不提一个至关重要的里程碑——那就是熟练运用Vitis Libraries。这个库集合了众多领域内关键的函数,并提供了它们的硬件实现版本。这对于那些希望将软件算法高效转换为硬件描述的开发者来说,无疑是一大福音。以BLAS(Basic Linear Algebra Subprograms)库中的scale函数为例,我们可以看到这些库的实用性和强大功能。

scale函数的作用听起来非常直接:计算Y = alpha * X,其中alpha是一个标量,X是一个向量,这个操作将X中的每个元素乘以alpha,得到新的向量Y。乍一看,scale函数的功能似乎异常简单,直白。然而,当我们深入其函数参数时,事情开始变得有些复杂:

template  <typename t_DataType, unsigned int t_ParEntries, typename t_IndexType = unsigned int>
void scal(unsigned int p_n,t_DataType p_alpha,hls::stream<WideType<t_DataType, t_ParEntries>>& p_x,hls::stream<WideType<t_DataType, t_ParEntries>>& p_res)

这段代码中充满了模板参数、数据类型和流对象,令初看之下显得颇为复杂。对于初学者来说,这些参数和类型定义可能会让人感到困惑,特别是对于那些刚接触硬件设计领域的学生或工程师而言。但别担心,今天我们就来一步步解析这些参数,揭开scal函数背后的神秘面纱。

2. 初识scal()

  • t_DataType指的是数据类型,这意味着scal函数能够支持不同的数据类型操作,增加了函数的通用性。
  • t_ParEntries定义了每次操作可以处理的数据量,这直接关联到了算法的并行度和处理效率。
  • t_IndexType通常用作索引的数据类型,默认为unsigned int,这提供了足够的灵活性来适应不同大小的数据集。
  • p_n参数指定了向量X中元素的数量
  • p_alpha是乘法因子alpha。
  • p_x和p_res分别是输入和输出数据的流对象,它们使用了WideType模板,这是一种封装了并行数据条目的类型,允许数据以流的形式进行高效处理。

通过这样的设计,scal函数不仅仅是一个简单的比例计算函数,而是一个高度优化且可定制的并行数据处理单元,能够在硬件级别上实现高效的线性代数运算。这种深度优化的实现方式,虽然在一开始可能让人望而生畏,但一旦掌握,便能大幅提升数据处理任务的性能。

3. 函数具体实现

接下来,我们详细研究每一处细节。函数实现如下:

template <typename t_DataType, unsigned int t_ParEntries, typename t_IndexType = unsigned int>
void scal(unsigned int p_n,t_DataType p_alpha,hls::stream<typename WideType<t_DataType, t_ParEntries>::t_TypeInt>& p_x,hls::stream<typename WideType<t_DataType, t_ParEntries>::t_TypeInt>& p_res) {
#ifndef __SYNTHESIS__assert((p_n % t_ParEntries) == 0);
#endifconst unsigned int l_parEntries = p_n / t_ParEntries;for (t_IndexType i = 0; i < l_parEntries; ++i) {
#pragma HLS PIPELINEWideType<t_DataType, t_ParEntries> l_valX;WideType<t_DataType, t_ParEntries> l_valY;l_valX = p_x.read();for (unsigned int j = 0; j < t_ParEntries; ++j) {l_valY[j] = p_alpha * l_valX[j];}p_res.write(l_valY);}
}

3.1 变量命名规则

  • t_DataType,t_前缀表示template,模板参数
  • p_n,p_前缀表示parameter,函数参数
  • l_abs,l_前缀表示local,函数内部变量(局部变量)

3.2 t_ParEntries解释

const unsigned int l_parEntries = p_n / t_ParEntries;

用途:计算在给定并行度 t_ParEntries 下,需要进行多少次迭代来处理整个输入向量。

  • p_n 是输入向量 X 的元素总数。
  • t_ParEntries 是每次可以并行处理的元素数。
  • 注意p_n / t_ParEntries必须能被整除。

因此,l_parEntries 是迭代的总次数,即必须执行多少次循环迭代来处理整个向量 X,使每个元素都乘以 alpha。

图示说明:

如果向量 p_n 包含9个元素(即 p_n=9),并且设定并行度 t_ParEntries=3,则最多可以有3个并行执行的流水线同时进行计算,通过三次迭代就可以完成整个向量的运算。换句话说,每次迭代处理3个元素,总共需要3次迭代来覆盖所有9个元素。

也可以设置 t_ParEntries=9,这样一来,整个向量的乘法运算可以在单次迭代中完成。

加入迭代间隔(II)为1,这意味着在一个周期内就可以完成所有9个元素的乘法运算。当然,这种配置会消耗更多的硬件资源,因为它需要在同一时刻支持更多的并行乘法操作。

这种权衡是在硬件资源消耗与运算速度之间进行的。选择更高的并行度可以减少所需的总迭代次数,从而加快运算速度,但代价是需要更多的硬件资源来实现这种高并行度。相反,较低的并行度虽然硬件资源消耗更少,但需要更多的迭代次数来完成相同的计算,可能导致整体性能降低。

3.3 流类型详解

hls::stream<typename WideType<t_DataType, t_ParEntries>::t_TypeInt>& p_x

hls::stream<typename WideType<t_DataType, t_ParEntries>::t_TypeInt>& p_res

关键字typename的作用:在模板编程中,编译器并不能自动推断出所有的名字是否代表类型。特别是当类型依赖于模板参数时,这里t_TypeInt就是一个依赖模板参数的类型,我们也称其为依赖类型。typename为了告诉编译器t_TypeInt是一个类型。

进一步我们调查t_TypeInt的定义:

template <typename T, unsigned int t_Width, unsigned int t_DataWidth = sizeof(T) * 8, typename Enable = void>
class WideType {private:…public:static const unsigned int t_TypeWidth = t_Width * t_DataWidth;typedef ap_uint<t_TypeWidth> t_TypeInt;

可以看到,t_TypeInt只是一个别名,代指ap_uint<t_TypeWidth>;

绕了半天,发现p_x,p_res就是ap_uint<m>的hls::stream!

3.4 双重循环

for (t_IndexType i = 0; i < l_parEntries; ++i) {
#pragma HLS PIPELINEWideType<t_DataType, t_ParEntries> l_valX;WideType<t_DataType, t_ParEntries> l_valY;l_valX = p_x.read();for (unsigned int j = 0; j < t_ParEntries; ++j) {l_valY[j] = p_alpha * l_valX[j];}p_res.write(l_valY);
}

这段代码是实现向量缩放操作(即 Y = alpha * X)的核心部分。

内层循环对于硬件实现来说非常关键,因为它被设计为可以完全展开并并行执行。

当外层循环使用了 #pragma HLS PIPELINE 指令时,即使没有显式地使用 #pragma HLS UNROLL 指令,内层循环也可能会默认展开。

l_valX、l_valY变量是Vitis HLS推荐使用的方法。

l_valX = p_x.read()和p_res.write(l_valY)也是hls::stream操作fifo的方法。

4. 总结

虽然Vitis Libraries中的函数在一开始看起来可能令人困惑,但它们提供了强大的工具集,用于构建高效的硬件加速应用程序。通过深入学习和实践,我们可以逐渐解锁这些库的潜力,为自己的项目带来前所未有的性能提升。

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

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

相关文章

【Leetcode】代码随想录Day16|二叉树3.0

文章目录 104 二叉树的最大深度559 n叉树的最大深度111 二叉树的最小深度222 完全二叉树的节点个数 104 二叉树的最大深度 递归法&#xff1a;无论是哪一种顺序&#xff0c;标记最大深度 class Solution(object):def depthHelper(self, root, depth):if root:depth 1left_de…

HWOD:合并整型数组

一、知识点 合并整型数组目前有两种方法 合并数组并不一定需要真正的合并 1、下意识的方法 对两个整型数组分别排序&#xff0c;然后合并 2、不排序的方法 遍历两个数组&#xff0c;找出最小值&#xff0c;输出最小值。将两个数组中与最小值相等的位置置为超大值 重复以…

VBA_MF系列技术资料1-510

MF系列VBA技术资料1-510 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-0…

go限流、计数器固定窗口算法/计数器滑动窗口算法

go限流、计数器固定窗口算法/计数器滑动窗口算法 一、问题 问题1&#xff1a;后端接口只能支撑每10秒1w个请求&#xff0c;要怎么来保护它呢&#xff1f; 问题2&#xff1a;发短信的接口&#xff0c;不超过100次/时&#xff0c;1000次/24小时&#xff0c;要怎么实现&#xff…

豆瓣影评信息爬取 (爬虫)

代码块&#xff1a; from lxml import etree import requestsheaders{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0 }url_list[] for i in range(0,5):i*20urlsf"https:…

链表带环问题——leetcode环形链表1 2

证明链表带环 链表的带环问题指的是本该指向NULL的最后一个节点指向了之前的节点&#xff0c;导致链表成环&#xff0c;找不到尾结点的情况&#xff0c;那么我们该如何证明链表带环呢&#xff1f; 我们可以类比物理中的追及问题&#xff0c;让快慢指针同时走&#xff0c;两者相…

企微知识库是如何搭建的?这篇文章来解答

知识库在企业中发挥着至关重要的作用&#xff0c;它不仅能够存储和整理重要的工作资料&#xff0c;还能提高员工的工作效率&#xff0c;加强团队之间的协作。对于使用微信企业版&#xff08;企业微信&#xff09;的企业来说&#xff0c;搭建一个专门的知识库是极有必要的。本文…

ceph osd分组

一、前言 使用分组可以更好的管理osd&#xff0c;将不同类型的磁盘&#xff0c;分到不同的组中&#xff0c;例如hhd类型的osd分配到hhd组&#xff0c;ssd类型的osd分配到ssd组&#xff0c;将io要求不高的分配到hhd组做存储&#xff0c;io要求高的分配到ssd组做存储 二、配置 查…

ubuntu23.10.1 php8.2安装

1、更新镜像源 apt update2、安装php apt install php php-fpm php-mysql其他扩展包&#xff0c;在后面加个-可以查看&#xff0c;选择安装,我这里是php8.2版本 apt-get install php8.2- 2.1php与nginx结合 PHP-FPM的配置文件位于/etc/php/{PHP版本}/fpm/pool.d/www.conf;…

Springboot中为什么你能通过一小段代码来访问网页?

为什么你能通过一小段代码来访问网页 要明白这件事&#xff0c;首先要知道我们是如何访问网站的 访问网页的本质涉及多个技术层面&#xff0c;从用户输入网址到最终在浏览器上看到页面的过程包含了多个步骤&#xff1a; 域名解析&#xff1a;当你在浏览器中输入一个网址&…

4.19作业

1.总结二进制信号量和计数型信号量的区别&#xff0c;以及他们的使用场景。 二进制信号量&#xff1a;信号量的数值只有0和1。&#xff08;用于共享资源的访问&#xff09;&#xff0c;用于同步互斥计数型信号量&#xff1a;计数型信号量的值一般是大于或者等于2&#xff08;生…

字体反爬知识积累2

一、os模块中函数的应用 如何获取当前文件中所有文件的路径方法 这段代码使用 os.walk()函数来遍历指定目录 imgs 下的所有子目录和文件。具体来说&#xff0c;os.walk()函数返回一个生成器&#xff0c;可以在每次迭代中获取目录树中的一个元组&#xff0c;元组包含当前目录的…

MySQL--数据的增删改

目录 1.添加数据 1.1、添加全部字段的数据 1.2、添加指定字段的部分数据 1.3、同时添加多条记录 1.4、插入查询结果数据 2.修改数据 2.1、更新全部数据 2.2、更新部分数据 3.删除部分数据 3.1、删除部分数据 3.2、删除全部数据 文中[ ]里 面的内容可写可不写 1.添加数…

【Linux C | 多线程编程】线程同步 | 条件变量(万字详解)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a;2024-04-15 0…

电大搜题微信公众号:重庆开放大学学子的学习利器

在当今信息化时代&#xff0c;学习已经成为每个人不可或缺的一部分。然而&#xff0c;对于重庆开放大学的学子们来说&#xff0c;由于远程教育的特殊性&#xff0c;他们面临着更大的学习挑战。幸运的是&#xff0c;他们现在可以依靠一款强大的学习利器——电大搜题微信公众号&a…

单片机基础知识 07

一. 键盘检测 键盘分为编码键盘和非编码键盘。 编码键盘 &#xff1a;键盘上闭合键的识别由专用的硬件编码器实现&#xff0c;并产生键编码号或者键值&#xff0c;如计算机键盘。 非编码键盘&#xff1a;靠软件编程来识别。 在单片机组成的各种系统中&#xff0c;用的较多的…

wsl + ubuntu + pycups + mqtt 远程打印入门

文章目录 wsl + ubuntu + pycups + mqtt 远程打印入门1. wsl安装python2. 安装pycups3. 打印机列表4. 查看API5. 打印文件6. mqtt配置7. mqtt对接参考wsl + ubuntu + pycups + mqtt 远程打印入门 这篇讲pycups 配合mqtt 做远程打印,cups 安装要看上一篇 windows10 下 wsl + u…

Darknet框架优化介绍

一、DarkNet框架简介 1.DarkNet的简介 Darknet是一个完全使用C语言编写的人工智能框架&#xff0c;可以使用CUDA的开源框架。主要应用于图像识别领域。 它具有可移植性好&#xff0c;安装间接&#xff0c;查看源码方便等优势&#xff0c;提供了OpenCV等附加选项&#xff0c;还…

(七)Pandas时序数据 学习简要笔记 #Python #CDA学习打卡

一. 时序数据简介 1&#xff09;定义 时间序列&#xff08;time series&#xff09;&#xff0c;就是由时间构成的序列&#xff0c;它指的是在一定时间内按照时间顺序测量的某个变量的取值序列&#xff0c;比如一天内的温度会随时间而发生变化&#xff0c;或者股票的价格会随…

c语言题目之求最大公约数

题目内容&#xff1a;求最大公约数 给定两个数&#xff0c;求这两个数的最大公约数 例如&#xff1a; 输入&#xff1a;20 40 输出&#xff1a;20 什么叫最大公约数&#xff1f; 方法分析&#xff1a; 提示&#xff1a;这里我们用辗转相除法&#xff1a; 例如&#xff1a;输…