diff --git a/tools/clear_env.sh b/tools/clear_env.sh index ac66914b67c6f8984ac4f5f711691bcff038f13a..cc8a6f00ef0a30fee992c17d23ac0ddf60e335bc 100644 --- a/tools/clear_env.sh +++ b/tools/clear_env.sh @@ -1,8 +1,22 @@ +#!/bin/bash + +Usage() { + echo "Usage: bash tools/clear_env.sh target_soc" +} + +if [ $# -lt 1 ]; then + Usage + exit 1 +fi + CURRENT_DIR=`dirname $0` source ${CURRENT_DIR}/env.sh +TARGET_SOC=$1 +DEVICE_ID=`echo_device_id_by_soc $TARGET_SOC` + if [ x"$TARGET_ABI" != x"host" ]; then - adb shell rm -rf $PHONE_DATA_DIR + adb -s $DEVICE_ID shell rm -rf $PHONE_DATA_DIR || exit 1 fi rm -rf mace/codegen/models diff --git a/tools/env.sh b/tools/env.sh index 0c8720d55ca1a11cad694c4de8697363c7f736a6..254ddd6982b09e5464d5e6762e151520168f2a90 100644 --- a/tools/env.sh +++ b/tools/env.sh @@ -32,3 +32,14 @@ if [ x"$TARGET_ABI" = x"host" ]; then GENERATED_MODEL_LIB_NAME="libgenerated_models.pic.a" fi GENERATED_MODEL_LIB_PATH="bazel-bin/mace/codegen/${GENERATED_MODEL_LIB_NAME}" + +echo_device_id_by_soc() +{ + TARGET_SOC=$1 + for device in `adb devices | grep "^[A-Za-z0-9]\+[[:space:]]\+device$"| cut -f1`; do + device_soc=`adb -s ${device} shell getprop | grep ro.board.platform | cut -d [ -f3 | cut -d ] -f1` + if [ x"$TARGET_SOC" = x"$device_soc" ]; then + echo "$device" + fi + done +} diff --git a/tools/example.yaml b/tools/example.yaml index f55b62e18386bb318bb4ae5b98d40a417019e064..b1fc4154b00bd428fe93dca380fabe983246fcdb 100644 --- a/tools/example.yaml +++ b/tools/example.yaml @@ -2,7 +2,7 @@ # Each yaml file describes a exported library (could be named [target_abi]/libmace-${filename}.a), # which can contains more than one models target_abis: [armeabi-v7a, arm64-v8a] -target_socs: [MSM8953] # target_socs not enabled yet +target_socs: [MSM8953] embed_model_data: 1 vlog_level: 0 models: diff --git a/tools/generate_production_code.sh b/tools/generate_production_code.sh index 2015846cf63cc38ced0f465d24252c1c169787c6..5f3dc346065861e040ed8b14efafd9ee57dd2387 100644 --- a/tools/generate_production_code.sh +++ b/tools/generate_production_code.sh @@ -1,10 +1,10 @@ #!/bin/bash Usage() { - echo "Usage: bash tools/generate_production_code.sh cl_bin_dirs pull_or_not" + echo "Usage: bash tools/generate_production_code.sh target_soc cl_bin_dirs pull_or_not" } -if [ $# -lt 2 ]; then +if [ $# -lt 3 ]; then Usage exit 1 fi @@ -12,16 +12,19 @@ fi CURRENT_DIR=`dirname $0` source ${CURRENT_DIR}/env.sh -CL_BIN_DIRS=$1 -PULL_OR_NOT=$2 +TARGET_SOC=$1 +CL_BIN_DIRS=$2 +PULL_OR_NOT=$3 + +DEVICE_ID=`echo_device_id_by_soc $TARGET_SOC` if [ "$PULL_OR_NOT" = 1 ]; then CL_BIN_DIR=${CL_BIN_DIRS} rm -rf ${CL_BIN_DIR} mkdir -p ${CL_BIN_DIR} if [ x"$TARGET_ABI" != x"host" ]; then - adb pull ${KERNEL_DIR}/. ${CL_BIN_DIR} > /dev/null - adb pull ${PHONE_DATA_DIR}/mace_run.config ${CL_BIN_DIR} > /dev/null + adb -s $DEVICE_ID pull ${KERNEL_DIR}/. ${CL_BIN_DIR} > /dev/null || exit 1 + adb -s $DEVICE_ID pull ${PHONE_DATA_DIR}/mace_run.config ${CL_BIN_DIR} > /dev/null || exit 1 fi fi diff --git a/tools/mace_tools.py b/tools/mace_tools.py index 0aa67f9506e543e118a1879b3cefa91c1c8a6404..156f8b501735dbe590ed03fede580381b64c0f21 100644 --- a/tools/mace_tools.py +++ b/tools/mace_tools.py @@ -57,15 +57,15 @@ def generate_opencl_and_version_code(): run_command(command) -def clear_env(): - command = "bash tools/clear_env.sh" +def clear_env(target_soc): + command = "bash tools/clear_env.sh {}".format(target_soc) run_command(command) -def generate_random_input(model_output_dir): +def generate_random_input(target_soc, model_output_dir): generate_data_or_not = True - command = "bash tools/validate_tools.sh {} {}".format( - model_output_dir, int(generate_data_or_not)) + command = "bash tools/validate_tools.sh {} {} {}".format( + target_soc, model_output_dir, int(generate_data_or_not)) run_command(command) @@ -80,10 +80,10 @@ def build_mace_run(production_mode, model_output_dir, hexagon_mode): run_command(command) -def tuning_run(model_output_dir, running_round, tuning, production_mode, +def tuning_run(target_soc, model_output_dir, running_round, tuning, production_mode, restart_round, option_args=''): - command = "bash tools/tuning_run.sh {} {} {} {} {} \"{}\"".format( - model_output_dir, running_round, int(tuning), int(production_mode), + command = "bash tools/tuning_run.sh {} {} {} {} {} {} \"{}\"".format( + target_soc, model_output_dir, running_round, int(tuning), int(production_mode), restart_round, option_args) run_command(command) @@ -93,22 +93,22 @@ def benchmark_model(model_output_dir, option_args=''): run_command(command) -def run_model(model_output_dir, running_round, restart_round, option_args): - tuning_run(model_output_dir, running_round, False, False, restart_round, +def run_model(target_soc, model_output_dir, running_round, restart_round, option_args): + tuning_run(target_soc, model_output_dir, running_round, False, False, restart_round, option_args) -def generate_production_code(model_output_dirs, pull_or_not): +def generate_production_code(target_soc, model_output_dirs, pull_or_not): cl_bin_dirs = [] for d in model_output_dirs: cl_bin_dirs.append(os.path.join(d, "opencl_bin")) cl_bin_dirs_str = ",".join(cl_bin_dirs) - command = "bash tools/generate_production_code.sh {} {}".format( - cl_bin_dirs_str, int(pull_or_not)) + command = "bash tools/generate_production_code.sh {} {} {}".format( + target_soc, cl_bin_dirs_str, int(pull_or_not)) run_command(command) -def build_mace_run_prod(model_output_dir, tuning, global_runtime): +def build_mace_run_prod(target_soc, model_output_dir, tuning, global_runtime): if "dsp" == global_runtime: hexagon_mode = True else: @@ -117,6 +117,7 @@ def build_mace_run_prod(model_output_dir, tuning, global_runtime): production_or_not = False build_mace_run(production_or_not, model_output_dir, hexagon_mode) tuning_run( + target_soc, model_output_dir, running_round=0, tuning=tuning, @@ -125,7 +126,7 @@ def build_mace_run_prod(model_output_dir, tuning, global_runtime): production_or_not = True pull_or_not = True - generate_production_code([model_output_dir], pull_or_not) + generate_production_code(target_soc, [model_output_dir], pull_or_not) build_mace_run(production_or_not, model_output_dir, hexagon_mode) @@ -147,13 +148,13 @@ def build_production_code(): run_command(command) -def merge_libs_and_tuning_results(output_dir, model_output_dirs): +def merge_libs_and_tuning_results(target_soc, output_dir, model_output_dirs): pull_or_not = False - generate_production_code(model_output_dirs, pull_or_not) + generate_production_code(target_soc, model_output_dirs, pull_or_not) build_production_code() model_output_dirs_str = ",".join(model_output_dirs) - command = "bash tools/merge_libs.sh {} {}".format(output_dir, + command = "bash tools/merge_libs.sh {} {} {}".format(target_soc, output_dir, model_output_dirs_str) run_command(command) @@ -191,13 +192,6 @@ def parse_args(): def main(unused_args): configs = parse_model_configs() - if FLAGS.mode == "build" or FLAGS.mode == "all": - # Remove previous output dirs - if not os.path.exists(FLAGS.output_dir): - os.makedirs(FLAGS.output_dir) - elif os.path.exists(os.path.join(FLAGS.output_dir, "libmace")): - shutil.rmtree(os.path.join(FLAGS.output_dir, "libmace")) - if FLAGS.mode == "validate": FLAGS.round = 1 FLAGS.restart_round = 1 @@ -206,79 +200,88 @@ def main(unused_args): os.environ["VLOG_LEVEL"] = str(configs["vlog_level"]) os.environ["PROJECT_NAME"] = os.path.splitext(os.path.basename(FLAGS.config))[0] + if FLAGS.mode == "build" or FLAGS.mode == "all": + # Remove previous output dirs + if not os.path.exists(FLAGS.output_dir): + os.makedirs(FLAGS.output_dir) + elif os.path.exists(os.path.join(FLAGS.output_dir, "libmace")): + shutil.rmtree(os.path.join(FLAGS.output_dir, os.environ["PROJECT_NAME"])) + os.makedirs(os.path.join(FLAGS.output_dir, os.environ["PROJECT_NAME"])) + generate_opencl_and_version_code() option_args = ' '.join([arg for arg in unused_args if arg.startswith('--')]) for target_abi in configs["target_abis"]: - global_runtime = get_global_runtime(configs) - # Transfer params by environment - os.environ["TARGET_ABI"] = target_abi - model_output_dirs = [] - for model_name in configs["models"]: + for target_soc in configs["target_socs"]: + global_runtime = get_global_runtime(configs) # Transfer params by environment - os.environ["MODEL_TAG"] = model_name - print '=======================', model_name, '=======================' - model_config = configs["models"][model_name] - for key in model_config: - if key in ['input_nodes', 'output_nodes'] and isinstance(model_config[key], list): - os.environ[key.upper()] = ",".join(model_config[key]) - elif key in ['input_shapes', 'output_shapes'] and isinstance(model_config[key], list): - os.environ[key.upper()] = ":".join(model_config[key]) - else: - os.environ[key.upper()] = str(model_config[key]) - - md5 = hashlib.md5() - md5.update(model_config["model_file_path"]) - model_path_digest = md5.hexdigest() - model_output_dir = "%s/%s/%s/%s" % (FLAGS.output_dir, model_name, model_path_digest, target_abi) - model_output_dirs.append(model_output_dir) - - if FLAGS.mode == "build" or FLAGS.mode == "all": - if os.path.exists(model_output_dir): - shutil.rmtree(model_output_dir) - os.makedirs(model_output_dir) - clear_env() - - # Support http:// and https:// - if model_config["model_file_path"].startswith( - "http://") or model_config["model_file_path"].startswith("https://"): - os.environ["MODEL_FILE_PATH"] = model_output_dir + "/model.pb" - urllib.urlretrieve(model_config["model_file_path"], os.environ["MODEL_FILE_PATH"]) - - if model_config["platform"] == "caffe" and (model_config["weight_file_path"].startswith( - "http://") or model_config["weight_file_path"].startswith("https://")): - os.environ["WEIGHT_FILE_PATH"] = model_output_dir + "/model.caffemodel" - urllib.urlretrieve(model_config["weight_file_path"], os.environ["WEIGHT_FILE_PATH"]) - - if FLAGS.mode == "build" or FLAGS.mode == "run" or FLAGS.mode == "validate"\ - or FLAGS.mode == "benchmark" or FLAGS.mode == "all": - generate_random_input(model_output_dir) - - if FLAGS.mode == "build" or FLAGS.mode == "all": - generate_model_code() - build_mace_run_prod(model_output_dir, FLAGS.tuning, global_runtime) - - if FLAGS.mode == "run" or FLAGS.mode == "validate" or FLAGS.mode == "all": - run_model(model_output_dir, FLAGS.round, FLAGS.restart_round, option_args) - - if FLAGS.mode == "benchmark": - benchmark_model(model_output_dir, option_args) - - if FLAGS.mode == "validate" or FLAGS.mode == "all": - validate_model(model_output_dir) - - if FLAGS.mode == "build" or FLAGS.mode == "merge" or FLAGS.mode == "all": - merge_libs_and_tuning_results(FLAGS.output_dir + "/" + target_abi, - model_output_dirs) - - if FLAGS.mode == "throughput_test": - merged_lib_file = FLAGS.output_dir + "/%s/libmace/lib/libmace_%s.a" % \ - (configs["target_abis"][0], os.environ["PROJECT_NAME"]) - generate_random_input(FLAGS.output_dir) - for model_name in configs["models"]: - runtime = configs["models"][model_name]["runtime"] - os.environ["%s_MODEL_TAG" % runtime.upper()] = model_name - build_run_throughput_test(FLAGS.run_seconds, merged_lib_file, FLAGS.output_dir) + os.environ["TARGET_ABI"] = target_abi + model_output_dirs = [] + for model_name in configs["models"]: + # Transfer params by environment + os.environ["MODEL_TAG"] = model_name + print '=======================', model_name, '=======================' + model_config = configs["models"][model_name] + for key in model_config: + if key in ['input_nodes', 'output_nodes'] and isinstance(model_config[key], list): + os.environ[key.upper()] = ",".join(model_config[key]) + elif key in ['input_shapes', 'output_shapes'] and isinstance(model_config[key], list): + os.environ[key.upper()] = ":".join(model_config[key]) + else: + os.environ[key.upper()] = str(model_config[key]) + + md5 = hashlib.md5() + md5.update(model_config["model_file_path"]) + model_path_digest = md5.hexdigest() + model_output_dir = "%s/%s/%s/%s/%s" % (FLAGS.output_dir, model_name, model_path_digest, target_soc, target_abi) + model_output_dirs.append(model_output_dir) + + if FLAGS.mode == "build" or FLAGS.mode == "all": + if os.path.exists(model_output_dir): + shutil.rmtree(model_output_dir) + os.makedirs(model_output_dir) + clear_env(target_soc) + + # Support http:// and https:// + if model_config["model_file_path"].startswith( + "http://") or model_config["model_file_path"].startswith("https://"): + os.environ["MODEL_FILE_PATH"] = model_output_dir + "/model.pb" + urllib.urlretrieve(model_config["model_file_path"], os.environ["MODEL_FILE_PATH"]) + + if model_config["platform"] == "caffe" and (model_config["weight_file_path"].startswith( + "http://") or model_config["weight_file_path"].startswith("https://")): + os.environ["WEIGHT_FILE_PATH"] = model_output_dir + "/model.caffemodel" + urllib.urlretrieve(model_config["weight_file_path"], os.environ["WEIGHT_FILE_PATH"]) + + if FLAGS.mode == "build" or FLAGS.mode == "run" or FLAGS.mode == "validate"\ + or FLAGS.mode == "benchmark" or FLAGS.mode == "all": + generate_random_input(target_soc, model_output_dir) + + if FLAGS.mode == "build" or FLAGS.mode == "all": + generate_model_code() + build_mace_run_prod(target_soc, model_output_dir, FLAGS.tuning, global_runtime) + + if FLAGS.mode == "run" or FLAGS.mode == "validate" or FLAGS.mode == "all": + run_model(target_soc, model_output_dir, FLAGS.round, FLAGS.restart_round) + + if FLAGS.mode == "benchmark": + benchmark_model(model_output_dir) + + if FLAGS.mode == "validate" or FLAGS.mode == "all": + validate_model(model_output_dir) + + if FLAGS.mode == "build" or FLAGS.mode == "merge" or FLAGS.mode == "all": + merge_libs_and_tuning_results(target_soc, FLAGS.output_dir + "/" + os.environ["PROJECT_NAME"], + model_output_dirs) + + if FLAGS.mode == "throughput_test": + merged_lib_file = FLAGS.output_dir + "/%s/libmace/lib/libmace_%s.a" % \ + (configs["target_abis"][0], os.environ["PROJECT_NAME"]) + generate_random_input(target_soc, FLAGS.output_dir) + for model_name in configs["models"]: + runtime = configs["models"][model_name]["runtime"] + os.environ["%s_MODEL_TAG" % runtime.upper()] = model_name + build_run_throughput_test(FLAGS.run_seconds, merged_lib_file, FLAGS.output_dir) if __name__ == "__main__": diff --git a/tools/merge_libs.sh b/tools/merge_libs.sh index 3e6bb80b67806781977a5c111f9f08114420e844..a2b02cd680ee695944f94dcab59b654b3719538f 100644 --- a/tools/merge_libs.sh +++ b/tools/merge_libs.sh @@ -1,10 +1,10 @@ #!/bin/bash Usage() { - echo "Usage: bash tools/merge_libs.sh libmace_output_dir model_output_dirs" + echo "Usage: bash tools/merge_libs.sh target_soc libmace_output_dir model_output_dirs" } -if [ $# -lt 2 ]; then +if [ $# -lt 3 ]; then Usage exit 1 fi @@ -12,23 +12,33 @@ fi CURRENT_DIR=`dirname $0` source ${CURRENT_DIR}/env.sh -LIBMACE_BUILD_DIR=$1 -MODEL_OUTPUT_DIRS=$2 +TARGET_SOC=$1 +LIBMACE_BUILD_DIR=$2 +MODEL_OUTPUT_DIRS=$3 MODEL_OUTPUT_DIRS_ARR=(${MODEL_OUTPUT_DIRS//,/ }) -MODEL_HEADER_DIR=${LIBMACE_BUILD_DIR}/libmace/include/mace/public -MODEL_DATA_DIR=${LIBMACE_BUILD_DIR}/libmace/data +MODEL_HEADER_DIR=${LIBMACE_BUILD_DIR}/include/mace/public +MODEL_DATA_DIR=${LIBMACE_BUILD_DIR}/data -rm -rf ${LIBMACE_BUILD_DIR}/libmace -mkdir -p ${LIBMACE_BUILD_DIR}/libmace/include/mace/public -mkdir -p ${LIBMACE_BUILD_DIR}/libmace/lib -mkdir -p ${MODEL_DATA_DIR} -cp -rf ${MACE_SOURCE_DIR}/mace/public/*.h ${LIBMACE_BUILD_DIR}/libmace/include/mace/public/ -cp ${MACE_SOURCE_DIR}/mace/core/runtime/hexagon/libhexagon_controller.so ${LIBMACE_BUILD_DIR}/libmace/lib +if [ ! -d "${MODEL_HEADER_DIR}" ]; then + mkdir -p ${MODEL_HEADER_DIR} +fi +if [ ! -d "${LIBMACE_BUILD_DIR}/${TARGET_ABI}" ]; then + mkdir -p ${LIBMACE_BUILD_DIR}/${TARGET_ABI} +fi +if [ ! -d "${LIBMACE_BUILD_DIR}/hexagon" ]; then + mkdir -p ${LIBMACE_BUILD_DIR}/hexagon +fi +if [ ! -d "${MODEL_DATA_DIR}" ]; then + mkdir -p ${MODEL_DATA_DIR} +fi + +cp -rf ${MACE_SOURCE_DIR}/mace/public/*.h ${LIBMACE_BUILD_DIR}/include/mace/public/ +cp ${MACE_SOURCE_DIR}/mace/core/runtime/hexagon/libhexagon_controller.so ${LIBMACE_BUILD_DIR}/hexagon/ LIBMACE_TEMP_DIR=`mktemp -d -t libmace.XXXX` # Merge all libraries in to one -echo "create ${LIBMACE_BUILD_DIR}/libmace/lib/libmace_${PROJECT_NAME}.a" > ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri +echo "create ${LIBMACE_BUILD_DIR}/${TARGET_ABI}/libmace_${PROJECT_NAME}.${TARGET_SOC}.a" > ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri if [ x"$TARGET_ABI" = x"host" ]; then echo "addlib bazel-bin/mace/codegen/libgenerated_opencl_prod.pic.a" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri diff --git a/tools/tuning_run.sh b/tools/tuning_run.sh index 4cc2b4182725561d3e9d16860df6f68bfdb72203..63897941be33ba67688017320ff30693202fe1ac 100644 --- a/tools/tuning_run.sh +++ b/tools/tuning_run.sh @@ -1,10 +1,10 @@ #!/bin/bash Usage() { - echo "Usage: bash tools/tuning_run.sh model_output_dir round tuning production_mode" + echo "Usage: bash tools/tuning_run.sh target_soc model_output_dir round tuning production_mode" } -if [ $# -lt 4 ]; then +if [ $# -lt 7 ]; then Usage exit 1 fi @@ -12,15 +12,18 @@ fi CURRENT_DIR=`dirname $0` source ${CURRENT_DIR}/env.sh -MODEL_OUTPUT_DIR=$1 -ROUND=$2 -TUNING_OR_NOT=$3 -PRODUCTION_MODE=$4 -RESTART_ROUND=$5 -OPTION_ARGS=$6 +TARGET_SOC=$1 +MODEL_OUTPUT_DIR=$2 +ROUND=$3 +TUNING_OR_NOT=$4 +PRODUCTION_MODE=$5 +RESTART_ROUND=$6 +OPTION_ARGS=$7 echo $OPTION_ARGS +DEVICE_ID=`echo_device_id_by_soc $TARGET_SOC` + if [ x"$TARGET_ABI" = x"host" ]; then MACE_CPP_MIN_VLOG_LEVEL=$VLOG_LEVEL \ ${MODEL_OUTPUT_DIR}/mace_run \ @@ -42,22 +45,22 @@ else tuning_flag=0 fi - adb shell "mkdir -p ${PHONE_DATA_DIR}" || exit 1 + adb -s $DEVICE_ID shell "mkdir -p ${PHONE_DATA_DIR}" || exit 1 if [ "$PRODUCTION_MODE" = 0 ]; then - adb shell "mkdir -p ${KERNEL_DIR}" || exit 1 + adb -s $DEVICE_ID shell "mkdir -p ${KERNEL_DIR}" || exit 1 fi IFS=',' read -r -a INPUT_NAMES <<< "${INPUT_NODES}" for NAME in "${INPUT_NAMES[@]}";do FORMATTED_NAME=$(sed s/[^[:alnum:]]/_/g <<< ${NAME}) - adb push ${MODEL_OUTPUT_DIR}/${INPUT_FILE_NAME}_${FORMATTED_NAME} ${PHONE_DATA_DIR} > /dev/null || exit 1 + adb -s $DEVICE_ID push ${MODEL_OUTPUT_DIR}/${INPUT_FILE_NAME}_${FORMATTED_NAME} ${PHONE_DATA_DIR} > /dev/null || exit 1 done - adb /dev/null || exit 1 + adb -s $DEVICE_ID /dev/null || exit 1 if [ "$EMBED_MODEL_DATA" = 0 ]; then - adb push ${MODEL_OUTPUT_DIR}/${MODEL_TAG}.data ${PHONE_DATA_DIR} > /dev/null || exit 1 + adb -s $DEVICE_ID push ${MODEL_OUTPUT_DIR}/${MODEL_TAG}.data ${PHONE_DATA_DIR} > /dev/null || exit 1 fi - adb push mace/core/runtime/hexagon/libhexagon_controller.so ${PHONE_DATA_DIR} > /dev/null || exit 1 + adb -s $DEVICE_ID push mace/core/runtime/hexagon/libhexagon_controller.so ${PHONE_DATA_DIR} > /dev/null || exit 1 ADB_CMD_STR="LD_LIBRARY_PATH=${PHONE_DATA_DIR} \ MACE_TUNING=${tuning_flag} \ @@ -78,11 +81,11 @@ else --restart_round=$RESTART_ROUND \ $OPTION_ARGS; echo \\$?" echo $ADB_CMD_STR - mace_adb_output=`adb /dev/null + adb -s $DEVICE_ID pull ${PHONE_DATA_DIR}/${OUTPUT_FILE_NAME}_${FORMATTED_NAME} ${MODEL_OUTPUT_DIR} > /dev/null || exit 1 done fi python -u tools/validate.py --platform=tensorflow \ @@ -77,7 +80,7 @@ elif [ "$PLATFORM" == "caffe" ];then for NAME in "${OUTPUT_NAMES[@]}";do FORMATTED_NAME=$(sed s/[^[:alnum:]]/_/g <<< ${NAME}) rm -rf ${MODEL_OUTPUT_DIR}/${OUTPUT_FILE_NAME}_${FORMATTED_NAME} - adb pull ${PHONE_DATA_DIR}/${OUTPUT_FILE_NAME}_${FORMATTED_NAME} ${MODEL_OUTPUT_DIR} > /dev/null + adb -s $DEVICE_ID pull ${PHONE_DATA_DIR}/${OUTPUT_FILE_NAME}_${FORMATTED_NAME} ${MODEL_OUTPUT_DIR} > /dev/null || exit 1 done fi for NAME in "${OUTPUT_NAMES[@]}";do