Vitis HLS中的Array Partition与Array Reshape详解

news2025/3/17 8:32:24

Vitis HLS中的Array Partition与Array Reshape详解

引言

在高层次综合(HLS)设计中,数组是最常用的数据结构之一,但默认情况下,HLS会将数组映射到单个BRAM块,这会限制并行访问能力,成为性能瓶颈。为了克服这一限制,Vitis HLS提供了两种强大的数组优化指令:ARRAY_PARTITIONARRAY_RESHAPE。这两种优化都能显著提高设计的并行度,但它们的工作原理、适用场景和资源影响各不相同。本文将深入剖析这两种优化技术的细节,帮助您在HLS设计中做出明智的选择。

Array Partition(数组分区)

基本概念

ARRAY_PARTITION指令将一个大数组分解成多个较小的数组或独立的存储单元,从而增加可用的访问端口数量,实现并行访问。当一个数组被分区后,综合工具可以为每个分区生成独立的存储结构,允许在同一时钟周期内访问多个数组元素。

在这里插入图片描述

分区类型

Vitis HLS支持三种分区类型,每种类型适用于不同的访问模式:

1. Complete Partition(完全分区)

完全分区将数组的每个元素分解为完全独立的变量,通常映射到寄存器而非BRAM。

int array[16];
#pragma HLS ARRAY_PARTITION variable=array complete dim=1

工作原理

  • 数组的每个元素都被分配到独立的存储单元
  • 允许在同一时钟周期内访问所有元素
  • 完全消除了存储结构,每个元素都可能映射到寄存器

适用场景

  • 需要在同一时钟周期内访问多个或所有数组元素
  • 数组大小较小(通常小于100个元素)
  • 实现高度并行的算法,如矩阵乘法内循环

BRAM影响

  • 通常减少或完全消除BRAM使用
  • 转而使用寄存器资源,适合小型数组
  • 对于大型数组,可能导致寄存器资源耗尽
2. Block Partition(块分区)

块分区将数组分成连续的块,每个块包含相邻的元素。

int array[100];
#pragma HLS ARRAY_PARTITION variable=array block factor=4 dim=1
// 创建4个分区:[0-24], [25-49], [50-74], [75-99]

工作原理

  • 数组被分成大小相等的连续块
  • 每个块映射到单独的存储结构
  • 同一时钟周期可以访问不同块中的元素

适用场景

  • 算法以块为单位访问数据,如图像处理中的块操作
  • 数据局部性较强的应用
  • 需要在同一时钟周期访问不同块的元素

BRAM影响

  • 通常会增加BRAM使用量,因为每个分区需要单独的BRAM块
  • 当分区因子增加时,可能导致BRAM利用率降低
  • 例如,一个1024元素的数组默认使用1个BRAM,分成4块后可能使用4个BRAM,每个只使用25%的容量
3. Cyclic Partition(循环分区)

循环分区以交替方式将元素分配到不同分区,相邻元素被分配到不同分区。

int array[100];
#pragma HLS ARRAY_PARTITION variable=array cyclic factor=4 dim=1
// 分区0: 0, 4, 8, ...
// 分区1: 1, 5, 9, ...
// 分区2: 2, 6, 10, ...
// 分区3: 3, 7, 11, ...

工作原理

  • 数组元素以循环方式分配到不同分区
  • 每隔factor个元素被分配到同一分区
  • 允许同时访问间隔固定的多个元素

适用场景

  • 需要以步长访问数组(如stride访问)
  • 循环中有规律地访问间隔元素
  • 实现向量化操作,如SIMD处理

BRAM影响

  • 与Block分区类似,通常会增加BRAM使用量
  • 可能导致BRAM利用率降低
  • 适合特定的访问模式,如卷积或FFT算法

多维数组分区

对于多维数组,可以指定要分区的维度:

int matrix[10][10];
#pragma HLS ARRAY_PARTITION variable=matrix complete dim=1  // 分割行
#pragma HLS ARRAY_PARTITION variable=matrix cyclic factor=2 dim=2  // 循环分割列

也可以使用dim=0表示分割所有维度:

