1. 程式人生 > >嵌入式深度學習之mxnet交叉編譯Arm Linux

嵌入式深度學習之mxnet交叉編譯Arm Linux

參考文件

本文件涉及到的目標硬體為全志H8(8核Cortex-A7,Armv7架構),但是對其他Arm晶片也有一定的借鑑意義,只需要更換交叉編譯鏈即可。

開發環境介紹

  • 主機作業系統:Ubuntu14.04 64位
  • 目標平臺:CQA83t 全志H8
  • 交叉工具鏈:arm-linux-gnueabihf,gcc4.9.2
  • mxnet版本:20180124-master

注意:mxnet的最低GCC版本為4.8.0

設定交叉編譯鏈

# 在/etc/bash.bashrc的最後增加如下指令
# Allwinner H8 CQA83t cross compiler
export ARCH=arm
export
PATH=/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/:$PATH export CROSS_COMPILE=arm-linux-gnueabihf- export CC=/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-gcc export CXX=/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-g++ export
LD=/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-ld export AR=/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-ar export AS=/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-as export RANLIB=/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9
-2014.09_linux/bin/arm-linux-gnueabihf-ranlib # 修改完成之後需要重啟命令列才能生效 # 你可以通過如下指令來確認交叉編譯鏈是否已經設定好 echo $CC # 當顯示/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-gcc時表示交叉編譯鏈 # 已經設定好 # 當需要更換為本機編譯時遮蔽上面的指令即可

下載依賴庫

編譯OpenBLAS

編譯

cd OpenBLAS-0.2.20
# 編譯單獨的靜態庫版本
make TARGET=ARMV7 HOSTCC=gcc CROSS=1 CROSS_SUFFIX=arm-linux-gnueabihf- BINARY=32 NOFORTRAN=1 libs -j8
# 編譯動態庫版本
make TARGET=ARMV7 HOSTCC=gcc CROSS=1 CROSS_SUFFIX=arm-linux-gnueabihf- BINARY=32 NOFORTRAN=1 libs shared

# 另附上ARMV8晶片的編譯命令以供參考
make TARGET=ARMV8 HOSTCC=gcc CROSS=1 CROSS_SUFFIX=aarch64-linux-gnu- BINARY=64 NOFORTRAN=1 libs -j8
make TARGET=ARMV8 HOSTCC=gcc CROSS=1 CROSS_SUFFIX=aarch64-linux-gnu- BINARY=64 NOFORTRAN=1 libs shared -j8

安裝

# PREFIX使用您自己的自定義安裝目錄
make PREFIX=/usr/local/H8/openBLAS-0.2.20 install

編譯mxnet

修改CmakeLists.txt

修改
# ---[ LAPack
if(USE_LAPACK)
  add_definitions(-DMXNET_USE_LAPACK=1)
  list(APPEND mxnet_LINKER_LIBS lapack)
else(USE_LAPACK)
  Workaround for Windows until using new Jenkinsfile.
  if(BLAS STREQUAL "Open" OR BLAS STREQUAL "open")
    add_definitions(-DMXNET_USE_LAPACK=1)
  endif()
endif()
為
# ---[ LAPack
if(USE_LAPACK)
  add_definitions(-DMXNET_USE_LAPACK=1)
  list(APPEND mxnet_LINKER_LIBS lapack)
else(USE_LAPACK)
  # Workaround for Windows until using new Jenkinsfile.
  # if(BLAS STREQUAL "Open" OR BLAS STREQUAL "open")
  #   add_definitions(-DMXNET_USE_LAPACK=1)
  # endif()
endif()

# 這裡遮蔽add_definitions(-DMXNET_USE_LAPACK=1)是因為這裡的新增是Windows專用的,針對Linux需要遮蔽

修改tests/CmakeLists.txt

修改
if(NOT MSVC)
  set(UNITTEST_STATIC_LINK ON)
endif()
為
if(NOT MSVC)
  set(UNITTEST_STATIC_LINK OFF)
endif()

修改
if(UNITTEST_STATIC_LINK)
    target_link_libraries(${PROJECT_NAME}_unit_tests
      ${GTEST_LIBRARY}
      ${BEGIN_WHOLE_ARCHIVE} mxnet ${END_WHOLE_ARCHIVE}
      dmlc
      ${mxnet_LINKER_LIBS}
      ${pslite_LINKER_LIBS}
      )
  else()
    target_link_libraries(${PROJECT_NAME}_unit_tests
      ${GTEST_LIBRARY}
      dmlc
      ${nnvm_LINKER_LIBS}
      ${mxnet_LINKER_LIBS}
      mxnet
      ${pslite_LINKER_LIBS}
      )
  endif()
