Vitis HLS 学习笔记--矢量数据类型

news2024/11/9 1:40:21

目录

1. 简介

2. 用法详解

2.1 存储器布局

2.2 示例展示 

2.3 综合报告

3. 总结


1. 简介

在 Vitis HLS 中,矢量数据类型是一种特殊的数据类型,它允许你一次处理多个数据元素,就像一排并排的盒子,每个盒子里都装着一个数据元素。这种方式非常适合于同时执行多个相同的操作,这就是所谓的 SIMD(单指令多数据)操作。

矢量数据类型用法

#include <hls_vector.h>
hls::vector<T,N> aVec;

在代码中,#include <hls_vector.h> 这行告诉程序,我们要使用 Vitis HLS 提供的矢量数据类型。hls::vector<T,N> aVec; 这行代码声明了一个矢量变量 aVec。这里的 T 表示数据的类型,比如整数或浮点数,而 N 表示这个矢量中有多少个元素。

当 T 的位宽(即每个数据元素占用的位数)和 N(矢量中元素的数量)都是 2 的幂(比如 2, 4, 8, 16…)时,这个矢量数据类型就能以最高效的方式运行,因为计算机处理这样的数字时更加高效。

打个简单的比方,就像你在超市买东西时,如果你有一个足够大的购物车,你可以一次性把所有东西放进去,然后一起结账,这样就比每次只买一个东西要快得多。在 Vitis HLS 中,矢量数据类型就像是一个大购物车,让你能够一次性处理很多数据,提高效率。

2. 用法详解

2.1 存储器布局

hls::vector<T,N> aVec;

这个数据结构被定义为 hls::vector<T,N>,其中 T 表示矢量中元素的类型,而 N 表示矢量中元素的数量。

存储器连续性:矢量中的元素在内存中是连续存储的。这意味着,如果你知道了矢量中第一个元素的内存地址,就可以通过这个地址和元素的索引(乘以元素的大小)来计算出任何一个元素的内存地址。

存储大小:矢量的总大小(以字节为单位)是元素类型大小 sizeof(T) 与元素数量 N 的乘积。这是因为所有元素都紧密地排列在一起,没有任何间隙。

对齐要求:矢量的对齐要求是其总大小的最大2的幂值。对齐是指数据的起始内存地址是某个数(通常是2的幂)的倍数。这有助于提高内存访问的效率。特别地,当 N 和 sizeof(T) 都是2的幂时,矢量应该对齐到其总大小。这意味着如果你有一个类型大小为4字节(2的2次幂),包含8个元素(2的3次幂)的矢量,那么这个矢量的总大小是32字节(2的5次幂),它应该对齐到32字节。

这种设计与许多计算机架构上的矢量实现相匹配,因为它们通常也有类似的连续存储和对齐要求。这样的设计可以使得数据结构在这些架构上运行得更有效率。

2.2 示例展示 

#include "hls_vector.h"
#include <ap_int.h>

// Each vector will be 64 bytes (16 x 4 bytes)
typedef hls::vector<float, 16> float16;

template <int N, typename T> void load(T (&out)[N], const T* in) {
#pragma HLS INLINE off
    for (int i = 0; i < N; ++i) {
#pragma HLS pipeline
        out[i] = in[i];
    }
}

template <int N, typename T> void store(T* out, const T (&in)[N]) {
#pragma HLS INLINE off
    for (int i = 0; i < N; ++i) {
#pragma HLS pipeline
        out[i] = in[i];
    }
}

template <int N, typename T, typename S>
void compute(T (&res)[N], const S (&lhs)[N], const S (&rhs)[N]) {
#pragma HLS INLINE off
    for (int i = 0; i < N; ++i) {
#pragma HLS pipeline
        res[i] = lhs[i] + rhs[i];
    }
}