int cube[10][10][10];
#pragma HLS ARRAY_PARTITION variable=cube complete dim=0  // 完全分割所有维度

在这里插入图片描述

Array Reshape(数组重塑)

基本概念

ARRAY_RESHAPE 指令通过垂直重映射模式来重构阵列,用于减少所耗用的块 RAM 的数量,同时提供对数据的并行访问。
ARRAY_RESHAPE是一种结合了分区和合并的优化技术。它首先将数组分区,然后将各个分区的对应元素合并为更宽的数据类型,创建一个新的数组结构。这种方法既增加了并行访问能力,又保持了数组的原始结构。

工作原理

假设有一个8元素的数组,使用factor=4进行reshape:

  1. 首先将数组分成4个分区(类似于partition)
  2. 然后将每个分区的对应元素合并为一个更宽的数据类型
  3. 结果是一个新数组,长度是原来的1/4,但每个元素是原来宽度的4倍
原始数组: [a0, a1, a2, a3, a4, a5, a6, a7]

使用factor=4的cyclic reshape:
结果数组: [{a0,a1,a2,a3}, {a4,a5,a6,a7}]

使用示例

与Array Partition类似,Array Reshape也支持complete、block和cyclic三种类型:

void foo (...) {
int  array1[N];
int  array2[N];
int  array3[N];
#pragma HLS ARRAY_RESHAPE variable=array1 type=block factor=2 dim=1
#pragma HLS ARRAY_RESHAPE variable=array2 type=cycle factor=2 dim=1
#pragma HLS ARRAY_RESHAPE variable=array3 type=complete dim=1
...   
}

在这里插入图片描述

BRAM消耗影响

ARRAY_RESHAPE对BRAM消耗的影响与ARRAY_PARTITION不同:

  1. 总BRAM数量

    • 通常不会显著增加BRAM数量
    • 倾向于保持相似的总体BRAM使用量
  2. BRAM配置

    • 改变BRAM的配置,使用更宽但更短的存储结构
    • 例如,可能从32位x1024转变为128位x256
  3. BRAM利用率

    • 通常比等效的ARRAY_PARTITION有更高的BRAM利用率
    • 减少了由于最小BRAM大小限制导致的浪费

Array Partition与Array Reshape的比较

相同点

  • 目标相同:两者都旨在通过优化数组访问模式来提高并行度
  • 提升性能:通过增加并行访问能力,改善设计的吞吐量和延迟

不同点

  • 实现方式

    • Array Partition:通过分割数组本身来实现并行访问
    • Array Reshape:通过改变数组的存储结构来实现并行访问
  • 存储结构

    • Array Partition:创建多个独立的小数组或寄存器
    • Array Reshape:创建一个结构上更宽但更短的数组
  • 访问方式

    • Array Partition:需要使用不同的索引访问不同分区
    • Array Reshape:使用相同的索引访问,但需要额外的位选择逻辑
  • 资源影响

    • Array Partition:可能增加总体BRAM使用,或将BRAM转换为寄存器
    • Array Reshape:通常保持相似的BRAM数量,但增加数据宽度
  • 适用场景

    • Array Partition:更适合需要直接并行访问多个元素的情况
    • Array Reshape:适合需要在多维空间中调整访问模式的情况

实际应用案例

案例1:矩阵乘法优化

矩阵乘法是一个经典的需要高度并行访问的算法:

void matrix_multiply(int A[N][N], int B[N][N], int C[N][N]) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            int sum = 0;
            for (int k = 0; k < N; k++) {
                #pragma HLS PIPELINE II=1
                sum += A[i][k] * B[k][j];
            }
            C[i][j] = sum;
        }
    }
}

优化策略

  • 对矩阵B进行complete分区,因为内循环需要随机访问B的行
#pragma HLS ARRAY_PARTITION variable=B complete dim=1
  • 对矩阵A进行cyclic分区,因为内循环顺序访问A的列
#pragma HLS ARRAY_PARTITION variable=A cyclic factor=16 dim=2

案例2:图像处理滤波器

考虑一个3x3卷积滤波器,需要同时访问9个像素:

