From 6efe5f46b125fec5948f7496ef7a7529a998d23c Mon Sep 17 00:00:00 2001 From: Wenbo Yang Date: Mon, 6 Feb 2017 23:18:11 +0800 Subject: [PATCH] Add Android cross compile script. --- CMakeLists.txt | 14 +-- README.md | 10 ++- cmake/{ => Modules}/FindAtlas.cmake | 0 cmake/{ => Modules}/FindOpenBLAS.cmake | 0 src/caffe/util/math_functions.cpp | 20 +++-- third_party/build-openblas.sh | 114 +++++++++++++++++++++++++ 6 files changed, 141 insertions(+), 17 deletions(-) rename cmake/{ => Modules}/FindAtlas.cmake (100%) mode change 100755 => 100644 rename cmake/{ => Modules}/FindOpenBLAS.cmake (100%) mode change 100755 => 100644 create mode 100755 third_party/build-openblas.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 82d8400..a4920c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,20 +27,20 @@ if(NOT MSVC) endif() endif() -# Set protobuf search path for different platform -if(CMAKE_PREFIX_PATH AND NOT IOS) +# Set search path for cross compile +if(THIRD_PARTY) set(SAVE_PATH ${CMAKE_FIND_ROOT_PATH}) - set(CMAKE_FIND_ROOT_PATH ${CMAKE_PREFIX_PATH}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SOURCE_DIR}/third_party/protobuf ${CMAKE_SOURCE_DIR}/third_party/OpenBLAS) include(./cmake/ProtoBuf.cmake) + include(./cmake/Modules/FindOpenBLAS.cmake) set(CMAKE_FIND_ROOT_PATH ${SAVE_PATH}) else() include(./cmake/ProtoBuf.cmake) + include(./cmake/Modules/FindOpenBLAS.cmake) endif() - -# Select blas lib for different platform include(./cmake/Modules/FindvecLib.cmake) -include(./cmake/FindOpenBLAS.cmake) -include(./cmake/FindAtlas.cmake) +include(./cmake/Modules/FindAtlas.cmake) +# Select blas lib for different platform # APPLE only, 1st if(VECLIB_FOUND) include_directories(${vecLib_INCLUDE_DIR}) diff --git a/README.md b/README.md index 90fed9f..99e4d14 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ $ ./build-protobuf-3.1.0.sh iPhoneSimulator $ mkdir ../build $ cd ../build $ cmake .. -DCMAKE_TOOLCHAIN_FILE=../third_party/ios-cmake/toolchain/iOS.cmake \ - -DIOS_PLATFORM=SIMULATOR -DCMAKE_PREFIX_PATH=$PWD/../third_party/protobuf + -DIOS_PLATFORM=SIMULATOR -DTHIRD_PARTY=1 $ make -j 4 ``` @@ -24,8 +24,10 @@ $ make -j 4 Follow the instructions in [Training LeNet on MNIST with Caffe](http://caffe.berkeleyvision.org/gathered/examples/mnist.html) to train your LeNet Model on MNIST. Then copy the model file `caffe/examples/mnist/lenet.prototxt` and the trained weight file `caffe/examples/mnist/lenet_iter_10000.caffemodel` to CaffeSimple app directory. ``` -$ cp $CAFFE/examples/mnist/lenet.prototxt $CAFFE_MOBILE/examples/ios/simple/CaffeSimple/data/net.prototxt -$ cp $CAFFE/examples/mnist/lenet_iter_10000.caffemodel $CAFFE_MOBILE/examples/ios/simple/CaffeSimple/data/weight.caffemodel +$ cp $CAFFE/examples/mnist/lenet.prototxt \ + $CAFFE_MOBILE/examples/ios/simple/CaffeSimple/data/net.prototxt +$ cp $CAFFE/examples/mnist/lenet_iter_10000.caffemodel \ + $CAFFE_MOBILE/examples/ios/simple/CaffeSimple/data/weight.caffemodel ``` - Load the Xcode project inside the `$CAFFE_MOBILE/examples/ios/simple/` folder, and press Command-R to build and run it on the simulator. @@ -41,7 +43,7 @@ $ ./build-protobuf-3.1.0.sh iPhoneOS $ mkdir ../build $ cd ../build $ cmake .. -DCMAKE_TOOLCHAIN_FILE=../third_party/ios-cmake/toolchain/iOS.cmake \ - -DIOS_PLATFORM=OS -DCMAKE_PREFIX_PATH=$PWD/../third_party/protobuf + -DIOS_PLATFORM=OS -DTHIRD_PARTY=1 $ make -j 4 ``` diff --git a/cmake/FindAtlas.cmake b/cmake/Modules/FindAtlas.cmake old mode 100755 new mode 100644 similarity index 100% rename from cmake/FindAtlas.cmake rename to cmake/Modules/FindAtlas.cmake diff --git a/cmake/FindOpenBLAS.cmake b/cmake/Modules/FindOpenBLAS.cmake old mode 100755 new mode 100644 similarity index 100% rename from cmake/FindOpenBLAS.cmake rename to cmake/Modules/FindOpenBLAS.cmake diff --git a/src/caffe/util/math_functions.cpp b/src/caffe/util/math_functions.cpp index 77a0cd9..66e5c98 100644 --- a/src/caffe/util/math_functions.cpp +++ b/src/caffe/util/math_functions.cpp @@ -1,7 +1,9 @@ #ifdef USE_BOOST #include #include -#endif +#else +#include +#endif // USE_BOOST #include @@ -232,15 +234,11 @@ unsigned int caffe_rng_rand() { return (*caffe_rng())(); } +#ifdef USE_BOOST template Dtype caffe_nextafter(const Dtype b) { -#ifdef USE_BOOST return boost::math::nextafter( b, std::numeric_limits::max()); -#else - return std::nextafter( - b, std::numeric_limits::max()); -#endif } template @@ -248,6 +246,16 @@ float caffe_nextafter(const float b); template double caffe_nextafter(const double b); +#else +// std::nextafter has some problems with tr1 & _GLIBCXX_USE_C99_MATH_TR1 +// when using android ndk +float caffe_nextafter(const float b) { + return ::nextafterf(b, std::numeric_limits::max()); +} +double caffe_nextafter(const double b) { + return ::nextafter(b, std::numeric_limits::max()); +} +#endif template void caffe_rng_uniform(const int n, const Dtype a, const Dtype b, Dtype* r) { diff --git a/third_party/build-openblas.sh b/third_party/build-openblas.sh new file mode 100755 index 0000000..4790005 --- /dev/null +++ b/third_party/build-openblas.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +PLATFORM=Android + +# Options for All +OPENBLAS_VERSION=0.2.19 +MAKE_FLAGS="$MAKE_FLAGS -j 4" +BUILD_DIR=".cbuild" + +# Options for Android +ANDROID_NDK=/opt/android-ndk-r13b +ANDROID_NATIVE_API_LEVEL=21 +ANDROID_ABI="armeabi-v7a with NEON" +ANDROID_ABI="arm64-v8a" + +# Build Environment +if [ "$(uname)" = "Darwin" ]; then + OS=darwin +elif [ "$(expr substr $(uname -s) 1 5)" = "Linux" ]; then + OS=linux +elif [ "$(expr substr $(uname -s) 1 10)" = "MINGW32_NT" || + "$(expr substr $(uname -s) 1 9)" = "CYGWIN_NT" ]; then + OS=windows +else + echo "Unknown OS" + exit 1 +fi + +if [ "$(uname -m)" = "x86_64" ]; then + BIT=x86_64 +else + BIT=x86 +fi + +echo "$(tput setaf 2)" +echo Building Openblas for $PLATFORM +echo "$(tput sgr0)" + +RUN_DIR=$PWD + +function fetch-OpenBLAS { + echo "$(tput setaf 2)" + echo "##########################################" + echo " Fetch Openblas $OPENBLAS_VERSION from source." + echo "##########################################" + echo "$(tput sgr0)" + + if [ ! -f OpenBLAS-${OPENBLAS_VERSION}.tar.gz ]; then + curl -L https://github.com/xianyi/OpenBLAS/archive/v${OPENBLAS_VERSION}.tar.gz --output OpenBLAS-${OPENBLAS_VERSION}.tar.gz + fi + if [ -d OpenBLAS-${OPENBLAS_VERSION} ]; then + rm -rf OpenBLAS-${OPENBLAS_VERSION} + fi + tar -xzf OpenBLAS-${OPENBLAS_VERSION}.tar.gz +} + +function build-Android { + echo "$(tput setaf 2)" + echo "#####################" + echo " Building OpenBLAS for $PLATFORM" + echo "#####################" + echo "$(tput sgr0)" + + if [ "${ANDROID_ABI}" = "armeabi-v7a with NEON" ]; then + CROSS_SUFFIX=$ANDROID_NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/${OS}-${BIT}/bin/arm-linux-androideabi- + SYSROOT=$ANDROID_NDK/platforms/android-$ANDROID_NATIVE_API_LEVEL/arch-arm + TARGET=ARMV7 + BINARY=32 + elif [ "${ANDROID_ABI}" = "arm64-v8a" ]; then + CROSS_SUFFIX=$ANDROID_NDK/toolchains/aarch64-linux-android-4.9/prebuilt/${OS}-${BIT}/bin/aarch64-linux-android- + SYSROOT=$ANDROID_NDK/platforms/android-$ANDROID_NATIVE_API_LEVEL/arch-arm64 + TARGET=ARMV8 + BINARY=64 + else + echo "Error: not support OpenBLAS for ABI: ${ANDROID_ABI}" + exit 1 + fi + + mkdir -p OpenBLAS-$TARGET + cd OpenBLAS-$OPENBLAS_VERSION + make ${MAKE_FLAGS} \ + NOFORTRAN=1 \ + NO_NOLAPACKE=1 \ + SMP=1 \ + USE_THREAD=1 \ + NUM_THREAD=4 \ + CROSS_SUFFIX="$CROSS_SUFFIX" \ + CC="${CROSS_SUFFIX}gcc --sysroot=$SYSROOT" \ + HOSTCC=gcc \ + TARGET=$TARGET \ + BINARY=$BINARY \ + PREFIX="../OpenBLAS-$TARGET" + make ${MAKE_FLAGS} \ + NOFORTRAN=1 \ + NO_NOLAPACKE=1 \ + SMP=1 \ + USE_THREAD=1 \ + NUM_THREAD=4 \ + CROSS_SUFFIX="$CROSS_SUFFIX" \ + CC="${CROSS_SUFFIX}gcc --sysroot=$SYSROOT" \ + HOSTCC=gcc \ + TARGET=$TARGET \ + BINARY=$BINARY \ + PREFIX="../OpenBLAS-$TARGET" \ + install + cd .. +} + +ANDROID_ABI="armeabi-v7a with NEON" +fetch-OpenBLAS +build-$PLATFORM +#ANDROID_ABI="arm64-v8a" +#fetch-OpenBLAS +#build-$PLATFORM