extern "C" void example(float16* res, const float16* lhs, const float16* rhs,
                        int n) {
#pragma HLS INTERFACE m_axi port = lhs offset = slave bundle = gmem0 depth = 32
#pragma HLS INTERFACE m_axi port = rhs offset = slave bundle = gmem1 depth = 32
#pragma HLS INTERFACE m_axi port = res offset = slave bundle = gmem0 depth = 32

    for (int i = 0; i < n; ++i) {
        float16 lhs_buf[32];
        float16 rhs_buf[32];
        float16 res_buf[32];

#pragma HLS DATAFLOW
        load(lhs_buf, lhs);
        load(rhs_buf, rhs);
        compute(res_buf, lhs_buf, rhs_buf);
        store(res, res_buf);
    }
}

这段代码中,定义了一种特定的向量类型 float16(由16个浮点数组成,总共64字节),并实现了几个基本操作:从内存加载数据 (load)、将数据存储回内存 (store) 以及执行向量之间的加法 (compute)。

类型定义

  • float16:定义了一个包含16个float元素的向量,每个float占用4字节,因此整个float16占用64字节内存。

函数模板

  • load:从指定的输入指针位置(in)加载N个元素到数组(out)中。这个函数通过循环实现,并使用#pragma HLS pipeline来指示HLS工具将循环的每次迭代实现为一个流水线步骤,以提高执行速度。
  • store:将数组(in)中的N个元素存储到指定的输出指针位置(out)。同样使用#pragma HLS pipeline来优化性能。
  • compute:对两个输入数组(lhs和rhs)进行逐元素加法,将结果存储在数组(res)中。再次使用#pragma HLS pipeline实现流水线加速。

主函数 example

  • 功能:这个函数执行一系列操作,对于给定数量n的float16类型向量(lhs和rhs),它逐个处理这些向量,执行加法运算,并将结果存储在res数组中。
  • 接口指令:#pragma HLS INTERFACE指令定义了函数参数与外部世界的接口方式,这里使用m_axi接口,它是一种适用于内存访问的通用接口。offset = slave指定这些接口作为从设备端口,bundle参数定义了不同的接口被分配到的AXI总线接口,depth参数指定了接口期望的数据深度。
  • 内部缓冲区:函数内部定义了三个float16类型的数组作为缓冲区(lhs_buf、rhs_buf、res_buf),用于存储加载的数据、临时计算结果和最终结果。
  • 数据流:通过#pragma HLS DATAFLOW指令,函数内部的操作被组织成一个数据流图,允许这些操作并行执行,从而提高整体性能。

2.3 综合报告

================================================================
== SW I/O Information
================================================================
* Top Function Arguments
+----------+-----------+---------------------------+
| Argument | Direction | Datatype                  |
+----------+-----------+---------------------------+
| res      | inout     | vector<float, 16>*        |
| lhs      | inout     | vector<float, 16> const * |
| rhs      | in        | vector<float, 16> const * |
| n        | in        | int                       |
+----------+-----------+---------------------------+

 通过 Top Function Arguments 报告,可以查看矢量数据类型的具体信息。

================================================================
== HW Interfaces
================================================================
* M_AXI
+-------------+------------+---------------+---------+--------+----------+-----------+--------------+--------------+-------------+-------------+
| Interface   | Data Width | Address Width | Latency | Offset | Register | Max Widen | Max Read     | Max Write    | Num Read    | Num Write   |
|             | (SW->HW)   |               |         |        |          | Bitwidth  | Burst Length | Burst Length | Outstanding | Outstanding |
+-------------+------------+---------------+---------+--------+----------+-----------+--------------+--------------+-------------+-------------+
| m_axi_gmem0 | 512 -> 512 | 64            | 64      | slave  | 0        | 512       | 16           | 16           | 16          | 16          |
| m_axi_gmem1 | 512 -> 512 | 64            | 64      | slave  | 0        | 512       | 16           | 16           | 16          | 16          |
+-------------+------------+---------------+---------+--------+----------+-----------+--------------+--------------+-------------+-------------+

向量类型 float16(由16个浮点数组成,总共64字节),64*8=512,符合综合报告。

3. 总结

在 Vitis HLS 中,矢量数据类型提供了一种高效的数据处理方式,允许开发者利用 SIMD 操作一次性处理多个数据元素。通过使用 hls::vector<T,N>,开发者可以创建一个由 N 个类型为 T 的元素组成的矢量。这种数据结构在内存中连续存储,且当元素类型和数量都是 2 的幂时,对齐到其总大小,可以实现最优的内存访问效率。