void filter(pixel_t image[HEIGHT][WIDTH], pixel_t result[HEIGHT-2][WIDTH-2]) {
    pixel_t window[3][3];
    
    for (int i = 1; i < HEIGHT-1; i++) {
        for (int j = 1; j < WIDTH-1; j++) {
            #pragma HLS PIPELINE II=1
            
            // 加载3x3窗口
            for (int di = -1; di <= 1; di++) {
                for (int dj = -1; dj <= 1; dj++) {
                    window[di+1][dj+1] = image[i+di][j+dj];
                }
            }
            
            // 应用滤波器
            result[i-1][j-1] = apply_filter(window);
        }
    }
}

优化策略

  • 对窗口数组进行complete分区,因为需要同时访问所有元素
#pragma HLS ARRAY_PARTITION variable=window complete dim=0
  • 对图像数组进行cyclic分区,以支持并行访问相邻像素
#pragma HLS ARRAY_PARTITION variable=image cyclic factor=3 dim=2

案例3:FFT算法

FFT算法需要特定模式的数据访问:

void fft(complex_t data[N]) {
    // FFT实现
    for (int stage = 0; stage < log2(N); stage++) {
        int distance = 1 << stage;
        for (int i = 0; i < N; i += 2*distance) {
            for (int j = 0; j < distance; j++) {
                #pragma HLS PIPELINE II=1
                butterfly(data[i+j], data[i+j+distance]);
            }
        }
    }
}

优化策略

  • 使用reshape而非partition,因为FFT的访问模式适合更宽的数据类型
#pragma HLS ARRAY_RESHAPE variable=data cyclic factor=8 dim=1

最佳实践与选择指南

何时选择Array Partition

  1. 随机访问需求:当算法需要在同一时钟周期随机访问多个数组元素时
  2. 小型数组:对于小型数组(通常<100元素),complete分区效果好
  3. 高度并行算法:需要最大化并行性的算法,如矩阵运算
  4. 特定访问模式
    • 块访问模式 → block分区
    • 步长访问模式 → cyclic分区

何时选择Array Reshape

  1. 顺序访问模式:当算法主要以顺序方式访问数组元素时
  2. BRAM资源受限:当需要提高并行性但BRAM资源有限时
  3. 中大型数组:对于较大的数组,reshape通常比partition更节省资源
  4. 数据局部性强:当算法在特定时间只访问数组的一小部分

三种实现二维矩阵的方式。左边采用原始的方式,保存N*M个元素。中间数组使用了array_partition
directive进行了变形,结果是使用了M个存储单元,每个保存N个元素。右边的,使用array_shape
directive进行了变形,结果保存在一个存储单元,带有N个入口,每个入口保存原始矩阵的M个元素

三种实现二维矩阵的方式。左边采用原始的方式,保存N*M个元素。中间数组使用了array_partition directive进行了变形,结果是使用了M个存储单元,每个保存N个元素。右边的,使用array_shape directive进行了变形,结果保存在一个存储单元,带有N个入口,每个入口保存原始矩阵的M个元素

举例

Xilinx Virtex Ultrascale+器件最小的block RAM(BRAM)是18 Kbits,可以支持不同深度和宽度的组合。当数组分块小于18kbits后,那么BRAM 就没有被充分使用。如果我们使用最原始的矩阵,4-bit数组,维度是 [1024][4] ,这个数组就可放到一个单独的BRAM 中,它配置为4Kbit x 4。对这个数组的第二个维度进行分块,那么将使用4个 1Kbit x 4的存储单元,每个都要比BRAM小很多。通过使用array_reshape 将数组变为1Kbit x 16,可以被一个BRAM 存储。

总结

ARRAY_PARTITIONARRAY_RESHAPE都是Vitis HLS中强大的数组优化工具,能够显著提高设计的并行度和性能。选择哪种优化方式取决于具体的应用场景、访问模式和资源限制:

  1. Array Partition

    • 将数组分解为多个独立的小数组或单个元素
    • 提供最大的并行访问能力
    • 可能增加总体BRAM使用量或将BRAM转换为寄存器
    • 提供三种分区类型(complete, block, cyclic),适用于不同的访问模式
  2. Array Reshape

    • 重组数组结构,创建更宽但更短的数组
    • 在保持类似BRAM数量的同时提高并行性
    • 通常有更好的BRAM利用率
    • 适合顺序访问模式和资源受限的设计

