版本一版本一主要是用来测试AXI总线IP核的实现可能。
- 该模块拥有19个32位寄存器
- 其中前9个寄存器用来保存需要计算的值
- 后面9个寄存器用来保存卷积核
- 在读取第19个寄存器的地址的时候计算9个寄存器的卷积和(该计算可以在一个时钟周期内完成)
- 9个寄存器单独赋值,程序中分别向对应地址写入内容,通过总线进行传输。
- 故乐观的来算,需要10个总线周期可以获取一个输出
可以从驱动的书写简单理解一下:
void Conv_HW(int filter[3][3], int arr[100][100], int filterW, int filterH, int arrW, int arrH) { int i, j; for (i = 2; i < filterH + arrH - 3; i++) { for (j = 2; j < filterW + arrW - 3; j++) { Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR, arr[j]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR+4, arr[j - 1]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR+8, arr[j - 2]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR+12, arr[i - 1][j]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR+16, arr[i - 1][j - 1]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR+20, arr[i - 1][j - 2]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR+24, arr[i - 2][j]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR+28, arr[i - 2][j - 1]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR+32, arr[i - 2][j - 2]); res[j] = Xil_In32(XPAR_CONV_0_S00_AXI_BASEADDR + 72); } if (i % 15 == 0) printf("="); }}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
版本一性能- 版本一性能最惨,由于没有时间戳,目测软件计算速度远远快于FPGA核心运算速度。
- 版本一的改进速度就是引入滑动窗口,能够最大程度减少总线周期。
版本二版本二引入滑动窗口,和初期设计的概念相同。
- 该模块拥有19个32位寄存器
- 其中前9个寄存器用来保存需要计算的值
- 后面9个寄存器用来保存卷积核
- 在读取第19个寄存器的地址的时候计算9个寄存器的卷积和(该计算可以在一个时钟周期内完成)
- 三个寄存器滑动赋值,该计算窗口在计算矩阵上滑动 除了冷启动多余两个周期用来预载寄存器,后面的每一个计算只需要四个总线周期
可以通过写的驱动简单理解一下:
void Conv_HW(int filter[3][3], int arr[100][100], int arrW, int arrH) {int i, j;i = 2; j = 2;for (i = 2; i < arrH; i++) { //pre load Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR + 8, arr[i - 1][j - 1]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR + 20, arr[j - 1]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR + 32, arr[i + 1][j - 1]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR + 8, arr[i - 1][j]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR + 20, arr[j]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR + 32, arr[i + 1][j]); for (j = 2; j < arrW; j++) { Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR + 8, arr[i - 1][j + 1]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR + 20, arr[j + 1]); Xil_Out32(XPAR_CONV_0_S00_AXI_BASEADDR + 32, arr[i + 1][j + 1]); res[j] = Xil_In32(XPAR_CONV_0_S00_AXI_BASEADDR + 72); }}} 版本二性能测试样本 500*500的32bit单位的矩阵 计算200次。
软件消耗33.78秒,卷积IP核心40.25秒
这样的结果还是非常不乐观,分析可能有两种限制了IP核的速度。
- 两个寄存器的乘法LUT太大,无法硬件优化
- 总线周期太慢太慢
版本三对于这两种可能进行探索。 |