对嵌套循环的加速。
void ConvProcess(float temp[CHN_IN],float sum[CHN_OUT])
{
//#pragma HLS ARRAY_PARTITION variable=filter_buf complete dim=2
int i,j;
convprocess1:
for(j=0;j<CHN_IN;j++)//Input channel
{
//#pragma HLS PIPELINE
//sum_0=0;sum_1=0;sum_2=0;sum_3=0;
convprocess2:
for(i=0;i<CHN_OUT;i++)//Output channel
{
//#pragma HLS UNROLL factor=2
//#pragma HLS PIPELINE
sum[i]+=temp[j]*filter_buf[i][j];
}
}
}
void ConvProcess(float temp[CHN_IN],float sum[CHN_OUT])
{
#pragma HLS ARRAY_PARTITION variable=filter_buf complete dim=2
int i,j;
convprocess1:
for(j=0;j<CHN_IN;j++)//Input channel
{
#pragma HLS PIPELINE
//sum_0=0;sum_1=0;sum_2=0;sum_3=0;
convprocess2:
for(i=0;i<CHN_OUT;i++)//Output channel
{
//#pragma HLS UNROLL factor=2
#pragma HLS PIPELINE
sum[i]+=temp[j]*filter_buf[i][j];
}
}
}
使用这种优化方法的效果,综合时间较长。
换一个清晰一点的卷积思路
void ConvProcess(float temp[CHN_IN],float sum[CHN_OUT])
{
//#pragma HLS ARRAY_PARTITION variable=filter_buf complete dim=2
int i,j;
float tmp_sum;
convprocess1:
for(i=0;i<CHN_OUT;i++)//Input channel
{
//#pragma HLS PIPELINE
//sum_0=0;sum_1=0;sum_2=0;sum_3=0;
convprocess2:
tmp_sum = 0;
for(j=0;j<CHN_IN;j++)//Output channel
{
//#pragma HLS UNROLL factor=2
//#pragma HLS PIPELINE
tmp_sum += temp[j]*filter_buf[i][j];
}
sum[i] = tmp_sum;
}
}
- 浮点乘法需要3个dsp 浮点加法需要两个dsp
- 浮点乘法需要5个周期 浮点加速需要10个周期
对内层的convprocess2进行pipeline指令优化。
对外层的convprocess使用pipeline指令。
最外层pipeline 内层unroll。
此时,对端口进行切割操作。
#pragma HLS ARRAY_RESHAPE variable=temp complete dim=1
#pragma HLS ARRAY_RESHAPE variable=filter_buf complete dim=2
看来在没有了数据读写端口的限制下,可以达到initiation interval为1的间隔。
如果按照给最大资源的思路进行优化的话
void ConvProcess(float temp[CHN_IN],float sum[CHN_OUT])
{
#pragma HLS ARRAY_RESHAPE variable=filter_buf complete dim=2
#pragma HLS ARRAY_RESHAPE variable=sum complete dim=1
#pragma HLS PIPELINE
#pragma HLS ARRAY_RESHAPE variable=temp complete dim=1
#pragma HLS ARRAY_RESHAPE variable=filter_buf complete dim=2
//#pragma HLS ARRAY_PARTITION variable=filter_buf complete dim=2
int i,j;
for(j=0;j<CHN_IN;j++)//Input channel
{
//#pragma HLS PIPELINE
//sum_0=0;sum_1=0;sum_2=0;sum_3=0;
for(i=0;i<CHN_OUT;i++)//Output channel
{
//#pragma HLS UNROLL factor=2
//#pragma HLS PIPELINE
sum[i]+=temp[j]*filter_buf[i][j];
}
}
}
为了更好的分析,把chn in改为3 cnh out改为6
分析报告如下
这里的一个疑问就是为什么乘法的环节这么少。
如果不对端口和数组做优化呢
分析图如下:
如果对权重数组做优化呢?
发现没有变换。看来如果不对输入输出同样做优化的话,就没啥用。