经验之谈:

array_partition指令更加灵活,但可能会导致存储资源使用不充分。
array_reshape指令更加节约资源,并且在时序较差的情况下有奇效。
大数组reshape直接干,小数组/高度优化 仔细使用partition。
计算好BRAM利用率,片上的cache非常宝贵。

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

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

相关文章

Centos离线安装openssl

文章目录 Centos离线安装openssl1. openssl是什么&#xff1f;2. openssl下载地址3. openssl-devel安装4. 安装结果验证5. 版本查看 Centos离线安装openssl 1. openssl是什么&#xff1f; OpenSSL 是一个开源的、跨平台的 加密工具库 和 命令行工具集&#xff0c;广泛用于实现…

protobuf安装

安装 github官方链接 https://github.com/protocolbuffers/protobuf/ 以protobuf21为例 https://github.com/protocolbuffers/protobuf/releases/download/v21.11/protobuf-all-21.11.zip windows 解压好文件夹后,使用cmake,vs,qt creator等工具打开该项目,进行编译,编译需…

《基于超高频RFID的图书馆管理系统的设计与实现》开题报告

一、研究背景与意义 1.研究背景 随着信息化时代的到来&#xff0c;运用计算机科学技术实现图书馆的管理工作已成为优势。更加科学地管理图书馆会大大提高工作效率。我国的图书管理体系发展经历了三个阶段&#xff1a;传统图书管理模式、现代图书管理模式以及基于无线射频识别&…

小程序渲染之谜:如何解决“加载中...”不消失的 Bug(glass-easel)

&#x1f389; 小程序渲染之谜&#xff1a;如何解决“加载中…”不消失的 Bug &#x1f389; 引言 在小程序开发中&#xff0c;渲染问题总能让人抓狂。&#x1f62b; 这次&#xff0c;我遇到了一个奇怪的 bug&#xff1a;产品详情页的内容已经正常显示&#xff0c;但页面却一…

网络原理之HTTPS(如果想知道网络原理中有关HTTPS的知识,那么只看这一篇就足够了!)

前言&#xff1a;随着互联网安全问题日益严重&#xff0c;HTTPS已成为保障数据传输安全的标准协议&#xff0c;通过加密技术和身份验证&#xff0c;HTTPS有效防止数据窃取、篡改和中间人攻击&#xff0c;确保通信双方的安全和信任。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要…

五子棋小游戏-简单开发版

一、需求分析 开发一个基于 Pygame 库的五子棋小游戏&#xff0c;允许两名玩家在棋盘上轮流落子&#xff0c;当有一方达成五子连珠时游戏结束&#xff0c;显示获胜信息&#xff0c;并提供退出游戏和重新开始游戏的操作选项。 1.棋盘显示 &#xff1a; 显示一个 15x15 的五子棋…

2025中国科技大学少年班/创新试点班·初试备考测试卷(数学)

本卷考查内容&#xff1a;高中课程内容及拓展。 本卷考查形式&#xff1a;书面作答&#xff08;客观题18小题解答题4题&#xff09;。 卷首语&#xff1a;中科大少年班、创新班每年大规模招录在数理成绩优异的中学学生。其中初试数学题在高考基础上略有拓展&#xff0c;难度又低…

即时通讯平台测试报告

1.项目概述 项目名称&#xff1a;即时通讯平台 版本号&#xff1a;V1.0.0 测试周期&#xff1a;2025年2月25日--2025年3月15日 测试目标&#xff1a;验证核心功能&#xff08;登录、注册、消息收发、用户管理、群组功能等&#xff09;的稳定性和性能指标。 2. 测试范围 功…

如何记录Matlab程序运行过程中所占用的最大内存

有些时候&#xff0c;我们需要分析Matlab程序运行过程中所占用的最大内存。如果只是得到程序运行到当前位置所占用的内存&#xff0c;可以简单在程序当前位置插入memory命令即可&#xff1a; user memory; MemUsed_now user.MemUsedMATLAB; 但如果我们想要的是整个程序在运行…

