HLS 开发学习(四)离散傅里叶变换DFT------矩阵向量

傅里叶级数与傅里叶变换

这个学过信号与系统应该都挺了解的
傅里叶级数

傅里叶变换

离散傅里叶变换

DFT将一个采样函数从一个域转换到频域。
离散信号和周期信号最重要的关联在于它可以用一组有限的数字表示。因此,可以使用数字系统来实现DFT。

X ( k ) = ∑ n = 0 N − 1 x ( n ) e − j 2 π k n / N X(k) = \sum\limits_{n=0}^{N-1}x(n)e^{-j2\pi kn/N} X(k)=n=0N1x(n)ej2πkn/N

复正弦求和
这个求和的结果恰好落在实值轴上或虚轴上。

离散信号

如果有一个N点的时域信号
在这里插入图片描述
在使用DFT进行分析的时候,会得出各个品类的正弦及余弦幅度,其中余弦幅度可以看作是复数的实数部分,而正弦幅度可以看作是复数的虚数部分。
在复频域中,有N/2+1个正弦和N/2+1个余弦。

(频域样本数量为N/2+1是因为时域信号是纯实数的,复数时域信号经过DFT后有N个样本的频域信号)

具有N点的DFT可以通过NxN矩阵成一个大小为N的矢量来缺点

S = [ 1 1 1 . . . 1 1 s s 2 . . . s N − 1 1 s 2 s 4 . . . s 2 ( N − 1 ) 1 s 3 s 6 . . . s 3 ( N − 1 ) . . . . . . . . . . . . . . . 1 s N − 1 s 2 ( N − 1 ) . . . s ( N − 1 ) ( N − 1 ) ] S =\begin{bmatrix} 1&1&1&...&1\\ 1&s&s^2&...&s^{N-1}\\ 1&s^2&s^4&...&s^{2(N-1)}\\ 1&s^3&s^6&...&s^{3(N-1)}\\ ...&...&...&...&...\\ 1&s^{N-1}&s^{2(N-1)}&...&s^{(N-1)(N-1)}\\ \end{bmatrix} S=1111...11ss2s3...sN11s2s4s6...s2(N1)..................1sN1s2(N1)s3(N1)...s(N1)(N1)

G = S ⋅ g , s = e − i 2 π N G = S\cdot g,s = e^{\frac{-i2\pi}{N}} G=Sg,s=eNi2π

则有频域样本

G ( t ) = ∑ n = 0 N − 1 g ( n ) s k n f o r      k = 0 , . . . , N − 1 G(t) = \sum_{n=0}^{N-1}g(n)s^{kn} for \ \ \ \ k = 0,...,N-1 G(t)=n=0N1g(n)sknfor    k=0,...,N1

S是对角对称矩阵,且第k行和第N-k行共轭(从第0行开始数),因此N个采样点的实值输入信号仅具有N/2+1个余弦和正弦,盛于的N/2频域值提供了冗余信息。

矩阵向量乘法

示例代码

#define SIZE 8
typedef int BaseType;
void matrix_vector(BaseType M[SIZE][SIZE], BaseType V_In[SIZE], BaseType V_Out[SIZE]) {
	BaseType i, j;
data_loop:
	for (i = 0; i < SIZE; i++) {
		BaseType sum = 0;
	dot_product_loop:
		for (j = 0; j < SIZE; j++) {
			sum += V_In[j] * M[i][j];
			}
		V_Out[i] = sum;
	}
}

matrix_vector 功能共有三个参数,我们对前两个参数进行乘法计算,输入矩阵和向量分别是BaseType M[SIZE][SIZE] 和 BaseType V In[SIZE]。第三个参数 BaseType V_Out[SIZE] 是合成向量。

pipeline和并行运行

这个基本算法就是循环嵌套,但是可以考虑能不能用并行思想来加速。

比如先考虑优化sum的累加

#define SIZE 8
typedef int BaseType;
void matrix_vector(BaseType M[SIZE][SIZE], BaseType V_In[SIZE], BaseType V_Out[SIZE]) {
	BaseType i, j;
data_loop:
for (i = 0; i < SIZE; i++) {
	BaseType sum = 0;
	V_Out[i] = V_In[0] * M[i][0] + V_In[1] * M[i][1] + V_In[2] * M[i][2] +
				V_In[3] * M[i][3] + V_In[4] * M[i][4] + V_In[5] * M[i][5] +
				V_In[6] * M[i][6] + V_In[7] * M[i][7];
	}
}

如果每个乘法同时执行,可以用加法器树求和就很好了。

在这里插入图片描述

在FPGA上加法器无法共享,因为加法器和多路复用器需要相同数量的资源

使用更少的乘法器将需要更多的时间周期。
在这里插入图片描述
在此基础上还可以进一步优化

在这里插入图片描述

还有更牛逼的优化

在这里插入图片描述

通过添加几个指令就能实现高度并行

#define SIZE 8
typedef int BaseType;

void matrix_vector(BaseType M[SIZE][SIZE], BaseType V_In[SIZE], BaseType V_Out[SIZE]) {
#pragma HLS array_partition variable=M dim=2 complete
#pragma HLS array_partition variable=V_In complete
	BaseType i, j;
data_loop:
	for (i = 0; i < SIZE; i++) {
#pragma HLS pipeline II=1
		BaseType sum = 0;
	dot_product_loop:
		for (j = 0; j < SIZE; j++) {
			sum += V_In[j] * M[i][j];
		}
		V_Out[i] = sum;
	}
}

内部j循环由Vivado HLS 自动展开,因此j在每次使用的时候都被替换为常量。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆沙粽子好吃嘛!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值