為
if(UNITTEST_STATIC_LINK)
    target_link_libraries(${PROJECT_NAME}_unit_tests
      ${GTEST_LIBRARY}
      ${BEGIN_WHOLE_ARCHIVE} mxnet ${END_WHOLE_ARCHIVE}
      dmlc
      ${mxnet_LINKER_LIBS}
      ${pslite_LINKER_LIBS}
      )
  else()
    target_link_libraries(${PROJECT_NAME}_unit_tests
      ${GTEST_LIBRARY}
      dmlc
      ${nnvm_LINKER_LIBS}
      ${mxnet_LINKER_LIBS}
      mxnet
      ${pslite_LINKER_LIBS}
      rt
      )
  endif()

新建cmake Build目錄

cd incubator-mxnet
mkdir _install

開啟cmake-gui進行交叉編譯鏈配置

注意:mxnet要求cmake版本需要高於3.0.2

這裡寫圖片描述

選擇Specify options for cross-compiling,進入交叉編譯鏈設定介面

這裡寫圖片描述

# 設定交叉編譯相關引數
# 本文使用的是NVIDIA提供的交叉工具鏈,存放位置為/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/
# (更改為你正在使用的目錄)
# 設定Operating System 為 arm-linux 
# 設定C編譯器為 /opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-gcc
# (更改為你正在使用的gcc)
# 設定C++編譯器為 /opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-g++ 
# 設定System Root 為 /opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/arm-linux-gnueabihf/sysroot

點選Configure生成配置選項,並且開啟Advancd選項

這裡寫圖片描述

此時Cmake會顯示CUDA錯誤,暫時先不用管,後面修改設定後錯誤會消失

修改設定選項:

# 去掉勾選為FLASE 勾選為TRUE
USE_CUDA                          # FALSE   
USE_CUDNN                         # FALSE
USE_GPERFTOOLS                    # FALSE
USE_JEMALLOC                      # FALSE
USE_LAPACK                        # FALSE
USE_OPENCV                        # FALSE
USE_OPENMP                        # TRUE 多核ARM建議開啟openmp

點選Configure

再次修改設定選項:

# 指定安裝型別和目錄
CMAKE_BUILD_TYPE                  Release
CMAKE_INSTALL_PREFIX              /usr/local/H8/mxnet-20180122

CMAKE_C_FLAGS                     -mfpu=neon -march=armv7-a
CMAKE_CXX_FLAGS                   -mfpu=neon -march=armv7-a
BLAS                              Open
# 指定OpenBLAS標頭檔案和庫檔案路徑(填寫之前交叉編譯OpenBLAS的安裝目錄)
OpenBLAS_INCLUDE_DIR              /usr/local/H8/openBLAS-0.2.20/include
OpenBLAS_LIBRARY                  /usr/local/H8/openBLAS-0.2.20/lib/libopenblas.so

點選Configure

點選Generate生成Makefile

進入_install目錄&編譯

cd _install
make -j8 
make install

檢視libmxnet.so的依賴庫

arm-linux-gnueabihf-readelf -d /usr/local/H8/mxnet-20180122/lib/libmxnet.so
Dynamic section at offset 0x13fde68 contains 33 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libopenblas.so.0]
 0x00000001 (NEEDED)                     Shared library: [3rdparty/openmp/runtime/src/libomp.so]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgomp.so.1]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x00000001 (NEEDED)                     Shared library: [ld-linux-armhf.so.3]

從上面的依賴庫可以看到3rdparty/openmp/runtime/src/libomp.so這個相對路徑,這樣並不利於最終的部署測試

可以嘗試改動Cmake生成的Makefile來解決

修改_install/CMakeFiles/mxnet.dir/link.txt

3rdparty/openmp/runtime/src/libomp.so
修改為-L/usr/local/H8/mxnet-20180122/lib/ -lomp
# /usr/local/H8/mxnet-20180122/lib/ 即是之前的安裝目錄

重新進行一次編譯&安裝

make -j8 
make install