HLS笔记——任意精度

参考博客:
https://blog.csdn.net/weixin_36520607/article/details/53152718
https://blog.csdn.net/zhangningning1996/article/details/107383183
https://blog.csdn.net/christne1225i/article/details/53353801

资源浪费

设计硬件时,往往是要求更精确的位宽。例如,一个filter的输入是12位和一个累加器的结果只需要一个最大范围为27位。然而对于硬件设计来说,使用标准的C数据类型会造成硬件成本的浪费。这就会造成我们要使用更多的LUT和寄存器,延迟甚至可能超过时钟周期和需要更多的周期来计算结果。这往往不是我们需要的结果。因此下面我将介绍如何利用Vivado HLS处理许多位准确或任意精度数据类型,以及允许使用任何(任意)宽度的模型变量。

例如,采用C语言去描述一个18*18 bits的乘法器,那么就需要将输入数据都声明为32 bits(int),结果声明为64 bits(long long),这将会在FPGA中消耗4个DSP48E1(DSP48E1乘法器是25x18 Multiplier),显然这是很浪费资源的。
在这里插入图片描述

Vivado HLS ap_fixed数据类型

任意精度定点数定点数
C++ Arbitrary Precision Fixed Point Types的缩写就是ap_fixed。编译这个类型,要加上**#include <ap_fixed.h>**头文件
在这里插入图片描述

定义如下

ap_[u]fixed<int W,
int I,
ap_q_mode Q,
ap_o_mode O,
ap_sat_bits N>;
W:宽度,数据占用的位宽,

I:整数部分的位数,那么(W-I)就是小数部分fraction占用的宽度了

Q:量化模式
AP_RNDAP_RND——指示该值应舍入到最接近ap_ [u]定点类型的可表示值;
AP_RND_ZERO ——向零取整;
AP_RND_MIN_INF——向负无穷取整;
AP_RND_INF ——向正无穷取整。

O:溢出模式
Saturation AP_SAT ——取到剩余位数能表示的最大的值

p_ufixed<4, 4, AP_RND, AP_SAT> UAPFixed4 = 19.0; // Yields: 15.0 4位无符号最大能取到15
ap_fixed<4, 4, AP_RND, AP_SAT> UAPFixed4 = 19.0; // Yields: 7.0 4位有符号数最大能取到7
ap_ufixed<4, 4, AP_RND, AP_SAT> UAPFixed4 = -19.0; // Yields: 0.0   4位无符号最大能取到0
ap_fixed<4, 4, AP_RND, AP_SAT> UAPFixed4 = -19.0; // Yields: -8.0 4位有符号极限能取到-8

AP_SAT_ZERO

ap_ufixed<4, 4, AP_RND, AP_SAT_ZERO> UAPFixed4 = 19.0; // Yields: 0.0
ap_fixed<4, 4, AP_RND, AP_SAT_ZERO> UAPFixed4 = 19.0; // Yields: 0.0
ap_ufixed<4, 4, AP_RND, AP_SAT_ZERO> UAPFixed4 = -19.0; // Yields: 0.0
ap_fixed<4, 4, AP_RND, AP_SAT_ZERO> UAPFixed4 = -19.0; // Yields: 0.0

AP_WRAP

