从一个矩阵乘法的例子一步一步进行功能设计与性能优化。
SDAccel矩阵乘法优化(一)
SDAccel矩阵乘法优化(二)
SDAccel矩阵乘法优化(三)
SDAccel矩阵乘法优化(四)
mmult实现及优化步骤
步骤 | 实现功能 | 关键概念/ Keywords |
---|---|---|
1、cpu实现 | 即在host 端实现简单的矩阵乘法,便于比对数据与性能对比 |
|
2、OpenCL实现 | 在device 端实现基于OpenCL的FPGA矩阵乘法硬件设计. |
Key Concepts - OpenCL APIs |
3、加入Local Memory |
采用 Local Memory 减少数据访存次数 |
Key Concepts - Kernel Optimization - Local Memory |
4、实现读写的突发传输 | 采用突发传输的方式更好的实现DDR 与 Local Memory 数据的读写访问 |
Key Concepts - Kernel Optimization - Burst Read/Write |
5、数组分割 | 通过循环展开与数组分割的方式,实现更好的计算性能 | Key Concepts - Array Partition - Loop Unroll Keywords - xcl_pipeline_loop - xcl_array_partition(complete, dim) - opencl_unroll_hint |
方案分析及优化思路一(Local Memory)
首先,我们先进行访存上的优化。原始版本的矩阵乘法实现虽然简单,但是在进行计算的过程中需要频繁的与DDR进行数据交互,但是DDR与FPGA进行交互的过程中是十分耗费时间与功耗的,因此,我们需要在FPGA上开一个局部的存储空间,先将数据从DDR搬运到FPGA片上的存储空间上,然后再进行计算,计算的过程数据在片上的空间进行索引,最后将计算完的数据再统一搬运回DDR上。这样,在片上的计算过程就不会频繁的受到DDR与FPGA访存慢的限制。
代码实现
1 |
|
实验结果分析
- vivado hls log文件分析
1 |
|
- HLS Report
- 综合结果分析
* 首先,硬件代码没有优化指令,不需要关注指令是否实现。
* 然后,相比于原始版本的矩阵乘法实现,Local Memory
的实现方式首先将整体的代码风格进行了调整,切分成三段并列的for
循环形式。从Pipleline
的角度考虑:第一段for循环pipeline
成功;第二段的for循环只有write_data
的for循环成功,最外层的两个for循环成功完成flatten
但是write_data
与次外层的for循环因为含有LOOP BODY
的原因,无法成功flatten
,因此也无法完成整体的pipeline
;第三段for循环pipeline
成功。
* 从pipeline成功后的II角度考虑:第一段for循环pipeline
后的II=2
,原因依然是 gmem carry dependency
;第二三段for循环pipeline
后的II=1
。
- 硬件仿真结果
- 硬件实现结果
参考
xilinx github Xilinx/SDAccel_Examples/cpu_to_fpga
ug1253 SDx Pragma Reference Guide 2017.2
ug1207 SDAccel Environment Optmizaton Guide