矩阵乘法C++实现
- 新建工程
- 添加源文件和测试文件
- 编写源代码和测试代码(仅仅是实现功能还没有做优化)
matrix.h
#ifndef __MATRIX__
#define __MATRIX__
#include "ap_fixed.h"
void matrix(ap_int<8> A[20][20],ap_int<8> B[20][20],ap_int<16> C[20][20]);
#endif
matrix.cpp
#include "matrix.h"
void matrix(ap_int<8> A[20][20],ap_int<8> B[20][20],ap_int<16> C[20][20])
{
for(int i=0;i<20;i++)
for(int j=0;j<20;j++)
{
C[i][j]=0;
for(int k=0;k<20;k++)
{
C[i][j]=C[i][j]+A[i][k]*B[k][j];
}
}
}
main.cpp
#include "matrix.h"
#include <iostream>
int main()
{
ap_int<8> A[20][20];ap_int<8> B[20][20];ap_int<16> C[20][20];
for(int i=0;i<20;i++)
for(int j=0;j<20;j++)
{
A[i][j]=i*20+j;
B[i][j]=A[i][j];
}
matrix(A,B,C);
for(int i=0;i<20;i++)
for(int j=0;j<20;j++)
std::cout<<"C["<<i<<","<<j<<"]="<<C[i][j]<<std::endl;
return 0;
}
C仿真结果
功能优化
- 当c仿真通过的时候,就可已进行联合仿真
把martix.cpp文件设为顶层文件
点击C synthesis联合仿真,就是相当于把c++转换成对应的电路
在这里可以看到没做优化前,跑完工程花的时间挺长的
从下图可以看出最内层循环loop1.1.1执行一次需要2个周期,一共执行了20次所以需要40个周期
Loop1.1也是执行20次,执行一次需要42个周期
Loop1 执行20次,每次需要842个周期
在这里把最内层循环unroll,或者再其外面加一个pipeline=1,目的是让最内层循环一次展开
可以看出的确优化了不少,但是还没达到我们想要
是什么原因导致的呢?这时候看一下warnning,显示存储器读写冲突,这个时候可以用hls工具进行联合仿真一下,然后用vivado看一下波形,找出是什么问题导致没有实现我们想要的电路.
我们想要的是每个周期取出A的一行,B的一列,然后算出c的一个元素,从波形图可以看出,A,B每一个周期读出两个元素,所以判定是数组读写冲突,下面对数组进行优化
就是将A,B数组的一行或者一列完全展开,从下图我们可以看出已经优化到我们想要的电路了。
细节讲解
- interval 和 latency
interval是指每两次矩阵乘法之间的间隔时间
latency是指完成一次矩阵乘法所需要的时间
-------------------------------------------------------------------------------更新-----------------------------------------------------------------------------
2.循环展开
#pragma HLS UNROLL
告诉编译器电路并行展开成N份
3.pipeline处理
#pragma HLS PIPELINE II=1
告诉编译器interval latency为1
4.数组优化
RESHAPE 和 PARTATION
partition可以增加寄存器端口
reshape仅仅增加数据字的带宽
#pragma HLS ARRAY_RESHAPE variable=A complete dim=2
#pragma HLS ARRAY_RESHAPE variable=B complete dim=1
// #pragma HLS ARRAY_PARTITION variable=A complete dim=2
// #pragma HLS ARRAY_PARTITION variable=B complete dim=1
5.接口综合约束
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE s_axilite port=A
#pragma HLS INTERFACE s_axilite port=B
#pragma HLS INTERFACE s_axilite port=C