FPGA
在上一节中,我们介绍了目前FPGA软件开发的基本情况和面临的问题,讲解了LeFlow开源工具的作用和基本的使用方式。这一小节我们将详解如何利用该开源项目快速将TensorFlow的模型转换到FPGA中。
安装部署
前提依赖:
♦ 拷贝LeFlow中对TensorFlow的修改代码,并进行编译(编译的时候记得选XLA支持)
♦ 编译TensorFlow需要工具:bazel
♦ 安装miniconda环境
使用conda创建python-2.7的环境,用来安装新编译的TensorFlow和其他依赖:
conda create --name py27 python=2.7
conda activate py27
conda install numpy
conda install matplotlib
conda install libgcc
pip install scipy
下载LeFlow代码及例子,这里我做了一些demo的增加,所以可以直接用我的。
git clone https://github.com/cdyangzhenyu/LeFlow.git
添加需要的环境变量
vi/etc/profile
...
export PATH=$PATH:/usr/loca/bin:/opt/inteldevstack/intelFPGA_pro/quartus/bin:/opt/inteldevstack/intelFPGA_pro/quartus/sopc_builder/bin:/opt/inteldevstack/intelFPGA_pro/hld/bin:/root/legup-4.0/llvm/Release+Asserts/bin:/opt/intelFPGA_modelsim/16.1/modelsim_ase/linux
export LD_LIBRARY_PATH=/root/miniconda3/lib:$LD_LIBRARY_PATH
...
这样LeFlow就安装好了。
测试
找一个简单的矩阵卷积代码做测试。
(py27) [root@fpga 09_conv2d_a]# cd LeFlow/test/09_conv2d_a
查看该文件代码:09_conv2d_a.py
import tensorflow as tf
import numpy as np
import string
import sys
sys.path.append('../../src')
import processMif as mif
size = 8
outputs = 2
X = tf.placeholder(tf.float32, [1, size,size,1])
weights = tf.placeholder(tf.float32, [3,3,1,outputs])
in_x = np.random.rand(1,size,size,1)
in_weights = np.random.rand(3,3,1,outputs)
mif.createMem([in_x,in_weights])
with tf.Session() as sess:
with tf.device("device:XLA_CPU:0"):
y = tf.nn.conv2d(X, weights, strides=[1, 1, 1, 1], padding='SAME')
sess.run(tf.global_variables_initializer())
result = sess.run(y,{X: in_x, weights: in_weights})
np.save("tf_result.npy" ,result)
print(result)
该例子就是一个8*8*1的矩阵和一个3*3*2的卷积核进行卷积,输出一个8*8*2的张量。可以看到全部由TensorFlow的框架实现。
♦ 其中mif.create是必须的,它会将参数的具体值保存在legup需要的文件中,这里还有个需要注意的,如果参数非常多的情况下,一定要把参数顺序搞对,否则做仿真时会报错,legup生成的顺序应该与参数的入栈顺序相关。
♦ with tf.device("device:XLA_CPU:0"):所有需要编译转换的代码,都需要写在它下面。
接下来使用LeFlow对该代码进行编译转换
(py27) [root@fpga 09_conv2d_a]# ../../src/LeFlow 09_conv2d_a.py
如果输出最后包含如下信息,则说明转换成功:
INFO: Converting between LLVM versions...
INFO: Running first batch of optimizations before unrolling...
INFO: Unrolling and Inlining according to user, simplifying elementary branches and optimizing away other values...
INFO: Restructuring the IR signature...
INFO: Rewriting unsupported operations...
INFO: Partitioning arrays...
User did not specify any arrays to partition
INFO: Converting human-readable .ll file to bitcode...
INFO: Starting LegUp Compilation...
INFO: Verilog file generated successfully
INFO: Instrumenting testbench and mapping args and temps
INFO: DONE!
注意:很多情况下可能会出错,比如代码语法有错误,网络权值过大(单层参数过万),某些不支持的算子等等。
查看输出:
(py27) [root@fpga 09_conv2d_a]# ll 09_conv2d_a_files
...
param0.mif
param1.mif
temp0.mif
09_conv2d_a.v
tfArgs
...
上面列出的都是比较重要的文件,其中.v文件就是我们需要的Verilog代码,接下来就可以根据上一篇文章做FPGA的仿真了。
总结
本文主要介绍了目前FPGA软件开发的基本情况和面临的问题,讲解了LeFlow开源工具的作用和基本的使用方式。下面会讲如何利用LeFlow实现将MNIST手写字识别算法移植到FPGA中。
★作者简介★
杨振宇,海云捷迅资深系统架构师,成都信息工程大学计算机应用技术硕士研究生毕业,10余年软件开发和架构经验,熟悉Linux,OpenStack,Kubernetes,Docker等开源技术并具有开源社区贡献经历,在云计算、人工智能、物联网等技术领域有较深的研究和丰富的一线开发经验。
推荐阅读
(1)如何将TensorFlow代码转换到FPGA上(一)
2 | 技术解读| 开源HLS工具Legup-4.0介绍(一) |
3 | SRIO 在某无线通信系统中的应用(一) |