鸽了这么久,正式开工


  Author: carbon
  email: ecras_y@163.com

  参考资料:

https://github.com/tensorflow/tensorflow

https://github.com/snipsco/tensorflow-build


 

  年中6月份的时候被抽到AI项目组,有幸接触目前最火的深度学习神经网络,

  从开始到现在,一直坚守在google的tensorflow

  目前行业的趋势是在PC或者服务器集群上进行训练,然后将训练好的模型export到mobile设备上,

  由mobile设备加载使用这些训练好的模型。

  我早几年前做过很多嵌入式的项目,所以将tensorflow移植到mobile嵌入式平台上的任务就落到了我的身上,我也当仁不让,

  一撸到底。

  目前仅支持交叉编译tensorflow的c和c++模块。

  python模块由于链接目标库问题,在mobile设备上也没有训练模型的需求,

  兼具性能的考虑,暂时没做python这一块的交叉编译支持。感兴趣的同学可以自己试试看。

 

  测试板子使用树莓派,

  树莓派可以跑完整的Linux操作系统,如果需要在树莓派上运行基于python的tensorflow,

  需要在树莓派上进行编译,但是可能需要编译几天时间

  基于以后可能需要将项目export到其它的嵌入式系统上,需要考虑到通用性  

  Android的编译比较特殊,直接使用官方的预编译好的组件即可

  这里只考虑非Android和iOS的嵌入式平台

 

  tensorflow编译使用bazel进行自动化编译管理,涉及到:

  1. 子模块网络下载

  2. 预编译期代码生成(generate files)

  3. 模块之间依赖判定

  4. 代码编译

 

  如果将工程更改为Makefile编译,工作量巨大,难以操作

  最好的做法还是使用bazel,加入交叉编译支持

  bazel交叉编译官方有一些指导文档,有很好的参考意义

https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain

 下载源码

  使用git命令下载tensorflow源码

git clone git@github.com:tensorflow/tensorflow.git

  google在最近发布了tensorflow lite,用于支持mobile设备,

  更小的编译目标文件,更好的性能

  但是还没有export到最新的tag中,所以这里我们直接基于master分支来操作

git checkout master

git checkout -b cross-compile

  文章最后加入对交叉编译tensorflow lite的说明

  编译之前需要先修正数据对齐bug

  x86和x64平台无对齐问题

  但是在某些arm平台上,需要地址对齐,

  否则程序会在运行时,访问内存奇数地址或者未对齐地址,导致crash

vim tensorflow/core/lib/gtl/inlined_vector.h +288

  将 T* unused_aligner 替换为 uint64_t unused_aligner

  强制为8字节对齐

 准备交叉编译工具链

  这里以树莓派为例

git clone https://github.com/raspberrypi/tools.git

  下载完成之后,将工具链路径添加到PATH中

 脚本编写

  目录结构

.

└── tensorflow

    ├── armv6-compiler

    │   ├── BUILD

    │   ├── CROSSTOOL

    │   └── cross_toolchain_target_armv6.BUILD

    ├── build_armv6.sh

    ├── build_tflite.sh

 

    └── WORKSPACE

  

  1. 修改WORKSPACE文件,添加交叉编译工具链仓库描述

  打开WORKSPACE文件,按照bazel的语法在文件末尾添加以下内容

new_local_repository(

        name='toolchain_target_armv6',

        path='/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf',

        build_file = 'armv6-compiler/cross_toolchain_target_armv6.BUILD'

 

)

  参数说明:

  交叉编译工具链别名: toolchain_target_armv6

  交叉编译工具链路经: /path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf

  交叉编译工具链描述文件: armv6-compiler/cross_toolchain_target_armv6.BUILD

 

  2. 编写WORKSPACE仓库引用的交叉编译工具链的BUILD描述文件

mkdir armv6-compiler && cd armv6-compiler

touch cross_toolchain_target_armv6.BUILD

 

vi cross_toolchain_target_armv6.BUILD

  具体语法规则参考详见

https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain

  脚本内容如下:

 1 package(default_visibility = ['//visibility:public'])
 2 
 3 filegroup(
 4   name = 'gcc',
 5   srcs = [
 6     'bin/arm-linux-gnueabihf-gcc',
 7   ],
 8 )
 9 
10 filegroup(
11   name = 'ar',
12   srcs = [
13     'bin/arm-linux-gnueabihf-ar',
14   ],
15 )
16 
17 filegroup(
18   name = 'ld',
19   srcs = [
20     'bin/arm-linux-gnueabihf-ld',
21   ],
22 )
23 
24 filegroup(
25   name = 'nm',
26   srcs = [
27     'bin/arm-linux-gnueabihf-nm',
28   ],
29 )
30 
31 filegroup(
32   name = 'objcopy',
33   srcs = [
34     'bin/arm-linux-gnueabihf-objcopy',
35   ],
36 )
37 
38 filegroup(
39   name = 'objdump',
40   srcs = [
41     'bin/arm-linux-gnueabihf-objdump',
42   ],
43 )
44 
45 filegroup(
46   name = 'strip',
47   srcs = [
48     'bin/arm-linux-gnueabihf-strip',
49   ],
50 )
51 
52 filegroup(
53   name = 'as',
54   srcs = [
55     'bin/arm-linux-gnueabihf-as',
56   ],
57 )
58 
59 filegroup(
60   name = 'compiler_pieces',
61   srcs = glob([
62     'arm-linux-gnueabihf/**',
63     'libexec/**',
64     'lib/gcc/arm-linux-gnueabihf/**',
65     'include/**',
66   ]),
67 )
68 
69 filegroup(
70   name = 'compiler_components',
71   srcs = [
72     ':gcc',
73     ':ar',
74     ':ld',
75     ':nm',
76     ':objcopy',
77     ':objdump',
78     ':strip',
79     ':as',
80   ],
81 )
cross_toolchain_target_armv6.BUILD

相关文章: