imx6ull部署tensorflow lite

问题描述

需求是要在imx6ull上跑起来tensorflow lite神经网络模型,进阶目标是可以在QT中编写tensorflow lite应用

环境

  1. 操作环境:VMware中的Ubuntu
  2. 部署环境:linux on imx6ull(正点原子出厂系统)

基本步骤总结

  1. 交叉编译出TensorFlow lite针对imx6ull的库
  2. 将编译好的lite库放在开发板上,Ubuntu中也要保留,且尽量在一样的位置,方便引用
  3. 在qt开发时,将lite库进行引用,将qt软件编译完成后放置到开发板上
  4. 其中的模型就是tflite,这个可以在Python端产生和转换

解决步骤

  1. 安装交叉编译工具
    • 这一步在正点原子的环境中已经配置过了,没有配置过的同学可以看参考链接
  2. 下载Tensorflow库,并编译其中的微处理器tensorflow lite库1
    1. 下载Tensorflow库
      • tensorflow/tensorflow: An Open Source Machine Learning Framework for Everyone (github.com)
      • 或者git clone https://github.com/tensorflow/tensorflow
    2. 解压后编译其中的微处理器tensorflow lite库
      1. 进去tensorflow总目录执行脚本下载依赖
        • 在低版本的tenrsoflow上可以使用下面的语句./tensorflow/lite/tools/make/download_dependencies.sh
        • 在高版本的tensorflow上,根据文件夹中的README.md,可知之前的文档已启用,需要使用新的方式进行编译,根据提示进入网站2后,可以看到提供了两种方式,Bazel与cmake,由于要用QT并且已经配好了cmake,这里选择cmake的方式3
        • 由于配置cmake过程中发现由于Tensorflow版本更新,配置需要的过程很复杂,而在仔细梳理部署步骤后,这一步完全可以编译之后发布到ARM,不是必须使用自己已经配置好的环境,因此使用Docker,并且使用官方更推荐的Bazel
      2. 使用cmake编译微处理器tensorflow lite库
        1. 检查目标处理器的适配性
          1. cat /proc/cpuinfo
          2. 查看imx6ull返回的信息4,可知应该选择Build for ARMv7 NEON enabled一项,可以根据这里的来配置cmake
        2. 根据下面的Run CMake5进行编译,编译过程参考6,其中cmake时提示一些包没办法下载,强烈建议手动下载并放到指定的位置上(这里建议参考使用clash for linux,代理后无需手动操作)
        3. 配置好后成功进行configuration
        4. 之后需要进行编译
          • cmake --build . -j8
          • 编译过程中报错arm-linux-gnueabihf-g++: error: unrecognized command line option ‘-mavx512f’,经查是gcc版本太低,换一个版本进行编译
          • 这里更换的版本是gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf
          • 更换更高版本gcc后有不明原因的报错,没有报错信息,观察到每次报错会卡死,提高虚拟机的核心数,重新进行编译,问题消失。
        5. 顺便将label_image编译出来,进行测试
          • cmake --build . -j -t label_image
          • 编译成功后放到开发板运行报错version GLIBCXX_3.4.22 not found
          • 是开发板libstdc++.so.6版本的问题,更新版本7
            • 下载一个更新的版本,我是在Ubuntu里进行了搜索,发现有支持3.4.22的libstdc,所以就将Ubuntu里的移动到了开发板上
              • sudo find / -name "libstdc++.so.6*"(搜索系统里的libstdc)
              • rm -rf libstdc++.so.6(在目录下删除原来的软连接)
              • ln -s libstdc++.so.6.0.23 libstdc++.so.6(生成新的软连接)
            • 问题成功解决
          • 下载model与label,放到同一个文件夹下进行测试
            • 这里放一下成功后的控制台显示,纪念一下8
        6. 尝试自己编译一下minimal,方便后续编写自己的程序9
          • 成功编译,调用mobilenet_v1_1.0_224.tflite
          • 下面跳转到使用QT编写程序的阶段
        • 使用Bazel
        1. 安装与配置docker
          1. 在 Ubuntu | 上安装 Docker 引擎Docker 文档
          2. 配置国内源
          3. 拉取TensorFlow devel docker 镜像
            • docker pull tensorflow/tensorflow:devel
          4. 启动镜像
            • docker run -d -it --name tflite tensorflow/tensorflow:devel
          5. 进入镜像控制台
            • docker attach tflite
        2. 使用Bazel构建ARM 二进制文件
          • 进入/tensorflow_src/目录下执行以下指令
          • bazel build --config=elinux_armhf -c opt //tensorflow/lite:libtensorflowlite.so
          • 在执行这个指令的时候会需要链接外网下载一部分文件,连不上的话会报错。搜索终端代理会有人推荐proxychains,实测配起来很麻烦,建议使用clash for linux,配置相对简单。如果过程中下载失败的话可能网速还是太慢,断连了,可以重新执行指令。
          • 编译成功后,编译好的结果在bazel-bin/tensorflow/lite/libtensorflowlite.so
        3. 将编译好的动态库so文件从docker中取出
          1. docker cp tflite:tensorflow_src/bazel-bin/tensorflow/lite/libtensorflowlite.so ./10
          2. 将libtensorflowlite.so放到开发板上的文件系统/usr/lib下
          3. 动态库编译好后需要在ubuntu上配置其他的静态库,主要就是将我们熟悉的.h文件提取出来放到一个include中进行调用,可以在tensorflow_src/tensorflow中使用下面的语句将所有需要的h文件打包为一个tar包,方便我们提取出来11
            • find ./lite -name "*.h" | tar -cf headers.tar -T -
          4. 编译官方demo测试
            1. 编译官方demo
              • bazel build --config=elinux_armhf -c opt //tensorflow/lite/examples/label_image:label_image
              • bazel build --config=elinux_armhf -c opt //tensorflow/lite/tools/benchmark:benchmark_model
            2. 编译报错,暂且不编
        • 编写QT中的c++程序进行简单测试
        1. 新建QT工程
        2. 在QT的引用中添加库的位置(项目右键->添加库->外部库)
          • 这里遇到了编译时FlatBuffers报错的问题,是版本的原因,API有所改变,降低版本即可。
        3. 基于minimal的文件进行修改,首先添加tensorflow的头文件进行测试,发现此时可以正常将头文件进行编译了12
        4. 基于minimal的文件与label_image的模型和测试数据进行部署测试
          1. 第一次到这一步是使用Docker+Bazel的方式,到这里.so文件报错,经查询是因为Docker中的系统glibc的版本与ubuntu和开发板的版本不对应
          2. 尝试更换Docker容器中glibc的版本13
            1. 此降级操作有风险,重新尝试cmake路线之后产生了可用的程序,这一条路没有继续走了,有兴趣的同学可以继续尝试
          3. 这一步添加了使用的方法后构建报错一百多个,经排查是由于那个600多MB的静态库还有许多的依赖没有包含,需要我们意义手动添加
          4. 手动添加后发现还是有报错,是关于std::的,当前怀疑是由于编译lite库使用的工具链与QT中配置的工具链不同
  3. 适用于微控制器的 TensorFlow Lite