示例代码展示了如何定义矢量类型 float16,以及如何实现加载、存储和计算操作。这些操作通过 HLS 指令优化,以流水线的形式执行,从而提高性能。主函数 example 则展示了如何将这些操作组织成数据流,以并行方式执行,进一步提升效率。

综合报告部分突出了矢量数据类型在硬件接口中的配置,如 M_AXI 接口的数据宽度和地址宽度,确保了与向量类型的内存布局相匹配。这种设计使得 Vitis HLS 中的矢量数据类型不仅在软件层面上高效,也在硬件层面上与现代计算机架构紧密对接,实现了数据处理的高效率和高性能。

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

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

相关文章

大模型基础——从零实现一个Transformer(3)

大模型基础——从零实现一个Transformer(1)-CSDN博客 一、前言 之前两篇文章已经讲了Transformer的Embedding,Tokenizer,Attention,Position Encoding, 本文我们继续了解Transformer中剩下的其他组件. 二、归一化 2.1 Layer Normalization layerNorm是针对序列数据提出的一种…

基于STM32移植U8g2图形库——OLED显示(HAL库)

文章目录 一、U8g2简介1、特点2、U8g2的使用步骤 二、I2C相关介绍1、I2C的基本原理2、I2C的时序协议 三、OLED屏的工作原理四、汉字点阵显示原理五、建立STM32CubeMX工程六、U8g2移植1、U8g2源码2、移植过程 七、代码编写1、参考博主实现的U82G的demo例程&#xff08;1&#xf…

VMware Workerstation开启虚拟机后,产生乱码名称日志文件

问题情况 如下图所示&#xff0c;我的虚拟机版本是16.1.2版本&#xff0c;每次在启动虚拟机之后&#xff0c;D盘目录下都会产生一个如图下所示的乱码名称文件。同时&#xff0c;虚拟机文件目录也是杂乱不堪&#xff0c;没有按照一台虚拟机对应一个文件夹的形式存在。 问题处理…

笔记 | 软件工程06-1:软件设计-软件设计基础

1 软件设计概述 1.1 为什么要软件设计 1.2 何为软件设计 何为软件系统的解决方案&#xff1f; 软件设计关注与软件需求的实现问题软件设计是需求分析和软件实现间的桥梁 1.3 软件设计的质量要求 1.4 软件设计的过程 1.4.1 软件体系结构设计 1.4.2 用户界面设计 1.4.3 软件详细…

最短路径Dijkstra算法详解

目录 最短距离问题 最短路径问题 进阶--标尺增多 升级方法 例题应用 最短距离问题 Dijkstra算法的策略&#xff1a; 设置集合S存放已被访问的顶点&#xff0c;然后执行n次下面的两个步骤&#xff08;n为顶点个数&#xff09;&#xff1a; &#xff08;1&#xff09;每次…

go-zero整合Excelize并实现Excel导入导出

go-zero整合Excelize并实现Excel导入导出 本教程基于go-zero微服务入门教程&#xff0c;项目工程结构同上一个教程。 本教程主要实现go-zero框架整合Excelize&#xff0c;并暴露接口实现Excel模板下载、Excel导入、Excel导出。 go-zero微服务入门教程&#xff1a;https://blo…

科技云报道:“元年”之后,生成式AI将走向何方?

科技云报道原创。 近两年&#xff0c;以大模型为代表的生成式AI技术&#xff0c;成为引爆数字原生最重要的技术奇点&#xff0c;人们见证了各类文生应用的进展速度。Gartner预测&#xff0c;到2026年&#xff0c;超过80%的企业将使用生成式AI的API或模型&#xff0c;或在生产环…

分布式光纤测温DTS与红外热成像系统的主要区别是什么?

分布式光纤测温DTS和红外热成像系统在应用领域和工作原理上存在显著的区别&#xff0c;两者具有明显的差异性。红外热成像系统适用于表现扩散式发热、面式场景以及环境条件较好的情况下。它主要用于检测物体表面的温度&#xff0c;并且受到镜头遮挡或灰尘等因素的影响会导致失效…

论文中表格跨页了做续表的正确方法