ap_ufixed<4, 4, AP_RND, AP_WRAP> UAPFixed4 = 19.0; // Yields: 3.0 10011取低4位就是3
ap_fixed<4, 4, AP_RND, AP_WRAP> UAPFixed4 = 31.0; // Yields: -1.0 
ap_ufixed<4, 4, AP_RND, AP_WRAP> UAPFixed4 = -19.0; // Yields: 13.0
ap_fixed<4, 4, AP_RND, AP_WRAP> UAPFixed4 = -19.0; // Yields: -3.0
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
void conv1x1(ap_uint<8> bottom[16][34][66], ap_uint<8> top[16][34][66], ap_int<8> weight[16][16],ap_int<16> bias[16], ap_fixed<32,1> factor) { ap_int<32> mid_result = 0; for (int h = 0; h < 32; h++) { for (int w = 0; w < 64; w++) { for (int coo = 0; coo < 16; coo++) { //output channel mid_result = compute_engine_16( weight[coo][0], bottom[0][h][w], weight[coo][1], bottom[1][h][w], weight[coo][2], bottom[2][h][w], weight[coo][3], bottom[3][h][w], weight[coo][4], bottom[4][h][w], weight[coo][5], bottom[5][h][w], weight[coo][6], bottom[6][h][w], weight[coo][7], bottom[7][h][w], weight[coo][8], bottom[8][h][w], weight[coo][9], bottom[9][h][w], weight[coo][10], bottom[10][h][w], weight[coo][11], bottom[11][h][w], weight[coo][12], bottom[12][h][w], weight[coo][13], bottom[13][h][w], weight[coo][14], bottom[14][h][w], weight[coo][15], bottom[15][h][w] ); top[coo][h][w] = relu( bias[coo] + qunat_dequant2(mid_result, factor)); } } } } void DW_CONV_3x3(ap_uint<8> bottom[16][34][66], ap_uint<8> top[16][34][66], ap_int<8> weight[16][3][3],ap_int<16> bias[16], ap_fixed<32,1> factor) { ap_int<32> mid_result = 0; for (int co = 0; co < 16; co++) { for (int h = 1; h <= 32; h++) { for (int w = 1; w <= 64; w++) { mid_result = (weight[co][0][0] * bottom[co][h - 1][w - 1]) + (weight[co][0][1] * bottom[co][h - 1][w]) + (weight[co][0][2] * bottom[co][h - 1][w + 1]) + (weight[co][1][0] * bottom[co][h][w - 1]) + (weight[co][1][1] * bottom[co][h][w]) + (weight[co][1][2] * bottom[co][h][w + 1]) + (weight[co][2][0] * bottom[co][h + 1][w - 1]) + (weight[co][2][1] * bottom[co][h + 1][w]) + (weight[co][2][2] * bottom[co][h + 1][w + 1]); top[co][h][w] = relu(bias[co] + qunat_dequant2(mid_result, factor)); } } } }
07-22
您的第一个问题是关于两个卷积函数的代码实现。 这两个函数分别是`conv1x1`和`DW_CONV_3x3`,它们都是用于卷积操作的。以下是对这两个函数的解释: `conv1x1`函数实现了1x1卷积操作,其中`bottom`是输入特征图(16个通道,尺寸为34x66),`top`是输出特征图(16个通道,尺寸为34x66)。`weight`是1x1卷积核权重矩阵(16个通道),`bias`是偏置矩阵(16个通道),`factor`是缩放因子。函数中使用了一个名为`compute_engine_16`的函数来计算卷积结果,并通过ReLU激活函数对结果进行处理。 `DW_CONV_3x3`函数实现了3x3深度可分离卷积操作,其中`bottom`是输入特征图(16个通道,尺寸为34x66),`top`是输出特征图(16个通道,尺寸为34x66)。`weight`是3x3卷积核权重矩阵(16个通道,每个通道有3x3个权重),`bias`是偏置矩阵(16个通道),`factor`是缩放因子。函数中使用了一个名为`qunat_dequant2`的函数来进行量化和反量化操作,以及一个名为`relu`的函数来进行ReLU激活。具体的计算过程是对每个通道、每个位置的像素进行3x3卷积操作,然后通过ReLU激活函数对结果进行处理。 这两个函数分别用于不同的卷积操作,`conv1x1`用于1x1卷积,而`DW_CONV_3x3`用于3x3深度可分离卷积。这些函数的实现是基于C++语言,并使用了一些数据类型和函数,例如`ap_uint`、`ap_int`和`ap_fixed`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值