参考文献


  1. 在树莓派上构建 TensorFlow Lite (google.cn) ↩︎

  2. 为 ARM 开发板构建 TensorFlow Lite ↩︎

  3. Cross compilation TensorFlow Lite with CMake ↩︎

  4. 检查系统显示的信息

    model name	: ARMv7 Processor rev 5 (v7l)
    BogoMIPS	: 12.00
    Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae 
    CPU implementer	: 0x41
    CPU architecture: 7
    CPU variant	: 0x0
    CPU part	: 0xc07
    CPU revision	: 5
    
    ↩︎
  5. cmake编译设置

    		ARMCC_FLAGS="-march=armv7-a -mfpu=neon-vfpv4 -funsafe-math-optimizations -mfp16-format=ieee"
    		ARMCC_PREFIX=${HOME}/toolchains/gcc-linaro-7.1.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
    		cmake -DCMAKE_C_COMPILER=${ARMCC_PREFIX}gcc \  -DCMAKE_CXX_COMPILER=${ARMCC_PREFIX}g++ \  -DCMAKE_C_FLAGS="${ARMCC_FLAGS}" \  -DCMAKE_CXX_FLAGS="${ARMCC_FLAGS}" \  -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \  -DCMAKE_SYSTEM_NAME=Linux \  -DCMAKE_SYSTEM_PROCESSOR=armv7 \  ../tensorflow/lite/
    
    ↩︎
  6. Linux 编译 tensorflow-lite 静态库 - 简书 (jianshu.com) ↩︎

  7. 解决类似 /usr/lib64/libstdc++.so.6: version GLIBCXX_3.4.21 not found 的问题 - IT笔录 (itbilu.com) ↩︎

  8. ↩︎
  9. 使用 CMake 构建 TensorFlow Lite ↩︎

  10. 怎么访问docker容器中的文件_knight11112的博客-CSDN博客_访问docker中的文件 ↩︎

  11. c++调用tflite实战 - 微笑sun - 博客园 (cnblogs.com) ↩︎

  12. tensorflow/minimal.cc at master · tensorflow/tensorflow (github.com) ↩︎

  13. 关于Linux下更换不同glibc版本的解决方法 - 灰信网(软件开发博客聚合) (freesion.com) ↩︎

你可能感兴趣的:(linux,边缘计算)