#!/usr/bin/env bash # Copyright 2017 The TensorFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== # This is a composite script to build and run inception with hexagon on Android set -e usage() { echo "Usage: QUALCOMM_SDK= NDK_ROOT= $(basename "$0")" echo "Optional: NNLIB_DIR=" echo "-b build only" echo "-c test count" echo "-E enable experimental hexnn ops" echo "-p use prebuilt hexagon binaries" echo "-s skip download if files already exist" exit 1 } TEST_COUNT=1 SKIP_DOWNLOAD_IF_EXIST=false while getopts "bc:Eps" opt_name; do case "$opt_name" in b) BUILD_ONLY="true";; c) TEST_COUNT="${OPTARG}";; E) ENABLE_EXPERIMENTAL_HEXNN_OPS="true";; p) USE_PREBUILT_HEXAGON_BINARIES="true";; s) SKIP_DOWNLOAD_IF_EXIST="true";; *) usage;; esac done shift $((OPTIND - 1)) if [[ -z "${NDK_ROOT}" ]]; then echo "NDK_ROOT is empty" 1>&2 usage exit 1 fi if [[ "${USE_PREBUILT_HEXAGON_BINARIES}" != "true" && -z "${QUALCOMM_SDK}" ]]; then echo "QUALCOMM_SDK is empty" 1>&2 usage exit 1 fi if [[ "${BUILD_ONLY}" != "true" ]]; then if ! type adb >/dev/null 2>&1; then echo "adb is not in your path ${PATH}." exit 1 fi if ! adb shell ls /system/lib/rfsa/adsp/testsig* >/dev/null 2>&1; then echo "test signature not found. Unlock your phone first" echo "See ${QUALCOMM_SDK}/tools/elfsigner/README.txt" exit 1 fi fi SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" TF_ROOT_DIR="$(cd "${SCRIPT_DIR}/../../../.." && pwd)" BUILD_ALL_ANDROID_PATH="${SCRIPT_DIR}/../build_all_android.sh" GEN_DIR="${SCRIPT_DIR}/gen" GEN_LIBS_DIR="${GEN_DIR}/libs" GEN_DOWNLOAD_DIR="${GEN_DIR}/downloads" URL_BASE="https://storage.googleapis.com/download.tensorflow.org" ARCH="armeabi-v7a" source "${SCRIPT_DIR}/../build_helper.subr" rm -rf "${GEN_DIR}" mkdir -p "${GEN_LIBS_DIR}" mkdir -p "${GEN_DOWNLOAD_DIR}" if [[ "${USE_PREBUILT_HEXAGON_BINARIES}" == "true" ]]; then echo "Download prebuilt hexagon binaries" if [[ "${BUILD_ONLY}" != "true" ]]; then CONTROLLER_PUSH_DEST="/data/local/tmp" NN_LIB_PUSH_DEST="/vendor/lib/rfsa/adsp" fi download_and_push "${URL_BASE}/deps/hexagon/libhexagon_controller.so" \ "${GEN_LIBS_DIR}/libhexagon_controller.so" "${CONTROLLER_PUSH_DEST}" \ "${SKIP_DOWNLOAD_IF_EXIST}" download_and_push "${URL_BASE}/deps/hexagon/libhexagon_nn_skel.so" \ "${GEN_LIBS_DIR}/libhexagon_nn_skel.so" "${NN_LIB_PUSH_DEST}" \ "${SKIP_DOWNLOAD_IF_EXIST}" else echo "Build hexagon binaries from source code" cd "${GEN_DIR}" if [[ -z "${NNLIB_DIR}" ]]; then git clone https://source.codeaurora.org/quic/hexagon_nn/nnlib else if [[ ! -f "${NNLIB_DIR}/Makefile" ]]; then echo "Couldn't locate ${NNLIB_DIR}/Makefile" 1>&2 exit 1 fi echo "Use nnlib in ${NNLIB_DIR}" 1>&2 GEN_NNLIB_DIR="${GEN_DIR}/nnlib" mkdir -p "${GEN_NNLIB_DIR}" cp -af "${NNLIB_DIR}/"* "${GEN_NNLIB_DIR}" fi cd "${QUALCOMM_SDK}" source "${QUALCOMM_SDK}/setup_sdk_env.sh" GENERATED_NNLIB_DIRECTORY="${QUALCOMM_SDK}/examples/common/generated_nnlib" if [[ -d "${GENERATED_NNLIB_DIRECTORY}" ]]; then echo "Existing nnlib found. Remove" rm -rf "${GENERATED_NNLIB_DIRECTORY}" fi cp -af "${GEN_DIR}/nnlib" "${GENERATED_NNLIB_DIRECTORY}" cd "${GENERATED_NNLIB_DIRECTORY}" make clean V=hexagon_Release_dynamic_toolv72_v60 rm -rf hexagon_Release_dynamic_toolv72_v60 make tree VERBOSE=1 V=hexagon_Release_dynamic_toolv72_v60 GENERATED_HEXAGON_CONTROLLER_DIRECTORY=\ "${QUALCOMM_SDK}/examples/common/generated_hexagon_controller" if [[ -d "${GENERATED_HEXAGON_CONTROLLER_DIRECTORY}" ]]; then echo "Existing hexagon controller found. Remove" rm -rf "${GENERATED_HEXAGON_CONTROLLER_DIRECTORY}" fi cp -af "${TF_ROOT_DIR}/tensorflow/contrib/hvx/hexagon_controller" \ "${GENERATED_HEXAGON_CONTROLLER_DIRECTORY}" echo "Copy interface directory" cp -afv "${GENERATED_NNLIB_DIRECTORY}/interface" \ "${GENERATED_HEXAGON_CONTROLLER_DIRECTORY}/" echo "Copy glue directory" cp -afv "${GENERATED_NNLIB_DIRECTORY}/glue" \ "${GENERATED_HEXAGON_CONTROLLER_DIRECTORY}/" cd "${GENERATED_HEXAGON_CONTROLLER_DIRECTORY}" make clean V=android_Release rm -rf android_Release make tree VERBOSE=1 V=android_Release cp -v "${GENERATED_HEXAGON_CONTROLLER_DIRECTORY}/android_Release/ship/libhexagon_controller.so" \ "${GEN_LIBS_DIR}" cp -v "${GENERATED_NNLIB_DIRECTORY}/hexagon_Release_dynamic_toolv72_v60/ship/libhexagon_nn_skel.so" \ "${GEN_LIBS_DIR}" fi if [[ -d "${TF_ROOT_DIR}/tensorflow/contrib/makefile/gen/protobuf" && -d "${TF_ROOT_DIR}/tensorflow/contrib/makefile/gen/protobuf-host" ]]; then echo "generated protobuf and protobuf-host found." EXTRA_ARGS+=("-T") fi if [[ "${ENABLE_EXPERIMENTAL_HEXNN_OPS}" == "true" ]]; then EXTRA_ARGS+=("-E") fi if [[ -z "${CC_PREFIX}" ]]; then echo "HINT: Installing ccache and specifying CC_PREFIX=ccache accelerate build time" fi CC_PREFIX=${CC_PREFIX} NDK_ROOT=${NDK_ROOT} "${BUILD_ALL_ANDROID_PATH}" \ -x "${GEN_LIBS_DIR}" \ -s "${TF_ROOT_DIR}/tensorflow/contrib/makefile/sub_makefiles/hexagon_graph_execution/Makefile.in" \ -t "hexagon_graph_execution" ${EXTRA_ARGS[@]} echo "Download and push inception image" HEXAGON_DOWNLOAD_PATH=\ "${TF_ROOT_DIR}/tensorflow/contrib/makefile/downloads/hexagon" rm -rf "${HEXAGON_DOWNLOAD_PATH}" mkdir -p "${HEXAGON_DOWNLOAD_PATH}/libs" if [[ "${BUILD_ONLY}" != "true" ]]; then BIN_PUSH_DEST="/data/local/tmp" fi download_and_push "${URL_BASE}/example_images/img_299x299.bmp" \ "${GEN_DOWNLOAD_DIR}/img_299x299.bmp" "${BIN_PUSH_DEST}" \ "${SKIP_DOWNLOAD_IF_EXIST}" download_and_push \ "${URL_BASE}/models/tensorflow_inception_v3_stripped_optimized_quantized.pb" \ "${GEN_DOWNLOAD_DIR}/tensorflow_inception_v3_stripped_optimized_quantized.pb" \ "${BIN_PUSH_DEST}" \ "${SKIP_DOWNLOAD_IF_EXIST}" download_and_push "${URL_BASE}/models/imagenet_comp_graph_label_strings.txt" \ "${GEN_DOWNLOAD_DIR}/imagenet_comp_graph_label_strings.txt" "${BIN_PUSH_DEST}" \ "${SKIP_DOWNLOAD_IF_EXIST}" # By default this script runs a test to fuse and run the model gtest_args+=("--gtest_filter=GraphTransferer.RunInceptionV3OnHexagonExampleWithTfRuntime") # Uncomment this block if you want to run the fused model #gtest_args+=("--gtest_filter=GraphTransferer.RunInceptionV3OnHexagonExampleWithFusedGraph") # Uncomment this block if you want to run the model with hexagon wrapper #gtest_args+=( # "--gtest_also_run_disabled_tests" # "--gtest_filter=GraphTransferer.DISABLED_RunInceptionV3OnHexagonExampleWithHexagonWrapper") # Uncomment this block if you want to get the list of tests #gtest_args+=("--gtest_list_tests") if [[ "${BUILD_ONLY}" != "true" ]]; then echo "Run hexagon_graph_execution" ANDROID_EXEC_FILE_MODE=755 adb push "${GEN_LIBS_DIR}/libhexagon_controller.so" "/data/local/tmp" adb push "${GEN_LIBS_DIR}/libhexagon_nn_skel.so" "/vendor/lib/rfsa/adsp" adb push -p \ "${TF_ROOT_DIR}/tensorflow/contrib/makefile/gen/bin/android_${ARCH}/hexagon_graph_execution" \ "/data/local/tmp/" adb wait-for-device adb shell chmod "${ANDROID_EXEC_FILE_MODE}" \ "/data/local/tmp/hexagon_graph_execution" adb wait-for-device for i in $(seq 1 "${TEST_COUNT}"); do adb shell 'LD_LIBRARY_PATH=/data/local/tmp:$LD_LIBRARY_PATH' \ "/data/local/tmp/hexagon_graph_execution" ${gtest_args[@]} done fi