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;…

字体反爬知识积累2

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

【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;用的较多的…

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;输…

腾讯云APP备案指南:一站式完成备案手续,助您顺利上线

工信部最新通知要求所有互联网信息服务提供者完成移动互联网应用程序备案手续。腾讯云为开发者提供了简单易行的备案流程&#xff0c;本文详细解答如何在腾讯云平台完成备案&#xff0c;帮助开发者快速上线自己的APP。从验证备案域名到腾讯云审核&#xff0c;一步步指导您完成备…

vue 一键更换主题颜色

这里提供简单的实现步骤&#xff0c;具体看自己怎么加到项目中 我展示的是vue2 vue3同理 在 App.vue 添加 入口处直接修改 #app { // 定义的全局修改颜色变量--themeColor:#008cff; } // 组件某些背景颜色需要跟着一起改变&#xff0c;其他也是同理 /deep/ .ant-btn-primar…

响应式修改 页面字体字号【大 中 小 】

浅浅记录下&#xff0c;工作中遇到的问题&#xff0c;修改页面文本字号。 <p class"change_fontSize">[ 字号 <a href"javascript:doZoom(18)">大</a><a href"javascript:doZoom(16)">中</a><a href"ja…

『FPGA通信接口』汇总目录

Welcome 大家好&#xff0c;欢迎来到瑾芳玉洁的博客&#xff01; &#x1f611;励志开源分享诗和代码&#xff0c;三餐却无汤&#xff0c;顿顿都被噎。 &#x1f62d;有幸结识那个值得被认真、被珍惜、被捧在手掌心的女孩&#xff0c;不出意外被敷衍、被唾弃、被埋在了垃圾堆。…