From 747e2715ccc949782dcf91a9b89bfa84d3682e74 Mon Sep 17 00:00:00 2001 From: yejianwu Date: Thu, 19 Apr 2018 20:18:24 +0800 Subject: [PATCH] update mace_tools to python sh --- mace/core/file_storage.cc | 2 +- mace/python/tools/binary_codegen.py | 14 + mace/python/tools/caffe_converter_lib.py | 14 + mace/python/tools/convert_util.py | 14 + mace/python/tools/converter.py | 14 + mace/python/tools/dsp_ops.py | 15 + mace/python/tools/encrypt_opencl_codegen.py | 14 + mace/python/tools/graph_util.py | 14 + mace/python/tools/memory_optimizer.py | 14 + mace/python/tools/opencl_codegen.py | 14 + mace/python/tools/source_converter_lib.py | 14 + mace/python/tools/tf_converter_lib.py | 14 + mace/python/tools/tf_dsp_converter_lib.py | 15 + mace/python/tools/tf_ops_stats.py | 14 + tools/bazel_adb_run.py | 17 +- tools/benchmark.sh | 108 --- tools/build_mace_run.sh | 79 -- tools/build_production_code.sh | 43 - tools/build_run_throughput_test.sh | 83 -- tools/clear_env.sh | 28 - tools/env.sh | 52 -- tools/falcon_cli.py | 14 + tools/generate_data.py | 14 + tools/generate_model_code.sh | 29 - tools/generate_opencl_code.sh | 58 -- tools/generate_tuning_param_code.sh | 40 - tools/generate_version_code.sh | 10 - tools/mace_tools.py | 737 ++++++++-------- tools/merge_libs.sh | 77 -- tools/packaging_lib.sh | 26 - tools/sh_commands.py | 891 +++++++++++++++++++- tools/tuning_run.sh | 102 --- tools/validate.py | 14 + tools/validate_tools.sh | 114 --- tools/wino_conv.py | 14 + 35 files changed, 1502 insertions(+), 1234 deletions(-) delete mode 100644 tools/benchmark.sh delete mode 100644 tools/build_mace_run.sh delete mode 100644 tools/build_production_code.sh delete mode 100644 tools/build_run_throughput_test.sh delete mode 100644 tools/clear_env.sh delete mode 100644 tools/env.sh delete mode 100644 tools/generate_model_code.sh delete mode 100644 tools/generate_opencl_code.sh delete mode 100644 tools/generate_tuning_param_code.sh delete mode 100644 tools/generate_version_code.sh delete mode 100644 tools/merge_libs.sh delete mode 100644 tools/packaging_lib.sh delete mode 100644 tools/tuning_run.sh delete mode 100644 tools/validate_tools.sh diff --git a/mace/core/file_storage.cc b/mace/core/file_storage.cc index 5f6f0777..d0ac3d78 100644 --- a/mace/core/file_storage.cc +++ b/mace/core/file_storage.cc @@ -21,9 +21,9 @@ #include #include +#include #include #include -#include #include "mace/utils/logging.h" diff --git a/mace/python/tools/binary_codegen.py b/mace/python/tools/binary_codegen.py index 1bafd5e5..c36941f0 100644 --- a/mace/python/tools/binary_codegen.py +++ b/mace/python/tools/binary_codegen.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + import argparse import os import sys diff --git a/mace/python/tools/caffe_converter_lib.py b/mace/python/tools/caffe_converter_lib.py index cce64c4d..8246c249 100644 --- a/mace/python/tools/caffe_converter_lib.py +++ b/mace/python/tools/caffe_converter_lib.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + from mace.proto import mace_pb2 from mace.proto import caffe_pb2 from mace.python.tools import memory_optimizer diff --git a/mace/python/tools/convert_util.py b/mace/python/tools/convert_util.py index 574e1e58..c4fcba43 100644 --- a/mace/python/tools/convert_util.py +++ b/mace/python/tools/convert_util.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + import tensorflow as tf from mace.proto import mace_pb2 diff --git a/mace/python/tools/converter.py b/mace/python/tools/converter.py index c4592d5a..b14d8912 100644 --- a/mace/python/tools/converter.py +++ b/mace/python/tools/converter.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + import argparse import sys import hashlib diff --git a/mace/python/tools/dsp_ops.py b/mace/python/tools/dsp_ops.py index 72a2f497..f5bd7b70 100644 --- a/mace/python/tools/dsp_ops.py +++ b/mace/python/tools/dsp_ops.py @@ -1,3 +1,18 @@ +# Copyright 2018 Xiaomi, Inc. 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. + + class DspOps(object): def __init__(self): self.dsp_ops = { diff --git a/mace/python/tools/encrypt_opencl_codegen.py b/mace/python/tools/encrypt_opencl_codegen.py index b541aef5..6edf48f3 100644 --- a/mace/python/tools/encrypt_opencl_codegen.py +++ b/mace/python/tools/encrypt_opencl_codegen.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + import argparse import os import sys diff --git a/mace/python/tools/graph_util.py b/mace/python/tools/graph_util.py index 29072ae2..22edb43a 100644 --- a/mace/python/tools/graph_util.py +++ b/mace/python/tools/graph_util.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + import tensorflow as tf from mace.proto import mace_pb2 from collections import OrderedDict diff --git a/mace/python/tools/memory_optimizer.py b/mace/python/tools/memory_optimizer.py index da92448d..4eef9395 100644 --- a/mace/python/tools/memory_optimizer.py +++ b/mace/python/tools/memory_optimizer.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + import sys import operator from mace.proto import mace_pb2 diff --git a/mace/python/tools/opencl_codegen.py b/mace/python/tools/opencl_codegen.py index 061dd25b..3d930768 100644 --- a/mace/python/tools/opencl_codegen.py +++ b/mace/python/tools/opencl_codegen.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + import argparse import os import sys diff --git a/mace/python/tools/source_converter_lib.py b/mace/python/tools/source_converter_lib.py index 3bae0310..404e56b9 100644 --- a/mace/python/tools/source_converter_lib.py +++ b/mace/python/tools/source_converter_lib.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + import os import uuid import numpy as np diff --git a/mace/python/tools/tf_converter_lib.py b/mace/python/tools/tf_converter_lib.py index c50766cb..c1f87781 100644 --- a/mace/python/tools/tf_converter_lib.py +++ b/mace/python/tools/tf_converter_lib.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + from mace.proto import mace_pb2 import tensorflow as tf import numpy as np diff --git a/mace/python/tools/tf_dsp_converter_lib.py b/mace/python/tools/tf_dsp_converter_lib.py index 62269cf0..65369b46 100644 --- a/mace/python/tools/tf_dsp_converter_lib.py +++ b/mace/python/tools/tf_dsp_converter_lib.py @@ -1,3 +1,18 @@ +# Copyright 2018 Xiaomi, Inc. 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. + + from mace.proto import mace_pb2 import tensorflow as tf from tensorflow import gfile diff --git a/mace/python/tools/tf_ops_stats.py b/mace/python/tools/tf_ops_stats.py index 303ec77b..02b82f5c 100644 --- a/mace/python/tools/tf_ops_stats.py +++ b/mace/python/tools/tf_ops_stats.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + import operator import functools import argparse diff --git a/tools/bazel_adb_run.py b/tools/bazel_adb_run.py index e11a72d0..b542f93a 100644 --- a/tools/bazel_adb_run.py +++ b/tools/bazel_adb_run.py @@ -1,4 +1,16 @@ -#!/usr/bin/env python +# Copyright 2018 Xiaomi, Inc. 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. # Must run at root dir of libmace project. # python tools/bazel_adb_run.py \ @@ -103,7 +115,8 @@ def main(unused_args): sh_commands.gen_mace_version() for target_abi in target_abis: - sh_commands.bazel_build(target, abi=target_abi) + sh_commands.bazel_build(target, abi=target_abi, + disable_no_tuning_warning=True) if FLAGS.run_target: for serialno in target_devices: if target_abi not in set( diff --git a/tools/benchmark.sh b/tools/benchmark.sh deleted file mode 100644 index d4d8dcbf..00000000 --- a/tools/benchmark.sh +++ /dev/null @@ -1,108 +0,0 @@ -#!/bin/bash - -Usage() { - echo "Usage: bash tools/benchmark.sh target_soc model_output_dir option_args" -} - -if [ $# -lt 1 ]; then - Usage - exit 1 -fi - -CURRENT_DIR=`dirname $0` -source ${CURRENT_DIR}/env.sh - -TARGET_SOC=$1 -MODEL_OUTPUT_DIR=$2 -OPTION_ARGS=$3 - -echo $OPTION_ARGS - -RESULT_VALUE=`echo_device_id_by_soc $TARGET_SOC` -if [ $? -ne 0 ]; then - echo $RESULT_VALUE - exit 1 -else - DEVICE_ID=$RESULT_VALUE -fi - -if [ -f "$MODEL_OUTPUT_DIR/benchmark_model" ]; then - rm -rf $MODEL_OUTPUT_DIR/benchmark_model -fi - -if [ "$EMBED_MODEL_DATA" = 0 ]; then - cp codegen/models/${MODEL_TAG}/${MODEL_TAG}.data $MODEL_OUTPUT_DIR -fi - -if [ x"$TARGET_ABI" == x"host" ]; then - bazel build --verbose_failures -c opt --strip always \ - //mace/benchmark:benchmark_model \ - --copt="-std=c++11" \ - --copt="-D_GLIBCXX_USE_C99_MATH_TR1" \ - --copt="-Werror=return-type" \ - --copt="-DMACE_MODEL_TAG=${MODEL_TAG}" \ - --copt="-O3" \ - --define openmp=true \ - --define production=true || exit 1 - - cp bazel-bin/benchmark/benchmark_model $MODEL_OUTPUT_DIR - - MACE_CPP_MIN_VLOG_LEVEL=$VLOG_LEVEL \ - ${MODEL_OUTPUT_DIR}/benchmark_model \ - --model_data_file=${PHONE_DATA_DIR}/${MODEL_TAG}.data \ - --device=${DEVICE_TYPE} \ - --input_node="${INPUT_NODES}" \ - --input_shape="${INPUT_SHAPES}"\ - --output_node="${OUTPUT_NODES}" \ - --output_shape="${OUTPUT_SHAPES}"\ - --input_file=${MODEL_OUTPUT_DIR}/${INPUT_FILE_NAME}_${INPUT_NODES} \ - $OPTION_ARGS || exit 1 - -else - bazel build --verbose_failures -c opt --strip always \ - //mace/benchmark:benchmark_model \ - --crosstool_top=//external:android/crosstool \ - --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \ - --cpu=${TARGET_ABI} \ - --copt="-std=c++11" \ - --copt="-D_GLIBCXX_USE_C99_MATH_TR1" \ - --copt="-Werror=return-type" \ - --copt="-DMACE_OBFUSCATE_LITERALS" \ - --copt="-DMACE_MODEL_TAG=${MODEL_TAG}" \ - --define openmp=true \ - --define neon=true \ - --copt="-O3" \ - --define production=true || exit 1 - - cp bazel-bin/mace/benchmark/benchmark_model $MODEL_OUTPUT_DIR - - adb -s $DEVICE_ID shell "mkdir -p ${PHONE_DATA_DIR}" || exit 1 - IFS=',' read -r -a INPUT_NAMES <<< "${INPUT_NODES}" - for NAME in "${INPUT_NAMES[@]}";do - FORMATTED_NAME=$(sed s/[^[:alnum:]]/_/g <<< ${NAME}) - adb -s $DEVICE_ID push ${MODEL_OUTPUT_DIR}/${INPUT_FILE_NAME}_${FORMATTED_NAME} \ - ${PHONE_DATA_DIR} > /dev/null || exit 1 - done - adb -s $DEVICE_ID push ${MODEL_OUTPUT_DIR}/benchmark_model \ - ${PHONE_DATA_DIR} > /dev/null || exit 1 - if [ "$EMBED_MODEL_DATA" = 0 ]; then - adb -s $DEVICE_ID push ${MODEL_OUTPUT_DIR}/${MODEL_TAG}.data \ - ${PHONE_DATA_DIR} > /dev/null || exit 1 - fi - - adb -s $DEVICE_ID /dev/null - fi - fi - - python mace/python/tools/opencl_codegen.py \ - --built_kernel_file_name=${CL_BUILT_KERNEL_FILE_NAME} \ - --platform_info_file_name=${CL_PLATFORM_INFO_FILE_NAME} \ - --cl_binary_dirs=${CL_BIN_DIRS} \ - --output_path=${CL_CODEGEN_DIR}/opencl_compiled_program.cc || exit 1 -fi - diff --git a/tools/generate_tuning_param_code.sh b/tools/generate_tuning_param_code.sh deleted file mode 100644 index 4d116c9f..00000000 --- a/tools/generate_tuning_param_code.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -CURRENT_DIR=`dirname $0` -source ${CURRENT_DIR}/env.sh - -mkdir -p ${TUNING_CODEGEN_DIR} - -if [ "$#" -eq "0" ]; then - python mace/python/tools/binary_codegen.py \ - --binary_file_name=mace_run.config \ - --output_path=${TUNING_CODEGEN_DIR}/tuning_params.cc -else - - TARGET_SOC=$1 - BIN_DIRS=$2 - PULL_OR_NOT=$3 - - RESULT_VALUE=`echo_device_id_by_soc $TARGET_SOC` - if [ $? -ne 0 ]; then - echo $RESULT_VALUE - exit 1 - else - DEVICE_ID=$RESULT_VALUE - fi - - if [ "$PULL_OR_NOT" = 1 ]; then - mkdir -p ${BIN_DIRS} - rm -rf ${BIN_DIRS}/mace_run.config - if [ x"$TARGET_ABI" != x"host" ]; then - adb -s $DEVICE_ID pull ${PHONE_DATA_DIR}/mace_run.config ${BIN_DIRS} > /dev/null - fi - fi - - python mace/python/tools/binary_codegen.py \ - --binary_dirs=${BIN_DIRS} \ - --binary_file_name=mace_run.config \ - --output_path=${TUNING_CODEGEN_DIR}/tuning_params.cc -fi - - diff --git a/tools/generate_version_code.sh b/tools/generate_version_code.sh deleted file mode 100644 index 7b1c33d2..00000000 --- a/tools/generate_version_code.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -CL_KERNEL_DIR_TAG=$1 - -CURRENT_DIR=`dirname $0` -source ${CURRENT_DIR}/env.sh - -rm -rf ${CODEGEN_DIR}/version -mkdir ${CODEGEN_DIR}/version -bash mace/tools/git/gen_version_source.sh ${CODEGEN_DIR}/version/version.cc || exit 1 diff --git a/tools/mace_tools.py b/tools/mace_tools.py index ca418472..ddcf29a5 100644 --- a/tools/mace_tools.py +++ b/tools/mace_tools.py @@ -1,4 +1,16 @@ -#!/usr/bin/env python +# Copyright 2018 Xiaomi, Inc. 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. # Must run at root dir of libmace project. # python tools/mace_tools.py \ @@ -7,10 +19,10 @@ # --mode=all import argparse +import filelock import hashlib import os import sh -import shutil import subprocess import sys import urllib @@ -22,24 +34,50 @@ import sh_commands from ConfigParser import ConfigParser -def run_command(command): - print("Run command: {}".format(command)) - result = subprocess.Popen( - command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out, err = result.communicate() +def get_target_socs(configs): + available_socs = sh_commands.adb_get_all_socs() + target_socs = available_socs + if hasattr(configs, "target_socs"): + target_socs = set(configs["target_socs"]) + target_socs = target_socs & available_socs + + if FLAGS.target_socs != "all": + socs = set(FLAGS.target_socs.split(',')) + target_socs = target_socs & socs + missing_socs = socs.difference(target_socs) + if len(missing_socs) > 0: + print( + "Error: devices with SoCs are not connected %s" % missing_socs) + exit(1) + + if not target_socs: + print("Error: no device to run") + exit(1) + + return target_socs + - if out: - print("Stdout msg:\n{}".format(out)) - if err: - print("Stderr msg:\n{}".format(err)) +def get_data_and_device_type(runtime): + data_type = "" + device_type = "" - if result.returncode != 0: - raise Exception( - "Exit not 0 from bash with code: {}, command: {}".format( - result.returncode, command)) + if runtime == "dsp": + data_type = "DT_UINT8" + device_type = "HEXAGON" + elif runtime == "gpu": + data_type = "DT_HALF" + device_type = "OPENCL" + elif runtime == "cpu": + data_type = "DT_FLOAT" + device_type = "CPU" + elif runtime == "neon": + data_type = "DT_FLOAT" + device_type = "NEON" + return data_type, device_type -def get_global_runtime(configs): + +def get_hexagon_mode(configs): runtime_list = [] for model_name in configs["models"]: model_runtime = configs["models"][model_name]["runtime"] @@ -47,141 +85,29 @@ def get_global_runtime(configs): global_runtime = "" if "dsp" in runtime_list: - global_runtime = "dsp" - elif "gpu" in runtime_list: - global_runtime = "gpu" - elif "cpu" in runtime_list: - global_runtime = "cpu" - elif "neon" in runtime_list: - global_runtime = "neon" - else: - raise Exception("Not found available RUNTIME in config files!") - - return global_runtime - - -def generate_version_code(): - command = "bash tools/generate_version_code.sh" - run_command(command) - - -def generate_opencl_source_code(): - command = "bash tools/generate_opencl_code.sh source" - run_command(command) - - -def generate_opencl_binay_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) - if not cl_bin_dirs: - command = "bash tools/generate_opencl_code.sh binary" - else: - command = "bash tools/generate_opencl_code.sh {} {} {} {}".format( - 'binary', target_soc, cl_bin_dirs_str, int(pull_or_not)) - run_command(command) - - -def generate_tuning_param_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) - if not cl_bin_dirs: - command = "bash tools/generate_tuning_param_code.sh" - else: - command = "bash tools/generate_tuning_param_code.sh {} {} {}".format( - target_soc, cl_bin_dirs_str, int(pull_or_not)) - run_command(command) - - -def generate_code(target_soc, model_output_dirs, pull_or_not): - generate_opencl_binay_code(target_soc, model_output_dirs, pull_or_not) - generate_tuning_param_code(target_soc, model_output_dirs, pull_or_not) - - -def clear_env(target_soc): - command = "bash tools/clear_env.sh {}".format(target_soc) - run_command(command) - - -def input_file_name(input_name): - return os.environ['INPUT_FILE_NAME'] + '_' + \ - re.sub('[^0-9a-zA-Z]+', '_', input_name) - - -def generate_random_input(target_soc, model_output_dir, input_names, - input_files): - generate_data_or_not = True - command = "bash tools/validate_tools.sh {} {} {}".format( - target_soc, model_output_dir, int(generate_data_or_not)) - run_command(command) - - input_file_list = [] - if isinstance(input_files, list): - input_file_list.extend(input_files) - else: - input_file_list.append(input_files) - if len(input_file_list) != 0: - input_name_list = [] - if isinstance(input_names, list): - input_name_list.extend(input_names) - else: - input_name_list.append(input_names) - if len(input_file_list) != len(input_name_list): - raise Exception('If input_files set, the input files should ' - 'match the input names.') - for i in range(len(input_file_list)): - if input_file_list[i] is not None: - dst_input_file = model_output_dir + '/' + input_file_name( - input_name_list[i]) - if input_file_list[i].startswith("http://") or \ - input_file_list[i].startswith("https://"): - urllib.urlretrieve(input_file_list[i], dst_input_file) - else: - shutil.copy(input_file_list[i], dst_input_file) - - -def generate_model_code(): - command = "bash tools/generate_model_code.sh" - run_command(command) - - -def build_mace_run(production_mode, model_output_dir, hexagon_mode): - command = "bash tools/build_mace_run.sh {} {} {}".format( - int(production_mode), model_output_dir, int(hexagon_mode)) - run_command(command) - - -def tuning_run(model_name, - target_runtime, - target_abi, - target_soc, - model_output_dir, - running_round, - tuning, - restart_round, - option_args='', - out_of_range_check=False): - # TODO(yejianwu) refactoring the hackish code - stdout_buff = [] - process_output = sh_commands.make_output_processor(stdout_buff) - p = sh.bash( - "tools/tuning_run.sh", - target_soc, - model_output_dir, - running_round, - int(tuning), - restart_round, - option_args, - int(out_of_range_check), - _out=process_output, - _bg=True, - _err_to_out=True) - p.wait() + return True + return False + + +def generate_code(target_soc, target_abi, model_output_dirs, pull_or_not): + sh_commands.pull_binaries( + target_soc, target_abi, model_output_dirs, pull_or_not) + sh_commands.gen_opencl_binary_code( + target_soc, target_abi, model_output_dirs, pull_or_not) + sh_commands.gen_tuning_param_code( + target_soc, target_abi, model_output_dirs, pull_or_not) + + +def ops_benchmark_stdout_processor(stdout, + target_soc, + abi, + runtime, + running_round, + tuning): metrics = {} - for line in stdout_buff: + for line in stdout: + if "Aborted" in line: + raise Exception("Command failed") line = line.strip() parts = line.split() if len(parts) == 6 and parts[0].startswith("time"): @@ -195,8 +121,8 @@ def tuning_run(model_name, float(parts[5])) tags = { "ro.board.platform": target_soc, - "abi": target_abi, - # "runtime": target_runtime, # TODO(yejianwu) Add the actual runtime + "abi": abi, + "runtime": runtime, "round": running_round, # TODO(yejianwu) change this to source/binary "tuning": tuning } @@ -204,113 +130,125 @@ def tuning_run(model_name, metrics, endpoint="mace_model_benchmark", tags=tags) -def benchmark_model(target_soc, model_output_dir, option_args=''): - command = "bash tools/benchmark.sh {} {} \"{}\"".format( - target_soc, model_output_dir, option_args) - run_command(command) - - -def run_model(model_name, target_runtime, target_abi, target_soc, - model_output_dir, running_round, restart_round, option_args, - out_of_range_check): - tuning_run(model_name, target_runtime, target_abi, target_soc, - model_output_dir, running_round, False, restart_round, - option_args, out_of_range_check) - - -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( - target_soc, cl_bin_dirs_str, int(pull_or_not)) - run_command(command) - - -def build_mace_run_prod(model_name, target_runtime, target_abi, target_soc, - model_output_dir, tuning): - if "dsp" == target_runtime: - hexagon_mode = True - else: - hexagon_mode = False - - generate_code(target_soc, [], False) +def tuning_run(runtime, + target_soc, + target_abi, + vlog_level, + embed_model_data, + model_output_dir, + input_nodes, + output_nodes, + input_shapes, + output_shapes, + model_name, + device_type, + running_round, + restart_round, + out_of_range_check, + tuning=False, + limit_opencl_kernel_time=0, + option_args=""): + stdout = sh_commands.tuning_run( + target_soc, + target_abi, + vlog_level, + embed_model_data, + model_output_dir, + input_nodes, + output_nodes, + input_shapes, + output_shapes, + model_name, + device_type, + running_round, + restart_round, + limit_opencl_kernel_time, + tuning, + out_of_range_check, + option_args) + ops_benchmark_stdout_processor(stdout, + target_soc, + target_abi, + runtime, + running_round, + tuning) + + +def build_mace_run_prod(hexagon_mode, runtime, target_soc, target_abi, + vlog_level, embed_model_data, model_output_dir, + input_nodes, output_nodes, input_shapes, output_shapes, + model_name, device_type, running_round, restart_round, + tuning, limit_opencl_kernel_time): + generate_code(target_soc, target_abi, [], False) production_or_not = False - build_mace_run(production_or_not, model_output_dir, hexagon_mode) - - tuning_run( - model_name, - target_runtime, - target_abi, - target_soc, - model_output_dir, - running_round=0, - tuning=False, - restart_round=1, - out_of_range_check=True) - - tuning_run( - model_name, - target_runtime, - target_abi, - target_soc, - model_output_dir, - running_round=0, - tuning=tuning, - restart_round=1) - - generate_code(target_soc, [model_output_dir], True) + mace_run_target = "//mace/tools/validation:mace_run" + sh_commands.bazel_build( + mace_run_target, + abi=target_abi, + model_tag=model_name, + production_mode=False, + hexagon_mode=hexagon_mode) + sh_commands.update_mace_run_lib(model_output_dir, target_abi, model_name, + embed_model_data) + + tuning_run(runtime, target_soc, target_abi, vlog_level, embed_model_data, + model_output_dir, input_nodes, output_nodes, input_shapes, + output_shapes, model_name, device_type, running_round=0, + restart_round=1, out_of_range_check=True, tuning=False) + + tuning_run(runtime, target_soc, target_abi, vlog_level, embed_model_data, + model_output_dir, input_nodes, output_nodes, input_shapes, + output_shapes, model_name, device_type, running_round=0, + restart_round=1, out_of_range_check=False, tuning=tuning, + limit_opencl_kernel_time=limit_opencl_kernel_time) + + generate_code(target_soc, target_abi, [model_output_dir], True) production_or_not = True - build_mace_run(production_or_not, model_output_dir, hexagon_mode) - - -def build_run_throughput_test(target_soc, run_seconds, merged_lib_file, - model_input_dir): - command = "bash tools/build_run_throughput_test.sh {} {} {} {}".format( - target_soc, run_seconds, merged_lib_file, model_input_dir) - run_command(command) - - -def validate_model(target_soc, model_output_dir): - generate_data_or_not = False - command = "bash tools/validate_tools.sh {} {} {}".format( - target_soc, model_output_dir, int(generate_data_or_not)) - run_command(command) - - -def build_production_code(): - command = "bash tools/build_production_code.sh" - run_command(command) - - -def merge_libs_and_tuning_results(target_soc, output_dir, model_output_dirs): - generate_code(target_soc, model_output_dirs, False) - build_production_code() - - model_output_dirs_str = ",".join(model_output_dirs) - command = "bash tools/merge_libs.sh {} {} {}".format( - target_soc, output_dir, model_output_dirs_str) - run_command(command) - - -def packaging_lib_file(output_dir): - command = "bash tools/packaging_lib.sh {}".format(output_dir) - run_command(command) + sh_commands.bazel_build( + mace_run_target, + abi=target_abi, + model_tag=model_name, + production_mode=True, + hexagon_mode=hexagon_mode) + sh_commands.update_mace_run_lib(model_output_dir, target_abi, model_name, + embed_model_data) + + +def merge_libs_and_tuning_results(target_soc, + target_abi, + project_name, + output_dir, + model_output_dirs, + hexagon_mode, + embed_model_data): + generate_code(target_soc, target_abi, model_output_dirs, False) + sh_commands.build_production_code(target_abi) + + sh_commands.merge_libs(target_soc, + target_abi, + project_name, + output_dir, + model_output_dirs, + hexagon_mode, + embed_model_data) def download_model_files(model_file_path, model_output_dir, weight_file_path=""): + model_file = "" + weight_file = "" if model_file_path.startswith("http://") or \ model_file_path.startswith("https://"): - os.environ["MODEL_FILE_PATH"] = model_output_dir + "/model.pb" - urllib.urlretrieve(model_file_path, os.environ["MODEL_FILE_PATH"]) + model_file = model_output_dir + "/model.pb" + urllib.urlretrieve(model_file_path, model_file) if weight_file_path.startswith("http://") or \ weight_file_path.startswith("https://"): - os.environ["WEIGHT_FILE_PATH"] = model_output_dir + "/model.caffemodel" - urllib.urlretrieve(weight_file_path, os.environ["WEIGHT_FILE_PATH"]) + weight_file = model_output_dir + "/model.caffemodel" + urllib.urlretrieve(weight_file_path, weight_file) + + return model_file, weight_file def md5sum(str): @@ -368,13 +306,177 @@ def parse_args(): return parser.parse_known_args() -def set_environment(configs): - os.environ["EMBED_MODEL_DATA"] = str(configs["embed_model_data"]) - os.environ["VLOG_LEVEL"] = str(configs["vlog_level"]) - os.environ["PROJECT_NAME"] = os.path.splitext( - os.path.basename(FLAGS.config))[0] - os.environ['INPUT_FILE_NAME'] = "model_input" - os.environ['OUTPUT_FILE_NAME'] = "model_out" +def process_models(project_name, configs, embed_model_data, vlog_level, + target_soc, target_abi, option_args): + hexagon_mode = get_hexagon_mode(configs) + model_output_dirs = [] + for model_name in configs["models"]: + print '===================', model_name, '===================' + model_config = configs["models"][model_name] + input_file_list = model_config.get("validation_inputs_data", + []) + data_type, device_type = get_data_and_device_type( + model_config["runtime"]) + + for key in ["input_nodes", "output_nodes", "input_shapes", + "output_shapes"]: + if not isinstance(model_config[key], list): + model_config[key] = [model_config[key]] + + # Create model build directory + model_path_digest = md5sum(model_config["model_file_path"]) + model_output_dir = "%s/%s/%s/%s/%s/%s/%s" % ( + FLAGS.output_dir, project_name, "build", + 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): + sh.rm("-rf", model_output_dir) + os.makedirs(model_output_dir) + sh_commands.clear_mace_run_data(target_abi, target_soc) + + model_file_path, weight_file_path = download_model_files( + model_config["model_file_path"], + model_output_dir, + model_config.get("weight_file_path", "")) + + if FLAGS.mode == "build" or FLAGS.mode == "run" or \ + FLAGS.mode == "validate" or \ + FLAGS.mode == "benchmark" or FLAGS.mode == "all": + sh_commands.gen_random_input(model_output_dir, + model_config["input_nodes"], + model_config["input_shapes"], + input_file_list) + + if FLAGS.mode == "build" or FLAGS.mode == "all": + sh_commands.gen_model_code( + "mace/codegen/models/%s" % model_name, + model_config["platform"], + model_file_path, + weight_file_path, + model_config["model_sha256_checksum"], + ",".join(model_config["input_nodes"]), + ",".join(model_config["output_nodes"]), + data_type, + model_config["runtime"], + model_name, + ":".join(model_config["input_shapes"]), + model_config["dsp_mode"], + embed_model_data, + model_config["fast_conv"], + model_config["obfuscate"]) + build_mace_run_prod(hexagon_mode, + model_config["runtime"], + target_soc, + target_abi, + vlog_level, + embed_model_data, + model_output_dir, + model_config["input_nodes"], + model_config["output_nodes"], + model_config["input_shapes"], + model_config["output_shapes"], + model_name, + device_type, + FLAGS.round, + FLAGS.restart_round, + FLAGS.tuning, + model_config[ + "limit_opencl_kernel_time"]) + + if FLAGS.mode == "run" or FLAGS.mode == "validate" or \ + FLAGS.mode == "all": + tuning_run(model_config["runtime"], + target_soc, + target_abi, + vlog_level, + embed_model_data, + model_output_dir, + model_config["input_nodes"], + model_config["output_nodes"], + model_config["input_shapes"], + model_config["output_shapes"], + model_name, + device_type, + FLAGS.round, + FLAGS.restart_round, + FLAGS.out_of_range_check) + + if FLAGS.mode == "benchmark": + sh_commands.benchmark_model(target_soc, + target_abi, + vlog_level, + embed_model_data, + model_output_dir, + model_config["input_nodes"], + model_config["output_nodes"], + model_config["input_shapes"], + model_config["output_shapes"], + model_name, + device_type, + hexagon_mode, + option_args) + + if FLAGS.mode == "validate" or FLAGS.mode == "all": + sh_commands.validate_model(target_soc, + target_abi, + model_file_path, + weight_file_path, + model_config["platform"], + model_config["runtime"], + model_config["input_nodes"], + model_config["output_nodes"], + model_config["input_shapes"], + model_config["output_shapes"], + model_output_dir) + + if FLAGS.mode == "build" or FLAGS.mode == "merge" or \ + FLAGS.mode == "all": + merge_libs_and_tuning_results( + target_soc, + target_abi, + project_name, + FLAGS.output_dir, + model_output_dirs, + hexagon_mode, + embed_model_data) + + if FLAGS.mode == "throughput_test": + merged_lib_file = FLAGS.output_dir + \ + "/%s/%s/libmace_%s.%s.a" % \ + (project_name, target_abi, project_name, target_soc) + first_model = configs["models"].values()[0] + throughput_test_output_dir = "%s/%s/%s/%s" % ( + FLAGS.output_dir, project_name, "build", + "throughput_test") + if os.path.exists(throughput_test_output_dir): + sh.rm("-rf", throughput_test_output_dir) + os.makedirs(throughput_test_output_dir) + input_file_list = model_config.get("validation_inputs_data", + []) + sh_commands.gen_random_input(throughput_test_output_dir, + first_model["input_nodes"], + first_model["input_shapes"], + input_file_list) + model_tag_dict = {} + for model_name in configs["models"]: + runtime = configs["models"][model_name]["runtime"] + model_tag_dict[runtime] = model_name + sh_commands.build_run_throughput_test(target_soc, + target_abi, + vlog_level, + FLAGS.run_seconds, + merged_lib_file, + throughput_test_output_dir, + embed_model_data, + model_config["input_nodes"], + model_config["output_nodes"], + model_config["input_shapes"], + model_config["output_shapes"], + model_tag_dict.get("cpu", ""), + model_tag_dict.get("gpu", ""), + model_tag_dict.get("dsp", "")) def main(unused_args): @@ -384,126 +486,43 @@ def main(unused_args): FLAGS.round = 1 FLAGS.restart_round = 1 - set_environment(configs) - + 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"])) + sh.rm("-rf", os.path.join(FLAGS.output_dir, project_name)) + os.makedirs(os.path.join(FLAGS.output_dir, project_name)) - generate_version_code() - generate_opencl_source_code() + # generate source + sh_commands.gen_mace_version() + sh_commands.gen_encrypted_opencl_source() option_args = ' '.join( [arg for arg in unused_args if arg.startswith('--')]) - available_socs = sh_commands.adb_get_all_socs() - target_socs = available_socs - if hasattr(configs, "target_socs"): - target_socs = set(configs["target_socs"]) - target_socs = target_socs & available_socs - - if FLAGS.target_socs != "all": - socs = set(FLAGS.target_socs.split(',')) - target_socs = target_socs & socs - missing_socs = socs.difference(target_socs) - if len(missing_socs) > 0: - print( - "Error: devices with SoCs are not connected %s" % missing_socs) - exit(1) + target_socs = get_target_socs(configs) + embed_model_data = configs.get("embed_model_data", 1) + vlog_level = configs.get("vlog_level", 0) for target_soc in target_socs: 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"]: - print '===================', model_name, '===================' - # Transfer params by environment - os.environ["MODEL_TAG"] = model_name - model_config = configs["models"][model_name] - input_file_list = model_config.get("validation_inputs_data", - []) - 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]) - - # Create model build directory - model_path_digest = md5sum(model_config["model_file_path"]) - model_output_dir = "%s/%s/%s/%s/%s/%s/%s" % ( - FLAGS.output_dir, os.environ["PROJECT_NAME"], "build", - 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) - - download_model_files(model_config["model_file_path"], - model_output_dir, - model_config.get("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, - model_config['input_nodes'], - input_file_list) - - if FLAGS.mode == "build" or FLAGS.mode == "all": - generate_model_code() - build_mace_run_prod(model_name, global_runtime, target_abi, - target_soc, model_output_dir, - FLAGS.tuning) - - if FLAGS.mode == "run" or FLAGS.mode == "validate" or \ - FLAGS.mode == "all": - run_model(model_name, global_runtime, target_abi, - target_soc, model_output_dir, FLAGS.round, - FLAGS.restart_round, option_args, - FLAGS.out_of_range_check) - - if FLAGS.mode == "benchmark": - benchmark_model(target_soc, model_output_dir, option_args) - - if FLAGS.mode == "validate" or FLAGS.mode == "all": - validate_model(target_soc, 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/%s/libmace_%s.%s.a" % \ - (os.environ["PROJECT_NAME"], target_abi, - os.environ["PROJECT_NAME"], target_soc) - 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(target_soc, FLAGS.run_seconds, - merged_lib_file, FLAGS.output_dir) + serialno = sh_commands.adb_devices([target_soc]).pop() + props = sh_commands.adb_getprop_by_serialno(serialno) + print( + "=============================================================" + ) + print("Trying to lock device", serialno) + with sh_commands.device_lock(serialno): + print("Run on device: %s, %s, %s" % ( + serialno, props["ro.board.platform"], + props["ro.product.model"])) + process_models(project_name, configs, embed_model_data, + vlog_level, target_soc, target_abi, option_args) if FLAGS.mode == "build" or FLAGS.mode == "all": - packaging_lib_file(FLAGS.output_dir) + sh_commands.packaging_lib(FLAGS.output_dir, project_name) if __name__ == "__main__": diff --git a/tools/merge_libs.sh b/tools/merge_libs.sh deleted file mode 100644 index 90bfa7d9..00000000 --- a/tools/merge_libs.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/bash - -Usage() { - echo "Usage: bash tools/merge_libs.sh target_soc libmace_output_dir model_output_dirs" -} - -if [ $# -lt 3 ]; then - Usage - exit 1 -fi - -CURRENT_DIR=`dirname $0` -source ${CURRENT_DIR}/env.sh - -TARGET_SOC=$1 -LIBMACE_BUILD_DIR=$2 -MODEL_OUTPUT_DIRS=$3 -MODEL_OUTPUT_DIRS_ARR=(${MODEL_OUTPUT_DIRS//,/ }) -MODEL_HEADER_DIR=${LIBMACE_BUILD_DIR}/include/mace/public -MODEL_DATA_DIR=${LIBMACE_BUILD_DIR}/data - -if [ ! -d "${MODEL_HEADER_DIR}" ]; then - mkdir -p ${MODEL_HEADER_DIR} -fi -cp -rf ${MACE_SOURCE_DIR}/mace/public/*.h ${LIBMACE_BUILD_DIR}/include/mace/public/ - -if [ ! -d "${LIBMACE_BUILD_DIR}/${TARGET_ABI}" ]; then - mkdir -p ${LIBMACE_BUILD_DIR}/${TARGET_ABI} -fi -if [ ! -d "${MODEL_DATA_DIR}" ]; then - mkdir -p ${MODEL_DATA_DIR} -fi - -if [ x"${TARGET_ABI}" = x"armeabi-v7a" ]; then - cp ${MACE_SOURCE_DIR}/mace/core/runtime/hexagon/libhexagon_controller.so ${LIBMACE_BUILD_DIR}/${TARGET_ABI}/ -fi - -LIBMACE_TEMP_DIR=`mktemp -d -t libmace.XXXX` - -# Merge all libraries in to one -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.pic.a" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri - echo "addlib bazel-bin/mace/codegen/libgenerated_tuning_params.pic.a" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri -else - echo "addlib bazel-bin/mace/codegen/libgenerated_opencl.a" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri - echo "addlib bazel-bin/mace/codegen/libgenerated_tuning_params.a" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri - echo "addlib bazel-bin/mace/codegen/libgenerated_version.a" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri - echo "addlib bazel-bin/mace/core/libcore.a" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri - echo "addlib bazel-bin/mace/kernels/libkernels.a" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri - echo "addlib bazel-bin/mace/utils/libutils.a" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri - echo "addlib bazel-bin/mace/utils/libutils_prod.a" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri - echo "addlib bazel-bin/mace/ops/libops.lo" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri -fi - -for model_output_dir in ${MODEL_OUTPUT_DIRS_ARR[@]}; do - for lib in ${model_output_dir}/*.a; do - echo "addlib ${lib}" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri - done - if [ "${EMBED_MODEL_DATA}" == "0" ];then - for data_file in ${model_output_dir}/*.data; do - cp ${data_file} ${MODEL_DATA_DIR} - done - fi - for header_file in ${model_output_dir}/*.h; do - cp ${header_file} ${MODEL_HEADER_DIR} - done -done -echo "save" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri -echo "end" >> ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri -$ANDROID_NDK_HOME/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar \ - -M < ${LIBMACE_TEMP_DIR}/libmace_${PROJECT_NAME}.mri || exit 1 - -rm -rf ${LIBMACE_TEMP_DIR} - -echo "Libs merged!" diff --git a/tools/packaging_lib.sh b/tools/packaging_lib.sh deleted file mode 100644 index c6158cd5..00000000 --- a/tools/packaging_lib.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -Usage() { - echo "Usage: bash tools/packaging_lib.sh libmace_output_dir" -} - -if [ $# -lt 1 ]; then - Usage - exit 1 -fi - -CURRENT_DIR=`dirname $0` -source ${CURRENT_DIR}/env.sh - -LIBMACE_BUILD_DIR=$1 - -TAR_PACKAGE_NAME=libmace_${PROJECT_NAME}.tar.gz - -pushd $LIBMACE_BUILD_DIR/$PROJECT_NAME -if [ -f $TAR_PACKAGE_NAME ]; then - rm -f $TAR_PACKAGE_NAME -fi -ls | grep -v build | xargs tar cvzf $TAR_PACKAGE_NAME -popd - -echo "Packaging done!" diff --git a/tools/sh_commands.py b/tools/sh_commands.py index 40cc932a..55e4578e 100644 --- a/tools/sh_commands.py +++ b/tools/sh_commands.py @@ -1,7 +1,24 @@ +# Copyright 2018 Xiaomi, Inc. 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. + import falcon_cli import filelock +import glob +import os import re import sh +import subprocess import time @@ -36,6 +53,28 @@ def is_device_locked(serialno): return True +def formatted_file_name(input_name, input_file_name): + return input_file_name + '_' + \ + re.sub('[^0-9a-zA-Z]+', '_', input_name) + + +################################ +# clear data +################################ +def clear_mace_run_data(abi, + target_soc, + model_codegen_dir="mace/codegen/models", + mace_run_phone_data_dir="/data/local/tmp/mace_run"): + if abi != "host": + serialno = adb_devices([target_soc]).pop() + sh.adb("-s", + serialno, + "shell", + "rm -rf %s" % mace_run_phone_data_dir) + if os.path.exists(model_codegen_dir): + sh.rm("-rf", model_codegen_dir) + + ################################ # adb commands ################################ @@ -92,6 +131,19 @@ def adb_get_all_socs(): return set(socs) +def adb_push(src_path, dst_path, serialno): + print("Push %s to %s" % (src_path, dst_path)) + sh.adb("-s", serialno, "push", src_path, dst_path) + + +def adb_pull(src_path, dst_path, serialno): + print("Pull %s to %s" % (src_path, dst_path)) + try: + sh.adb("-s", serialno, "pull", src_path, dst_path) + except Exception as e: + print("Error msg: %s" % e.stderr) + + def adb_run(serialno, host_bin_path, bin_name, @@ -113,9 +165,7 @@ def adb_run(serialno, props["ro.product.model"])) sh.adb("-s", serialno, "shell", "rm -rf %s" % device_bin_path) sh.adb("-s", serialno, "shell", "mkdir -p %s" % device_bin_path) - print("Push %s to %s" % (host_bin_full_path, device_bin_full_path)) - sh.adb("-s", serialno, "push", host_bin_full_path, - device_bin_full_path) + adb_push(host_bin_full_path, device_bin_full_path, serialno) print("Run %s" % device_bin_full_path) stdout_buff = [] process_output = make_output_processor(stdout_buff) @@ -137,30 +187,82 @@ def adb_run(serialno, ################################ # bazel commands ################################ -def bazel_build(target, strip="always", abi="armeabi-v7a"): - print("Build %s with ABI %s" % (target, abi)) +def bazel_build(target, + strip="always", + abi="armeabi-v7a", + model_tag="", + production_mode=False, + hexagon_mode=False, + disable_no_tuning_warning=False): + print("* Build %s with ABI %s" % (target, abi)) + stdout_buff = [] + process_output = make_output_processor(stdout_buff) + if abi == "host": + p = sh.bazel( + "build", + "-c", + "opt", + "--strip", + strip, + "--verbose_failures", + target, + "--copt=-std=c++11", + "--copt=-D_GLIBCXX_USE_C99_MATH_TR1", + "--copt=-Werror=return-type", + "--copt=-DMACE_MODEL_TAG=%s" % model_tag, + "--copt=-O3", + "--define", + "openmp=true", + "--define", + "production=%s" % str(production_mode).lower(), + _out=process_output, + _bg=True, + _err_to_out=True) + p.wait() + else: + bazel_args = ( + "build", + "-c", + "opt", + "--strip", + strip, + "--verbose_failures", + target, + "--crosstool_top=//external:android/crosstool", + "--host_crosstool_top=@bazel_tools//tools/cpp:toolchain", + "--cpu=%s" % abi, + "--copt=-std=c++11", + "--copt=-D_GLIBCXX_USE_C99_MATH_TR1", + "--copt=-Werror=return-type", + "--copt=-DMACE_OBFUSCATE_LITERALS", + "--copt=-DMACE_MODEL_TAG=%s" % model_tag, + "--copt=-O3", + "--define", + "neon=true", + "--define", + "openmp=true", + "--define", + "production=%s" % str(production_mode).lower(), + "--define", + "hexagon=%s" % str(hexagon_mode).lower()) + if disable_no_tuning_warning: + bazel_args += ("--copt=-DMACE_DISABLE_NO_TUNING_WARNING",) + p = sh.bazel( + _out=process_output, + _bg=True, + _err_to_out=True, + *bazel_args) + p.wait() + print("Building done!\n") + return "".join(stdout_buff) + + +def bazel_build_common(target, build_args=""): stdout_buff = [] process_output = make_output_processor(stdout_buff) p = sh.bazel( "build", - "-c", - "opt", - "--strip", - strip, - "--verbose_failures", - target, - "--crosstool_top=//external:android/crosstool", - "--host_crosstool_top=@bazel_tools//tools/cpp:toolchain", - "--cpu=%s" % abi, - "--copt=-std=c++11", - "--copt=-D_GLIBCXX_USE_C99_MATH_TR1", - "--copt=-DMACE_DISABLE_NO_TUNING_WARNING", - "--copt=-Werror=return-type", - "--copt=-O3", - "--define", - "neon=true", - "--define", - "openmp=true", + target + build_args, _out=process_output, _bg=True, _err_to_out=True) @@ -190,6 +292,87 @@ def gen_encrypted_opencl_source(codegen_path="mace/codegen"): "--output_path=%s/opencl/opencl_encrypt_program.cc" % codegen_path) +def pull_binaries(target_soc, abi, model_output_dirs, pull_or_not): + serialno = adb_devices([target_soc]).pop() + compiled_opencl_dir = "/data/local/tmp/mace_run/cl_program/" + mace_run_config_file = "mace_run.config" + + 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) + if cl_bin_dirs and pull_or_not: + cl_bin_dir = cl_bin_dirs_str + if os.path.exists(cl_bin_dir): + sh.rm("-rf", cl_bin_dir) + sh.mkdir("-p", cl_bin_dir) + if abi != "host": + adb_pull(compiled_opencl_dir, cl_bin_dir, serialno) + adb_pull("/data/local/tmp/mace_run/%s" % mace_run_config_file, + cl_bin_dir, serialno) + + +def gen_opencl_binary_code(target_soc, + abi, + model_output_dirs, + pull_or_not, + codegen_path="mace/codegen"): + cl_built_kernel_file_name = "mace_cl_compiled_program.bin" + cl_platform_info_file_name = "mace_cl_platform_info.txt" + + serialno = adb_devices([target_soc]).pop() + compiled_opencl_dir = "/data/local/tmp/mace_run/cl_program/" + + 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) + if not cl_bin_dirs: + sh.python( + "mace/python/tools/opencl_codegen.py", + "--built_kernel_file_name=%s" % cl_built_kernel_file_name, + "--platform_info_file_name=%s" % cl_platform_info_file_name, + "--output_path=%s/opencl/opencl_compiled_program.cc" % + codegen_path) + else: + sh.python( + "mace/python/tools/opencl_codegen.py", + "--built_kernel_file_name=%s" % cl_built_kernel_file_name, + "--platform_info_file_name=%s" % cl_platform_info_file_name, + "--cl_binary_dirs=%s" % cl_bin_dirs_str, + "--output_path=%s/opencl/opencl_compiled_program.cc" % + codegen_path) + + +def gen_tuning_param_code(target_soc, + abi, + model_output_dirs, + pull_or_not, + codegen_path="mace/codegen"): + mace_run_config_file = "mace_run.config" + 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) + if not cl_bin_dirs: + opencl_codegen_dir = "%s/opencl/" % codegen_path + if not os.path.exists(opencl_codegen_dir): + sh.mkdir("-p", opencl_codegen_dir) + sh.python( + "mace/python/tools/binary_codegen.py", + "--binary_file_name=%s" % mace_run_config_file, + "--output_path=%s/opencl/tuning_params.cc" % codegen_path) + else: + tuning_codegen_dir = "%s/tuning/" % codegen_path + if not os.path.exists(tuning_codegen_dir): + sh.mkdir("-p", tuning_codegen_dir) + sh.python( + "mace/python/tools/binary_codegen.py", + "--binary_dirs=%s" % cl_bin_dirs_str, + "--binary_file_name=%s" % mace_run_config_file, + "--output_path=%s/tuning_params.cc" % tuning_codegen_dir) + + def gen_mace_version(codegen_path="mace/codegen"): sh.mkdir("-p", "%s/version" % codegen_path) sh.bash("mace/tools/git/gen_version_source.sh", @@ -203,6 +386,668 @@ def gen_compiled_opencl_source(codegen_path="mace/codegen"): "--output_path=%s/opencl/opencl_compiled_program.cc" % codegen_path) +def gen_model_code(model_codegen_dir, + platform, + model_file_path, + weight_file_path, + model_sha256_checksum, + input_nodes, + output_nodes, + data_type, + runtime, + model_tag, + input_shapes, + dsp_mode, + embed_model_data, + fast_conv, + obfuscate): + print("* Genearte model code") + bazel_build_common("//mace/python/tools:converter") + if os.path.exists(model_codegen_dir): + sh.rm("-rf", model_codegen_dir) + sh.mkdir("-p", model_codegen_dir) + sh.python("bazel-bin/mace/python/tools/converter", + "-u", + "--platform=%s" % platform, + "--model_file=%s" % model_file_path, + "--weight_file=%s" % weight_file_path, + "--model_checksum=%s" % model_sha256_checksum, + "--output=%s" % model_codegen_dir + "/model.cc", + "--input_node=%s" % input_nodes, + "--output_node=%s" % output_nodes, + "--data_type=%s" % data_type, + "--runtime=%s" % runtime, + "--output_type=source", + "--template=%s" % "mace/python/tools", + "--model_tag=%s" % model_tag, + "--input_shape=%s" % input_shapes, + "--dsp_mode=%s" % dsp_mode, + "--embed_model_data=%s" % embed_model_data, + "--winograd=%s" % fast_conv, + "--obfuscate=%s" % obfuscate) + print("Model code gen done!\n") + + +def gen_random_input(model_output_dir, + input_nodes, + input_shapes, + input_files, + input_file_name="model_input"): + for input_name in input_nodes: + formatted_name = formatted_file_name(input_name, input_file_name) + if os.path.exists(formatted_name): + sh.rm(formatted_name) + input_nodes_str = ",".join(input_nodes) + input_shapes_str = ":".join(input_shapes) + sh.python("-u", + "tools/generate_data.py", + "--input_node=%s" % input_nodes_str, + "--input_file=%s" % model_output_dir + "/" + input_file_name, + "--input_shape=%s" % input_shapes_str) + + input_file_list = [] + if isinstance(input_files, list): + input_file_list.extend(input_files) + else: + input_file_list.append(input_files) + if len(input_file_list) != 0: + input_name_list = [] + if isinstance(input_names, list): + input_name_list.extend(input_names) + else: + input_name_list.append(input_names) + if len(input_file_list) != len(input_name_list): + raise Exception('If input_files set, the input files should ' + 'match the input names.') + for i in range(len(input_file_list)): + if input_file_list[i] is not None: + dst_input_file = model_output_dir + '/' + \ + formatted_file_name(input_name_list[i], + input_file_name) + if input_file_list[i].startswith("http://") or \ + input_file_list[i].startswith("https://"): + urllib.urlretrieve(input_file_list[i], dst_input_file) + else: + sh.cp(input_file_list[i], dst_input_file) + + +def update_mace_run_lib(model_output_dir, + abi, + model_tag, + embed_model_data, + generated_model_lib_dir="bazel-bin/mace/codegen/"): + model_lib_path = model_output_dir + "/libmace_%s.a" % model_tag + if abi == "host": + bazel_build( + "//mace/codegen:generated_models", + abi=abi, + model_tag=model_tag) + generated_model_lib_name = "libgenerated_models.pic.a" + else: + generated_model_lib_name = "libgenerated_models.a" + + if os.path.exists(model_lib_path): + sh.rm("-rf", model_lib_path) + sh.cp(generated_model_lib_dir + "/" + generated_model_lib_name, + model_lib_path) + + mace_run_filepath = model_output_dir + "/mace_run" + if os.path.exists(mace_run_filepath): + sh.rm("-rf", mace_run_filepath) + sh.cp("bazel-bin/mace/tools/validation/mace_run", model_output_dir) + + if embed_model_data == 0: + sh.cp("mace/codegen/models/%s/%s.data" % (model_tag, model_tag), + model_output_dir) + + sh.cp("mace/codegen/models/%s/%s.h" % (model_tag, model_tag), + model_output_dir) + + +def tuning_run(target_soc, + abi, + vlog_level, + embed_model_data, + model_output_dir, + input_nodes, + output_nodes, + input_shapes, + output_shapes, + model_tag, + device_type, + running_round, + restart_round, + limit_opencl_kernel_time, + tuning, + out_of_range_check, + option_args="", + input_file_name="model_input", + output_file_name="model_out"): + print("* Run '%s' with round=%s, restart_round=%s, tuning=%s" % + (model_tag, running_round, restart_round, str(tuning))) + stdout_buff = [] + process_output = make_output_processor(stdout_buff) + if abi == "host": + p = subprocess.Popen([ + "env", + "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level, + "%s/mace_run" % model_output_dir, + "--input_node=%s" % ",".join(input_nodes), + "--output_node=%s" % ",".join(output_nodes), + "--input_shape=%s" % ":".join(input_shapes), + "--output_shape=%s" % ":".join(output_shapes), + "--input_file=%s/%s" % (model_output_dir, input_file_name), + "--output_file=%s/%s" % (model_output_dir, output_file_name), + "--model_data_file=%s/%s.data" % (model_output_dir, model_tag), + "--device=%s" % device_type, + "--round=%s" % running_round, + "--restart_round=%s" % restart_round, + "%s" % option_args]) + p.wait() + else: + serialno = adb_devices([target_soc]).pop() + phone_data_dir = "/data/local/tmp/mace_run/" + sh.adb("-s", serialno, "shell", "mkdir", "-p", phone_data_dir) + compiled_opencl_dir = "/data/local/tmp/mace_run/cl_program/" + sh.adb("-s", serialno, "shell", "mkdir", "-p", compiled_opencl_dir) + + for input_name in input_nodes: + formatted_name = formatted_file_name(input_name, + input_file_name) + adb_push("%s/%s" % (model_output_dir, formatted_name), + phone_data_dir, serialno) + adb_push("%s/mace_run" % model_output_dir, phone_data_dir, + serialno) + if not embed_model_data: + adb_push("%s/%s.data" % (model_output_dir, model_tag), + phone_data_dir, serialno) + adb_push("mace/core/runtime/hexagon/libhexagon_controller.so", + phone_data_dir, serialno) + + p = sh.adb( + "-s", + serialno, + "shell", + "LD_LIBRARY_PATH=%s" % phone_data_dir, + "MACE_TUNING=%s" % int(tuning), + "MACE_OUT_OF_RANGE_CHECK=%s" % int(out_of_range_check), + "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level, + "MACE_RUN_PARAMETER_PATH=%s/mace_run.config" % + phone_data_dir, + "MACE_CL_PROGRAM_PATH=%s/cl_program" % phone_data_dir, + "MACE_LIMIT_OPENCL_KERNEL_TIME=%s" % + limit_opencl_kernel_time, + "%s/mace_run" % phone_data_dir, + "--input_node=%s" % ",".join(input_nodes), + "--output_node=%s" % ",".join(output_nodes), + "--input_shape=%s" % ":".join(input_shapes), + "--output_shape=%s" % ":".join(output_shapes), + "--input_file=%s/%s" % (phone_data_dir, input_file_name), + "--output_file=%s/%s" % (phone_data_dir, output_file_name), + "--model_data_file=%s/%s.data" % (phone_data_dir, model_tag), + "--device=%s" % device_type, + "--round=%s" % running_round, + "--restart_round=%s" % restart_round, + "%s" % option_args, + _out=process_output, + _bg=True, + _err_to_out=True) + p.wait() + + print("Running finished!\n") + return "".join(stdout_buff) + + +def validate_model(target_soc, + abi, + model_file_path, + weight_file_path, + platform, + runtime, + input_nodes, + output_nodes, + input_shapes, + output_shapes, + model_output_dir, + input_file_name="model_input", + output_file_name="model_out"): + print("* Validate with %s" % platform) + serialno = adb_devices([target_soc]).pop() + phone_data_dir = "/data/local/tmp/mace_run" + stdout_buff = [] + process_output = make_output_processor(stdout_buff) + + if platform == "tensorflow": + if abi != "host": + for output_name in output_nodes: + formatted_name = formatted_file_name( + output_name, output_file_name) + if os.path.exists(formatted_name): + sh.rm(formatted_name) + adb_pull("%s/%s" % (phone_data_dir, formatted_name), + model_output_dir, serialno) + p = sh.python( + "-u", + "tools/validate.py", + "--platform=%s" % platform, + "--model_file=%s" % model_file_path, + "--input_file=%s" % model_output_dir + "/" + input_file_name, + "--mace_out_file=%s" % model_output_dir + "/" + + output_file_name, + "--mace_runtime=%s" % runtime, + "--input_node=%s" % ",".join(input_nodes), + "--output_node=%s" % ",".join(output_nodes), + "--input_shape=%s" % ":".join(input_shapes), + "--output_shape=%s" % ":".join(output_shapes), + _out=process_output, + _bg=True, + _err_to_out=True) + p.wait() + elif platform == "caffe": + image_name = "mace-caffe:latest" + container_name = "mace_caffe_validator" + res_file = "validation.result" + + docker_image_id = sh.docker("images", "-q", image_name) + if not docker_image_id: + print("Build caffe docker") + sh.docker("build", "-t", image_name, "docker/caffe") + + container_id = sh.docker("ps", "-qa", "-f", "name=%s" % container_name) + if not container_id: + print("Run caffe container") + sh.docker( + "run", + "-d", + "-it", + "--name", + container_name, + image_name, + "/bin/bash") + + container_status = sh.docker("inspect", + "-f", + "{{.State.Running}}", + container_name) + if container_status == "false": + print("Start caffe container") + sh.docker("start", container_name) + + for input_name in input_nodes: + formatted_input_name = formatted_file_name( + input_name, input_file_name) + sh.docker( + "cp", + "%s/%s" % (model_output_dir, formatted_input_name), + "%s:/mace" % container_name) + + if abi != "host": + for output_name in output_nodes: + formatted_output_name = formatted_file_name( + output_name, output_file_name) + sh.rm("-rf", + "%s/%s" % (model_output_dir, formatted_output_name)) + adb_pull("%s/%s" % (phone_data_dir, formatted_output_name), + model_output_dir, serialno) + + for output_name in output_nodes: + formatted_output_name = formatted_file_name( + output_name, output_file_name) + sh.docker( + "cp", + "%s/%s" % (model_output_dir, formatted_output_name), + "%s:/mace" % container_name) + model_file_name = os.path.basename(model_file_path) + weight_file_name = os.path.basename(weight_file_path) + sh.docker("cp", "tools/validate.py", "%s:/mace" % container_name) + sh.docker("cp", model_file_path, "%s:/mace" % container_name) + sh.docker("cp", weight_file_path, "%s:/mace" % container_name) + p = sh.docker( + "exec", + container_name, + "python", + "-u", + "/mace/validate.py", + "--platform=caffe", + "--model_file=/mace/%s" % model_file_name, + "--weight_file=/mace/%s" % weight_file_name, + "--input_file=/mace/%s" % input_file_name, + "--mace_out_file=/mace/%s" % output_file_name, + "--mace_runtime=%s" % runtime, + "--input_node=%s" % ",".join(input_nodes), + "--output_node=%s" % ",".join(output_nodes), + "--input_shape=%s" % ":".join(input_shapes), + "--output_shape=%s" % ":".join(output_shapes), + _out=process_output, + _bg=True, + _err_to_out=True) + p.wait() + + print("Validation done!\n") + return "".join(stdout_buff) + + +def build_production_code(abi): + bazel_build("//mace/codegen:generated_opencl", abi=abi) + bazel_build("//mace/codegen:generated_tuning_params", abi=abi) + + +def merge_libs(target_soc, + abi, + project_name, + libmace_output_dir, + model_output_dirs, + hexagon_mode, + embed_model_data): + print("* Merge mace lib") + project_output_dir = "%s/%s" % (libmace_output_dir, project_name) + model_header_dir = "%s/include/mace/public" % project_output_dir + model_data_dir = "%s/data" % project_output_dir + hexagon_lib_file = "mace/core/runtime/hexagon/libhexagon_controller.so" + model_bin_dir = "%s/%s/" % (project_output_dir, abi) + + if not os.path.exists(model_bin_dir): + sh.mkdir("-p", model_bin_dir) + if not os.path.exists(model_header_dir): + sh.mkdir("-p", model_header_dir) + if not os.path.exists(model_data_dir): + sh.mkdir("-p", model_data_dir) + if hexagon_mode: + sh.cp(hexagon_lib_file, model_bin_dir) + + mri_stream = "" + mri_stream += "create %s/libmace_%s.%s.a\n" % \ + (model_bin_dir, project_name, target_soc) + + if abi == "host": + mri_stream += ( + "addlib " + "bazel-bin/mace/codegen/libgenerated_opencl.pic.a\n") + mri_stream += ( + "addlib " + "bazel-bin/mace/codegen/libgenerated_tuning_params.pic.a\n") + else: + mri_stream += ( + "addlib " + "bazel-bin/mace/codegen/libgenerated_opencl.a\n") + mri_stream += ( + "addlib " + "bazel-bin/mace/codegen/libgenerated_tuning_params.a\n") + mri_stream += ( + "addlib " + "bazel-bin/mace/codegen/libgenerated_version.a\n") + mri_stream += ( + "addlib " + "bazel-bin/mace/core/libcore.a\n") + mri_stream += ( + "addlib " + "bazel-bin/mace/kernels/libkernels.a\n") + mri_stream += ( + "addlib " + "bazel-bin/mace/utils/libutils.a\n") + mri_stream += ( + "addlib " + "bazel-bin/mace/utils/libutils_prod.a\n") + mri_stream += ( + "addlib " + "bazel-bin/mace/ops/libops.lo\n") + + for model_output_dir in model_output_dirs: + for lib in sh.ls(glob.glob("%s/*.a" % model_output_dir), "-1"): + mri_stream += "addlib %s\n" % lib + if not embed_model_data: + for data_file in sh.ls(glob.glob("%s/*.data" % + model_output_dir), "-1"): + sh.cp(data_file.strip("\n"), model_data_dir) + for header_file in sh.ls(glob.glob("%s/*.h" % model_output_dir), + "-1"): + sh.cp(header_file.strip("\n"), model_header_dir) + + mri_stream += "save\n" + mri_stream += "end\n" + + cmd = sh.Command("%s/toolchains/" % os.environ["ANDROID_NDK_HOME"] + + "aarch64-linux-android-4.9/prebuilt/linux-x86_64/" + + "bin/aarch64-linux-android-ar") + + cmd("-M", _in=mri_stream) + + print("Libs merged!\n") + + +def packaging_lib(libmace_output_dir, project_name): + print("* Package libs for %s" % project_name) + tar_package_name = "libmace_%s.tar.gz" % project_name + project_dir = "%s/%s" % (libmace_output_dir, project_name) + tar_package_path = "%s/%s" % (project_dir, tar_package_name) + if os.path.exists(tar_package_path): + sh.rm("-rf", tar_package_path) + + print("Start packaging '%s' libs into %s" % (project_name, + tar_package_path)) + # ls ${project_dir} -1 | grep -v build | grep -v .tar.gz | xargs -I {} \ + # tar cvzf ${project_dir}/${tar_package_name} ${project_name}/{} + sh.xargs( + sh.grep( + sh.grep( + sh.ls(project_dir, "-1"), + "-v", "build"), + "-v", ".tar.gz"), + "-I", + "{}", + "tar", + "cvzf", + "%s" % tar_package_path, + "%s/{}" % project_dir) + print("Packaging Done!\n") + + +def benchmark_model(target_soc, + abi, + vlog_level, + embed_model_data, + model_output_dir, + input_nodes, + output_nodes, + input_shapes, + output_shapes, + model_tag, + device_type, + hexagon_mode, + option_args="", + input_file_name="model_input", + output_file_name="model_out"): + print("* Benchmark for %s" % model_tag) + benchmark_binary_file = "%s/benchmark_model" % model_output_dir + if os.path.exists(benchmark_binary_file): + sh.rm("-rf", benchmark_binary_file) + if not embed_model_data: + sh.cp("codegen/models/%s/%s.data" % (model_tag, model_tag), + model_output_dir) + + benchmark_target = "//mace/benchmark:benchmark_model" + bazel_build(benchmark_target, + abi=abi, + model_tag=model_tag, + hexagon_mode=hexagon_mode) + + target_bin = "/".join(bazel_target_to_bin(benchmark_target)) + sh.cp(target_bin, model_output_dir) + + stdout_buff = [] + process_output = make_output_processor(stdout_buff) + if abi == "host": + p = subprocess.Popen([ + "env", + "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level, + "%s/benchmark_model" % model_output_dir, + "--input_node=%s" % ",".join(input_nodes), + "--output_node=%s" % ",".join(output_nodes), + "--input_shape=%s" % ":".join(input_shapes), + "--output_shape=%s" % ":".join(output_shapes), + "--input_file=%s/%s" % (model_output_dir, input_file_name), + "--model_data_file=%s/%s.data" % (model_output_dir, model_tag), + "--device=%s" % device_type, + "%s" % option_args]) + p.wait() + else: + serialno = adb_devices([target_soc]).pop() + phone_data_dir = "/data/local/tmp/mace_run/" + sh.adb("-s", serialno, "shell", "mkdir", "-p", phone_data_dir) + + for input_name in input_nodes: + formatted_name = formatted_file_name(input_name, + input_file_name) + adb_push("%s/%s" % (model_output_dir, formatted_name), + phone_data_dir, serialno) + adb_push("%s/benchmark_model" % model_output_dir, phone_data_dir, + serialno) + if not embed_model_data: + adb_push("%s/%s.data" % (model_output_dir, model_tag), + phone_data_dir, serialno) + p = sh.adb( + "-s", + serialno, + "shell", + "LD_LIBRARY_PATH=%s" % phone_data_dir, + "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level, + "MACE_RUN_PARAMETER_PATH=%s/mace_run.config" % + phone_data_dir, + "MACE_OPENCL_PROFILING=1", + "%s/benchmark_model" % phone_data_dir, + "--input_node=%s" % ",".join(input_nodes), + "--output_node=%s" % ",".join(output_nodes), + "--input_shape=%s" % ":".join(input_shapes), + "--output_shape=%s" % ":".join(output_shapes), + "--input_file=%s/%s" % (phone_data_dir, input_file_name), + "--model_data_file=%s/%s.data" % (phone_data_dir, model_tag), + "--device=%s" % device_type, + "%s" % option_args, + _out=process_output, + _bg=True, + _err_to_out=True) + p.wait() + + print("Benchmark done!\n") + return "".join(stdout_buff) + + +def build_run_throughput_test(target_soc, + abi, + vlog_level, + run_seconds, + merged_lib_file, + model_input_dir, + embed_model_data, + input_nodes, + output_nodes, + input_shapes, + output_shapes, + cpu_model_tag, + gpu_model_tag, + dsp_model_tag, + strip="always", + input_file_name="model_input"): + print("* Build and run throughput_test") + phone_data_dir = "/data/local/tmp/mace_run/" + serialno = adb_devices([target_soc]).pop() + + model_tag_build_flag = "" + if cpu_model_tag: + model_tag_build_flag += "--copt=-DMACE_CPU_MODEL_TAG=%s " % \ + cpu_model_tag + if gpu_model_tag: + model_tag_build_flag += "--copt=-DMACE_GPU_MODEL_TAG=%s " % \ + gpu_model_tag + if dsp_model_tag: + model_tag_build_flag += "--copt=-DMACE_DSP_MODEL_TAG=%s " % \ + dsp_model_tag + + sh.cp(merged_lib_file, "mace/benchmark/libmace_merged.a") + stdout_buff = [] + process_output = make_output_processor(stdout_buff) + p = sh.bazel( + "build", + "-c", + "opt", + "--strip", + strip, + "--verbose_failures", + "//mace/benchmark:model_throughput_test", + "--crosstool_top=//external:android/crosstool", + "--host_crosstool_top=@bazel_tools//tools/cpp:toolchain", + "--cpu=%s" % abi, + "--copt=-std=c++11", + "--copt=-D_GLIBCXX_USE_C99_MATH_TR1", + "--copt=-Werror=return-type", + "--copt=-O3", + "--define", + "neon=true", + "--define", + "openmp=true", + model_tag_build_flag, + _out=process_output, + _bg=True, + _err_to_out=True) + p.wait() + + sh.rm("mace/benchmark/libmace_merged.a") + sh.adb("-s", + serialno, + "shell", + "mkdir", + "-p", + phone_data_dir) + adb_push("%s/%s_%s" % (model_input_dir, input_file_name, + ",".join(input_nodes)), + phone_data_dir, + serialno) + adb_push("bazel-bin/mace/benchmark/model_throughput_test", + phone_data_dir, + serialno) + if not embed_model_data: + adb_push("codegen/models/%s/%s.data" % cpu_model_tag, + phone_data_dir, + serialno) + adb_push("codegen/models/%s/%s.data" % gpu_model_tag, + phone_data_dir, + serialno) + adb_push("codegen/models/%s/%s.data" % dsp_model_tag, + phone_data_dir, + serialno) + adb_push("mace/core/runtime/hexagon/libhexagon_controller.so", + phone_data_dir, + serialno) + + p = sh.adb( + "-s", + serialno, + "shell", + "LD_LIBRARY_PATH=%s" % phone_data_dir, + "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level, + "MACE_RUN_PARAMETER_PATH=%s/mace_run.config" % + phone_data_dir, + "%s/model_throughput_test" % phone_data_dir, + "--input_node=%s" % ",".join(input_nodes), + "--output_node=%s" % ",".join(output_nodes), + "--input_shape=%s" % ":".join(input_shapes), + "--output_shape=%s" % ":".join(output_shapes), + "--input_file=%s/%s" % (phone_data_dir, input_file_name), + "--cpu_model_data_file=%s/%s.data" % (phone_data_dir, + cpu_model_tag), + "--gpu_model_data_file=%s/%s.data" % (phone_data_dir, + gpu_model_tag), + "--dsp_model_data_file=%s/%s.data" % (phone_data_dir, + dsp_model_tag), + "--run_seconds=%s" % run_seconds, + _out=process_output, + _bg=True, + _err_to_out=True) + p.wait() + + print("throughput_test done!\n") + + ################################ # falcon ################################ diff --git a/tools/tuning_run.sh b/tools/tuning_run.sh deleted file mode 100644 index 9499d792..00000000 --- a/tools/tuning_run.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/bash - -Usage() { - echo "Usage: bash tools/tuning_run.sh target_soc model_output_dir round tuning restart_round opt_args out_of_range_check" -} - -if [ $# -lt 7 ]; then - Usage - exit 1 -fi - -CURRENT_DIR=`dirname $0` -source ${CURRENT_DIR}/env.sh - -TARGET_SOC=$1 -MODEL_OUTPUT_DIR=$2 -ROUND=$3 -TUNING_OR_NOT=$4 -RESTART_ROUND=$5 -OPTION_ARGS=$6 -OUT_OF_RANGE_CHECK_OR_NOT=$7 - -echo $OPTION_ARGS - -RESULT_VALUE=`echo_device_id_by_soc $TARGET_SOC` -if [ $? -ne 0 ]; then - echo $RESULT_VALUE - exit 1 -else - DEVICE_ID=$RESULT_VALUE -fi - -if [ x"$TARGET_ABI" = x"host" ]; then - MACE_CPP_MIN_VLOG_LEVEL=$VLOG_LEVEL \ - ${MODEL_OUTPUT_DIR}/mace_run \ - --input_node="${INPUT_NODES}" \ - --input_shape="${INPUT_SHAPES}"\ - --output_node="${OUTPUT_NODES}" \ - --output_shape="${OUTPUT_SHAPES}"\ - --input_file=${MODEL_OUTPUT_DIR}/${INPUT_FILE_NAME} \ - --output_file=${MODEL_OUTPUT_DIR}/${OUTPUT_FILE_NAME} \ - --model_data_file=${MODEL_OUTPUT_DIR}/${MODEL_TAG}.data \ - --device=${DEVICE_TYPE} \ - --round=1 \ - --restart_round=1 \ - $OPTION_ARGS || exit 1 -else - if [[ "${TUNING_OR_NOT}" != "0" ]];then - tuning_flag=1 - else - tuning_flag=0 - fi - - if [[ "${OUT_OF_RANGE_CHECK_OR_NOT}" != "0" ]]; then - out_of_range_check_flag=1 - else - out_of_range_check_flag=0 - fi - - adb -s $DEVICE_ID shell "mkdir -p ${PHONE_DATA_DIR}" || exit 1 - adb -s $DEVICE_ID shell "mkdir -p ${COMPILED_PROGRAM_DIR}" || exit 1 - - IFS=',' read -r -a INPUT_NAMES <<< "${INPUT_NODES}" - for NAME in "${INPUT_NAMES[@]}";do - FORMATTED_NAME=$(sed s/[^[:alnum:]]/_/g <<< ${NAME}) - adb -s $DEVICE_ID push ${MODEL_OUTPUT_DIR}/${INPUT_FILE_NAME}_${FORMATTED_NAME} ${PHONE_DATA_DIR} > /dev/null || exit 1 - done - - adb -s $DEVICE_ID /dev/null || exit 1 - if [ "$EMBED_MODEL_DATA" = 0 ]; then - adb -s $DEVICE_ID push ${MODEL_OUTPUT_DIR}/${MODEL_TAG}.data ${PHONE_DATA_DIR} > /dev/null || exit 1 - fi - 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} \ - MACE_OUT_OF_RANGE_CHECK=${out_of_range_check_flag} \ - MACE_CPP_MIN_VLOG_LEVEL=$VLOG_LEVEL \ - MACE_RUN_PARAMETER_PATH=${PHONE_DATA_DIR}/mace_run.config \ - MACE_CL_PROGRAM_PATH=$COMPILED_PROGRAM_DIR \ - MACE_LIMIT_OPENCL_KERNEL_TIME=${LIMIT_OPENCL_KERNEL_TIME} \ - ${PHONE_DATA_DIR}/mace_run \ - --input_node="${INPUT_NODES}" \ - --input_shape="${INPUT_SHAPES}"\ - --output_node="${OUTPUT_NODES}" \ - --output_shape="${OUTPUT_SHAPES}"\ - --input_file=${PHONE_DATA_DIR}/${INPUT_FILE_NAME} \ - --output_file=${PHONE_DATA_DIR}/${OUTPUT_FILE_NAME} \ - --model_data_file=${PHONE_DATA_DIR}/${MODEL_TAG}.data \ - --device=${DEVICE_TYPE} \ - --round=$ROUND \ - --restart_round=$RESTART_ROUND \ - $OPTION_ARGS; echo \$?" - echo $ADB_CMD_STR - mace_adb_output=`adb -s $DEVICE_ID /dev/null || exit 1 - done - fi - python -u tools/validate.py --platform=tensorflow \ - --model_file ${MODEL_FILE_PATH} \ - --input_file ${MODEL_OUTPUT_DIR}/${INPUT_FILE_NAME} \ - --mace_out_file ${MODEL_OUTPUT_DIR}/${OUTPUT_FILE_NAME} \ - --mace_runtime ${RUNTIME} \ - --input_node ${INPUT_NODES} \ - --output_node ${OUTPUT_NODES} \ - --input_shape ${INPUT_SHAPES} \ - --output_shape ${OUTPUT_SHAPES} || exit 1 - -elif [ "$PLATFORM" == "caffe" ];then - IMAGE_NAME=mace-caffe:latest - CONTAINER_NAME=mace_caffe_validator - RES_FILE=validation.result - - if [[ "$(docker images -q mace-caffe:latest 2> /dev/null)" == "" ]]; then - echo "Build caffe docker" - docker build -t ${IMAGE_NAME} docker/caffe || exit 1 - fi - - if [ ! "$(docker ps -qa -f name=${CONTAINER_NAME})" ]; then - echo "Run caffe container" - docker run -d -it --name ${CONTAINER_NAME} ${IMAGE_NAME} /bin/bash || exit 1 - fi - - if [ "$(docker inspect -f {{.State.Running}} ${CONTAINER_NAME})" == "false" ];then - echo "Start caffe container" - docker start ${CONTAINER_NAME} - fi - - for NAME in "${INPUT_NAMES[@]}";do - FORMATTED_NAME=$(sed s/[^[:alnum:]]/_/g <<< ${NAME}) - docker cp ${MODEL_OUTPUT_DIR}/${INPUT_FILE_NAME}_${FORMATTED_NAME} ${CONTAINER_NAME}:/mace - done - - if [[ x"$TARGET_ABI" != x"host" ]]; 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 -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 - FORMATTED_NAME=$(sed s/[^[:alnum:]]/_/g <<< ${NAME}) - docker cp ${MODEL_OUTPUT_DIR}/${OUTPUT_FILE_NAME}_${FORMATTED_NAME} ${CONTAINER_NAME}:/mace - done - - MODEL_FILE_NAME=$(basename ${MODEL_FILE_PATH}) - WEIGHT_FILE_NAME=$(basename ${WEIGHT_FILE_PATH}) - docker cp tools/validate.py ${CONTAINER_NAME}:/mace - docker cp ${MODEL_FILE_PATH} ${CONTAINER_NAME}:/mace - docker cp ${WEIGHT_FILE_PATH} ${CONTAINER_NAME}:/mace - docker exec ${CONTAINER_NAME} python -u /mace/validate.py \ - --platform=caffe \ - --model_file /mace/${MODEL_FILE_NAME} \ - --weight_file /mace/${WEIGHT_FILE_NAME} \ - --input_file /mace/${INPUT_FILE_NAME} \ - --mace_out_file /mace/${OUTPUT_FILE_NAME} \ - --mace_runtime ${RUNTIME} \ - --input_node ${INPUT_NODES} \ - --output_node ${OUTPUT_NODES} \ - --input_shape ${INPUT_SHAPES} \ - --output_shape ${OUTPUT_SHAPES} || exit 1 - -fi diff --git a/tools/wino_conv.py b/tools/wino_conv.py index fc1c90d8..130bcbe2 100644 --- a/tools/wino_conv.py +++ b/tools/wino_conv.py @@ -1,3 +1,17 @@ +# Copyright 2018 Xiaomi, Inc. 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. + import numpy as np import math import tensorflow as tf -- GitLab