WIN11开发环境变量记录

这里写自定义目录标题 总图JAVA环境变量配置GIT环境变量配置NODEJS环境变量配置 总图 JAVA环境变量配置 新建系统变量。变量名&#xff1a;JAVA_HOME&#xff0c;变量值&#xff08;可以选择浏览目录&#xff0c;JAVA的根目录&#xff0c;本处为D:\Java\jdk1.8.0_251&#xff…

易语言模拟真人鼠标轨迹算法

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

洛谷P9950 [USACO20FEB] Mad Scientist B

P9950 [USACO20FEB] Mad Scientist B - 洛谷 代码区&#xff1a; #include <iostream> #include <string>using namespace std; int main() {int n;cin>> n;string a;string b;cin >> a >> b;int flag,step0,i,t;for ( i 0; i < a.length(…

prometheus自定义监控(pushgateway和blackbox)和远端存储VictoriaMetrics

1 pushgateway采集 1.1 自定义采集键值 如果自定义采集需求时&#xff0c;就可以通过写脚本 定时任务定期发送数据到 pushgateway 达到自定义监控 1.部署 pushgateway&#xff0c;以 10.0.0.42 节点为例 1.下载组件 wget https://github.com/prometheus/pushgateway/relea…

C++相关基础概念之入门讲解(上)

1. 命名空间 C中的命名空间&#xff08;namespace&#xff09;是用来避免命名冲突问题的一种机制。通过将类、函数、变量等封装在命名空间中&#xff0c;可以避免不同部分的代码中出现相同名称的冲突。在C中&#xff0c;可以使用namespace关键字来定义命名空间。 然后我们在调…

【大模型】Transformer、GPT1、GPT2、GPT3、BERT 的论文解析

前言 在自然语言处理&#xff08;NLP&#xff09;和深度学习的快速发展中&#xff0c;Transformer模型和 GPT系列模型扮演了至关重要的角色。本篇博客旨在对这些开创性的论文进行介绍&#xff0c;涵盖它们的提出时间、网络结构等关键信息&#xff0c;能够快速的理解这些模型的设…

【Java 优选算法】分治-归并排序

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 数组分块如二叉树的前序遍历, 而归并排序就如二叉树的后序遍历 912. 排序数组 解法 使用归并算法 根据中间点划分区间, mid (right left ) / 2将左右区间排序合并两个有…

三格电子Modbus TCP转CANOpen网关相关问答

型号&#xff1a;SG-TCP-COE-210 Q1: Modbus TCP转CANOpen网关的主要功能是什么&#xff1f; A1: 该网关的核心功能是实现 Modbus TCP协议与CANOpen协议之间的双向数据转换&#xff0c;使支持Modbus TCP的工业设备&#xff08;如PLC、HMI&#xff09;能够与基于CANOpen协议的设…

Flutter FloatingActionButton 从核心用法到高级定制

目录 1. 引言 2. FloatingActionButton 的基本用法 3. 主要属性 4. 进阶定制技巧 4.1 扩展型 FAB 4.2 动态变形动画 4.3 多个 FAB 协同 5. 主题与动效集成 5.1 全局主题配置 5.2 平台适配方案 5.3 高级动画控制器 6. 最佳实践 6.1 布局规范 6.2 性能优化 6.3 无…

【恒流源cc与恒压源cv典型电路解析】

在电子电路设计中&#xff0c;恒流源和恒压源是两种至关重要的电源类型&#xff0c;它们分别能为负载提供稳定的电流和电压。以下将详细解析这两种电源的典型电路。 ## 一、恒压源 ### &#xff08;一&#xff09;采用线性稳压器的恒压源电路 1. **电路组成** - 以常见的 78…

Anaconda conda常用命令:从入门到精通

1 创建虚拟环境 conda create -n env_name python3.8 2 创建虚拟环境的同时安装必要的包 conda create -n env_name numpy matplotlib python3.8 3 查看有哪些虚拟环境 以下三条命令都可以。注意最后一个是”--”&#xff0c;而不是“-”. conda env list conda info -e c…