在上方加表格 粘贴即可 文章来源于论文中表格跨页了做续表的正确方法&#xff01;论文人快来学习_哔哩哔哩_bilibili 小姐姐用WPS弄的&#xff0c;微软的不理想&#xff0c;我试了试&#xff0c;觉得在上面增加格子再粘贴表头&#xff0c;效果还行

Python | Leetcode Python题解之第145题二叉树的后序遍历

题目&#xff1a; 题解&#xff1a; class Solution:def postorderTraversal(self, root: TreeNode) -> List[int]:def addPath(node: TreeNode):count 0while node:count 1res.append(node.val)node node.righti, j len(res) - count, len(res) - 1while i < j:res…

使用fprintf函数实现写日志文件的功能(附源码)

输出打印日志是排查软件异常问题一个非常重要的手段,无论是业务上的异常,还是软件异常崩溃。一个成熟的软件产品,必然有一个功能完备的日志记录与打印系统。本文就来介绍一种简单易用的写日志文件的方法,给大家提供一个参考。 1、实现思路 主要使用C库中的fopen、fprintf和…

问题:设开环系统的频率特性为则其相频特性穿越-180°线时对应的频率为()。 #学习方法#微信

问题&#xff1a;设开环系统的频率特性为则其相频特性穿越-180线时对应的频率为&#xff08;&#xff09;。 ? A、10rad1s B、3rad/s C、lradIs D、√3rad/s 参考答案如图所示

AIGC简介

目录 1.概述 2.诞生背景 3.作用 4.优缺点 4.1.优点 4.2.缺点 5.应用场景 5.1.十个应用场景 5.2.社交媒体内容 6.如何使用 7.未来展望 8.总结 1.概述 AIGC 是“人工智能生成内容”&#xff08;Artificial Intelligence Generated Content&#xff09;的缩写&#x…

uniapp自定义tabbar——中间特殊按钮放大

在APP.vue里面 .uni-tabbar__item:nth-child(4) .uni-tabbar__icon {width: 50px !important;height: 50px !important;position: relative;bottom: 30rpx;}.uni-tabbar__item:nth-child(4) .uni-tabbar__label {position: relative;bottom: 25rpx;}

Stability AI发布AI音频模型Stable Audio Open,文本生成47秒高清音效

前言 Stability AI这家以开源图像生成模型 Stable Diffusion 而闻名的公司&#xff0c;在 6 月 6 日宣布开源其最新的 AI 音频模型 Stable Audio Open。这一新模型可以根据简单的文本提示生成最多 47 秒的高质量音频数据&#xff0c;为音乐制作和声音设计领域带来了新的可能性…

背景渐变动画登录页

b站视频演示效果: 效果图: 完整代码: <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>背景…

分布式安装安装LNMP_......

分布式安装安装LNMP LNMP是什么Nginx源码编译安装准备工作关闭安全防护配置上传源码包并解压安装编译源码依赖包创建运行用户 编译安装预配置安装选项编译源代码&&安装 配置优化优化路径添加 Nginx 系统服务 Mysql源码编译安装准备工作关闭安全防护配置卸载mariadb上传…

【云原生】创建harbor私有仓库及使用aliyun个人仓库

1.安装docker #删除已有dockersystemctl stop docker yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine #安装docker yum install -y docker-ce-20.10.1…

经济订货批量EOQ模型

一、什么是EOQ模型 EOQ是economic order quantity&#xff08;经济订货&#xff09;原理非常简单。就是把订货带来的成本&#xff0c;分为采购成本和持有成本两部分。 采购成本&#xff1a;每次订货时发生的&#xff0c;谈判、签约、物流等成本 持有成本&#xff1a;货物入仓后…

Linux kernel本地权限提升漏洞(CentOS8升级内核的解决方案)

一、CentOS8升级kernel内核的必要性 1、增强系统的安全性。 升级CentOS内核可以提供更好的安全性保障。新的内核版本通常包含了的安全补丁和漏洞修复&#xff0c;可以有效防止系统遭受恶意攻击&#xff0c;提高系统的稳定性和安全性。 2、优化硬件兼容性。 CentOS升级内核可以…