diff --git a/mace/core/file_storage.cc b/mace/core/file_storage.cc index 5f6f07774dc12b71e259343c93f2d5b3ac603d3e..d0ac3d7833a6e9da3417e787aa4380bb1a0d9b8b 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 1bafd5e525488e000999544e082c11ca34544b37..d04dee4b4b6512a7cb1f08b0c849341daac1de56 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 @@ -15,10 +29,10 @@ import numpy as np FLAGS = None -def generate_cpp_source(): +def generate_cpp_source(binary_dirs, binary_file_name, variable_name): data_map = {} - for binary_dir in FLAGS.binary_dirs.split(","): - binary_path = os.path.join(binary_dir, FLAGS.binary_file_name) + for binary_dir in binary_dirs.split(","): + binary_path = os.path.join(binary_dir, binary_file_name) if not os.path.exists(binary_path): continue @@ -49,16 +63,19 @@ def generate_cpp_source(): return env.get_template('str2vec_maps.cc.jinja2').render( maps=data_map, data_type='unsigned int', - variable_name=FLAGS.variable_name) + variable_name=variable_name) -def main(unused_args): - cpp_binary_source = generate_cpp_source() - if os.path.isfile(FLAGS.output_path): - os.remove(FLAGS.output_path) - w_file = open(FLAGS.output_path, "w") - w_file.write(cpp_binary_source) - w_file.close() +def tuning_param_codegen(binary_dirs, + binary_file_name, + output_path, + variable_name): + cpp_binary_source = generate_cpp_source( + binary_dirs, binary_file_name, variable_name) + if os.path.isfile(output_path): + os.remove(output_path) + with open(output_path, "w") as w_file: + w_file.write(cpp_binary_source) def parse_args(): @@ -87,4 +104,7 @@ def parse_args(): if __name__ == '__main__': FLAGS, unparsed = parse_args() - main(unused_args=[sys.argv[0]] + unparsed) + tuning_param_codegen(FLAGS.binary_dirs, + FLAGS.binary_file_name, + FLAGS.output_path, + FLAGS.variable_name) diff --git a/mace/python/tools/caffe_converter_lib.py b/mace/python/tools/caffe_converter_lib.py index 69950ccd990dd801207ee9d0d572f034d63af6f5..ca1e8086e38e5a23b90cad3c4c65297032239c43 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 574e1e58f0a77ca85fb497d6284d1064dc43bc5a..c4fcba43d22d6cf25324dd20169e013394dd7490 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 c4592d5ab11f1f56c14ac78050cbcd0103834168..b14d891250069194e78dbf657bdc8649b3b7b8d4 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 72a2f497c9418d70f9ad1f28e7f838c3aeac43ba..f5bd7b70b3984195bc611baac1a2229400dcaab2 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 b541aef5b1ab34a2648e0a765830d7ba4fda2573..1c227ab98fe6aed5ed021dc342db589e65e0c6b6 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 @@ -22,30 +36,30 @@ def encrypt_code(code_str): return encrypted_arr -def main(unused_args): - if not os.path.exists(FLAGS.cl_kernel_dir): - print("Input cl_kernel_dir " + FLAGS.cl_kernel_dir + " doesn't exist!") +def encrypt_opencl_codegen(cl_kernel_dir, output_path): + if not os.path.exists(cl_kernel_dir): + print("Input cl_kernel_dir " + cl_kernel_dir + " doesn't exist!") header_code = "" - for file_name in os.listdir(FLAGS.cl_kernel_dir): - file_path = os.path.join(FLAGS.cl_kernel_dir, file_name) + for file_name in os.listdir(cl_kernel_dir): + file_path = os.path.join(cl_kernel_dir, file_name) if file_path[-2:] == ".h": - f = open(file_path, "r") - header_code += f.read() + with open(file_path, "r") as f: + header_code += f.read() encrypted_code_maps = {} - for file_name in os.listdir(FLAGS.cl_kernel_dir): - file_path = os.path.join(FLAGS.cl_kernel_dir, file_name) + for file_name in os.listdir(cl_kernel_dir): + file_path = os.path.join(cl_kernel_dir, file_name) if file_path[-3:] == ".cl": - f = open(file_path, "r") - code_str = "" - for line in f.readlines(): - if "#include " in line: - code_str += header_code - else: - code_str += line - encrypted_code_arr = encrypt_code(code_str) - encrypted_code_maps[file_name[:-3]] = encrypted_code_arr + with open(file_path, "r") as f: + code_str = "" + for line in f.readlines(): + if "#include " in line: + code_str += header_code + else: + code_str += line + encrypted_code_arr = encrypt_code(code_str) + encrypted_code_maps[file_name[:-3]] = encrypted_code_arr env = jinja2.Environment(loader=jinja2.FileSystemLoader(sys.path[0])) cpp_cl_encrypted_kernel = env.get_template( @@ -54,11 +68,10 @@ def main(unused_args): data_type='unsigned char', variable_name='kEncryptedProgramMap') - if os.path.isfile(FLAGS.output_path): - os.remove(FLAGS.output_path) - w_file = open(FLAGS.output_path, "w") - w_file.write(cpp_cl_encrypted_kernel) - w_file.close() + if os.path.isfile(output_path): + os.remove(output_path) + with open(output_path, "w") as w_file: + w_file.write(cpp_cl_encrypted_kernel) print("Generate encrypted opencl source done!") @@ -81,4 +94,4 @@ def parse_args(): if __name__ == '__main__': FLAGS, unparsed = parse_args() - main(unused_args=[sys.argv[0]] + unparsed) + encrypt_opencl_codegen(FLAGS.cl_kernel_dir, FLAGS.output_path) diff --git a/mace/python/tools/graph_util.py b/mace/python/tools/graph_util.py index 29072ae2dfe3a50315689f51d77828387dd4345e..22edb43a01c710e0cc2a29fb417f778634d61395 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 01f271626b34d7333a17b24d0b9bf679f13ade11..fddb50e276d9f23f00ced9b666681467585283ee 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 061dd25b09c695b80a3619badbd8c42c918eb61e..c21e5b974df0ff767607398336090c385b3a7608 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 @@ -13,12 +27,14 @@ import jinja2 FLAGS = None -def generate_cpp_source(): +def generate_cpp_source(cl_binary_dirs, + built_kernel_file_name, + platform_info_file_name): maps = {} platform_info = '' - binary_dirs = FLAGS.cl_binary_dirs.strip().split(",") + binary_dirs = cl_binary_dirs.strip().split(",") for binary_dir in binary_dirs: - binary_path = os.path.join(binary_dir, FLAGS.built_kernel_file_name) + binary_path = os.path.join(binary_dir, built_kernel_file_name) if not os.path.exists(binary_path): continue @@ -45,7 +61,7 @@ def generate_cpp_source(): maps[key].append(hex(ele)) cl_platform_info_path = os.path.join(binary_dir, - FLAGS.platform_info_file_name) + platform_info_file_name) with open(cl_platform_info_path, 'r') as f: curr_platform_info = f.read() if platform_info != "": @@ -61,14 +77,17 @@ def generate_cpp_source(): ) -def main(unused_args): - - cpp_cl_binary_source = generate_cpp_source() - if os.path.isfile(FLAGS.output_path): - os.remove(FLAGS.output_path) - w_file = open(FLAGS.output_path, "w") - w_file.write(cpp_cl_binary_source) - w_file.close() +def opencl_codegen(output_path, + cl_binary_dirs="", + built_kernel_file_name="", + platform_info_file_name=""): + cpp_cl_binary_source = generate_cpp_source(cl_binary_dirs, + built_kernel_file_name, + platform_info_file_name) + if os.path.isfile(output_path): + os.remove(output_path) + with open(output_path, "w") as w_file: + w_file.write(cpp_cl_binary_source) def parse_args(): @@ -99,4 +118,7 @@ def parse_args(): if __name__ == '__main__': FLAGS, unparsed = parse_args() - main(unused_args=[sys.argv[0]] + unparsed) + opencl_codegen(FLAGS.output_path, + FLAGS.cl_binary_dirs, + FLAGS.built_kernel_file_name, + FLAGS.platform_info_file_name) diff --git a/mace/python/tools/source_converter_lib.py b/mace/python/tools/source_converter_lib.py index 3bae0310c42e2bb9da0ec378ce56e939c6abb4c4..9d6bc8970d84b4c77303cce66798a4d3bb5bedb2 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 @@ -159,9 +173,8 @@ def convert_to_source(net_def, mode_pb_checksum, template_dir, obfuscate, with open(output_dir + 'tensor_data' + '.cc', "wb") as f: f.write(source) if not embed_model_data: - f = open(output_dir + model_tag + '.data', "wb") - f.write(bytearray(model_data)) - f.close() + with open(output_dir + model_tag + '.data', "wb") as f: + f.write(bytearray(model_data)) # generate op source files template_name = 'operator.jinja2' diff --git a/mace/python/tools/tf_converter_lib.py b/mace/python/tools/tf_converter_lib.py index 1d4aac42e0c9ae8ef310993c55c6ed1161be0ac9..4079c953de0d26544cd3b63f060792d968b49b3d 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 62269cf0546ed744423fb9cf7470ee012d8a8092..65369b4625a9ead2c176921d661844cbb731a3d8 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 303ec77b32c3c7d8943af9bd0913544db5b30b9b..02b82f5c417ba53653525b741f397edfc195247a 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 e11a72d0a92c1f367f266f73768721146d0edfeb..b542f93a58f04ee3cd147389f68a245948da6165 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 d4d8dcbfcfc44d39c369715086308574278a2282..0000000000000000000000000000000000000000 --- 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 4d116c9fec7c140a2078e0d6f28e1c5181468e51..0000000000000000000000000000000000000000 --- 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 7b1c33d219a6a886c29335deff8c4bc6661c39c4..0000000000000000000000000000000000000000 --- 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 ca418472377dd8753e19f81bdcbca039fabea737..39b0bba674744d3148c432bc7a8bd382de3d2c49 100644 --- a/tools/mace_tools.py +++ b/tools/mace_tools.py @@ -1,16 +1,27 @@ -#!/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 \ # --config=tools/example.yaml \ # --round=100 \ # --mode=all import argparse +import filelock import hashlib import os import sh -import shutil import subprocess import sys import urllib @@ -22,24 +33,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 + + +def get_data_and_device_type(runtime): + data_type = "" + device_type = "" - if out: - print("Stdout msg:\n{}".format(out)) - if err: - print("Stderr msg:\n{}".format(err)) + 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" - if result.returncode != 0: - raise Exception( - "Exit not 0 from bash with code: {}, command: {}".format( - result.returncode, command)) + 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 +84,37 @@ 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 gen_opencl_and_tuning_code(target_soc, + target_abi, + model_output_dirs, + pull_or_not): + if pull_or_not: + sh_commands.pull_binaries( + target_soc, target_abi, model_output_dirs) + + codegen_path = "mace/codegen" + + # generate opencl binary code + sh_commands.gen_opencl_binary_code(target_soc, model_output_dirs) + + sh_commands.gen_tuning_param_code( + target_soc, model_output_dirs) + + +def model_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 +128,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 +137,131 @@ 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, + phone_data_dir, + 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, + phone_data_dir, + option_args) + model_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, phone_data_dir): + gen_opencl_and_tuning_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, + phone_data_dir=phone_data_dir, 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, + phone_data_dir=phone_data_dir, tuning=tuning, + limit_opencl_kernel_time=limit_opencl_kernel_time) + + gen_opencl_and_tuning_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): + gen_opencl_and_tuning_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 +319,182 @@ 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, phone_data_dir, 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, phone_data_dir) + + 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"], + phone_data_dir) + + 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, + phone_data_dir) + + 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, + phone_data_dir, + 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, + phone_data_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", ""), + phone_data_dir) def main(unused_args): @@ -384,126 +504,45 @@ 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) + phone_data_dir = "/data/local/tmp/mace_run/" 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, + phone_data_dir, 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 90bfa7d96a104775bc344975649c47e411f783a3..0000000000000000000000000000000000000000 --- 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 c6158cd5f9c954211d858526a4e560d9ceab8a0b..0000000000000000000000000000000000000000 --- 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 40cc932a33977fa34c0c3b3b75156001966e871c..f54c0a0d767e7cea8f29fad7c0e2356a39a03e19 100644 --- a/tools/sh_commands.py +++ b/tools/sh_commands.py @@ -1,10 +1,41 @@ +# 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 sys import time +sys.path.insert(0, "mace/python/tools") +try: + from encrypt_opencl_codegen import encrypt_opencl_codegen + from opencl_codegen import opencl_codegen + from binary_codegen import tuning_param_codegen + from generate_data import generate_input_data + from validate import validate +except Exception: + print("Error: import error.") + print("Does the script run at the root dir of mace project?") + exit(1) + + ################################ # common ################################ @@ -36,6 +67,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, + phone_data_dir, + model_codegen_dir="mace/codegen/models"): + if abi != "host": + serialno = adb_devices([target_soc]).pop() + sh.adb("-s", + serialno, + "shell", + "rm -rf %s" % phone_data_dir) + if os.path.exists(model_codegen_dir): + sh.rm("-rf", model_codegen_dir) + + ################################ # adb commands ################################ @@ -92,6 +145,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 +179,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 +201,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) @@ -181,13 +297,69 @@ def bazel_target_to_bin(target): ################################ # mace commands ################################ -# TODO this should be refactored def gen_encrypted_opencl_source(codegen_path="mace/codegen"): sh.mkdir("-p", "%s/opencl" % codegen_path) - sh.python( - "mace/python/tools/encrypt_opencl_codegen.py", - "--cl_kernel_dir=./mace/kernels/opencl/cl/", - "--output_path=%s/opencl/opencl_encrypt_program.cc" % codegen_path) + encrypt_opencl_codegen("./mace/kernels/opencl/cl/", + "mace/codegen/opencl/opencl_encrypt_program.cc") + + +def pull_binaries(target_soc, abi, model_output_dirs): + serialno = adb_devices([target_soc]).pop() + compiled_opencl_dir = "/data/local/tmp/mace_run/cl_program/" + mace_run_param_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: + 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_param_file, + cl_bin_dir, serialno) + + +def gen_opencl_binary_code(target_soc, + model_output_dirs, + codegen_path="mace/codegen"): + cl_built_kernel_file_name = "mace_cl_compiled_program.bin" + cl_platform_info_file_name = "mace_cl_platform_info.txt" + opencl_codegen_file = "%s/opencl/opencl_compiled_program.cc" % codegen_path + + serialno = adb_devices([target_soc]).pop() + + 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) + opencl_codegen(opencl_codegen_file, + cl_bin_dirs_str, + cl_built_kernel_file_name, + cl_platform_info_file_name) + + +def gen_tuning_param_code(target_soc, + model_output_dirs, + codegen_path="mace/codegen"): + mace_run_param_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) + + tuning_codegen_dir = "%s/tuning/" % codegen_path + if not os.path.exists(tuning_codegen_dir): + sh.mkdir("-p", tuning_codegen_dir) + + tuning_param_variable_name = "kTuningParamsData" + tuning_param_codegen(cl_bin_dirs_str, + mace_run_param_file, + "%s/tuning_params.cc" % tuning_codegen_dir, + tuning_param_variable_name) def gen_mace_version(codegen_path="mace/codegen"): @@ -197,10 +369,655 @@ def gen_mace_version(codegen_path="mace/codegen"): def gen_compiled_opencl_source(codegen_path="mace/codegen"): + opencl_codegen_file = "%s/opencl/opencl_compiled_program.cc" % codegen_path sh.mkdir("-p", "%s/opencl" % codegen_path) - sh.python( - "mace/python/tools/opencl_codegen.py", - "--output_path=%s/opencl/opencl_compiled_program.cc" % codegen_path) + opencl_codegen(opencl_codegen_file) + + +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) + generate_input_data("%s/%s" % (model_output_dir, input_file_name), + input_nodes_str, + 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("-f", 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("-f", 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("-f", "bazel-bin/mace/tools/validation/mace_run", model_output_dir) + + if embed_model_data == 0: + sh.cp("-f", "mace/codegen/models/%s/%s.data" % (model_tag, model_tag), + model_output_dir) + + sh.cp("-f", "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, + phone_data_dir, + 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() + 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, + phone_data_dir, + input_file_name="model_input", + output_file_name="model_out"): + print("* Validate with %s" % platform) + serialno = adb_devices([target_soc]).pop() + + 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) + validate(platform, model_file_path, "", + "%s/%s" % (model_output_dir, input_file_name), + "%s/%s" % (model_output_dir, output_file_name), runtime, + ":".join(input_shapes), ":".join(output_shapes), + ",".join(input_nodes), ",".join(output_nodes)) + 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) + + stdout_buff = [] + process_output = make_output_processor(stdout_buff) + 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") + + +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) + sh.cp("-f", glob.glob("mace/public/*.h"), model_header_dir) + if not os.path.exists(model_data_dir): + sh.mkdir("-p", model_data_dir) + if hexagon_mode: + sh.cp("-f", 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: + sh.cp("-f", glob.glob("%s/*.data" % model_output_dir), + model_data_dir) + sh.cp("-f", glob.glob("%s/*.h" % model_output_dir), 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, + phone_data_dir, + 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("-f", "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("-f", 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() + 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, + phone_data_dir, + strip="always", + input_file_name="model_input"): + print("* Build and run throughput_test") + 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("-f", 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") ################################ diff --git a/tools/tuning_run.sh b/tools/tuning_run.sh deleted file mode 100644 index 9499d792ba217d1415d7bcaff238825949b3fc73..0000000000000000000000000000000000000000 --- 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 0.999) or \ - (FLAGS.mace_runtime == "neon" and similarity > 0.999) or \ - (FLAGS.mace_runtime == "gpu" and similarity > 0.995) or \ - (FLAGS.mace_runtime == "dsp" and similarity > 0.930): + if (mace_runtime == "cpu" and similarity > 0.999) or \ + (mace_runtime == "neon" and similarity > 0.999) or \ + (mace_runtime == "gpu" and similarity > 0.995) or \ + (mace_runtime == "dsp" and similarity > 0.930): print '===================Similarity Test Passed==================' else: print '===================Similarity Test Failed==================' @@ -53,14 +68,15 @@ def compare_output(output_name, mace_out_value, out_value): sys.exit(-1) -def validate_tf_model(input_names, input_shapes, output_names): +def validate_tf_model(platform, mace_runtime, model_file, input_file, + mace_out_file, input_names, input_shapes, output_names): import tensorflow as tf - if not os.path.isfile(FLAGS.model_file): - print("Input graph file '" + FLAGS.model_file + "' does not exist!") + if not os.path.isfile(model_file): + print("Input graph file '" + model_file + "' does not exist!") sys.exit(-1) input_graph_def = tf.GraphDef() - with open(FLAGS.model_file, "rb") as f: + with open(model_file, "rb") as f: data = f.read() input_graph_def.ParseFromString(data) tf.import_graph_def(input_graph_def, name="") @@ -71,7 +87,7 @@ def validate_tf_model(input_names, input_shapes, output_names): input_dict = {} for i in range(len(input_names)): input_value = load_data( - FLAGS.input_file + "_" + format_name(input_names[i])) + input_file + "_" + format_name(input_names[i])) input_value = input_value.reshape(input_shapes[i]) input_node = graph.get_tensor_by_name( input_names[i] + ':0') @@ -83,31 +99,31 @@ def validate_tf_model(input_names, input_shapes, output_names): [graph.get_tensor_by_name(name + ':0')]) output_values = session.run(output_nodes, feed_dict=input_dict) for i in range(len(output_names)): - output_file_name = FLAGS.mace_out_file + "_" + \ + output_file_name = mace_out_file + "_" + \ format_name(output_names[i]) mace_out_value = load_data(output_file_name) - compare_output(output_names[i], mace_out_value, - output_values[i]) + compare_output(platform, mace_runtime, output_names[i], + mace_out_value, output_values[i]) -def validate_caffe_model(input_names, input_shapes, output_names, - output_shapes): - os.environ['GLOG_minloglevel'] = '1' # suppress Caffe verbose prints +def validate_caffe_model(platform, mace_runtime, model_file, input_file, + mace_out_file, weight_file, input_names, input_shapes, + output_names, output_shapes): + os.environ['GLOG_minloglevel'] = '1' # suprress Caffe verbose prints import caffe - if not os.path.isfile(FLAGS.model_file): - print("Input graph file '" + FLAGS.model_file + "' does not exist!") + if not os.path.isfile(model_file): + print("Input graph file '" + model_file + "' does not exist!") sys.exit(-1) - if not os.path.isfile(FLAGS.weight_file): - print("Input weight file '" + FLAGS.weight_file + "' does not exist!") + if not os.path.isfile(weight_file): + print("Input weight file '" + weight_file + "' does not exist!") sys.exit(-1) caffe.set_mode_cpu() - net = caffe.Net(FLAGS.model_file, caffe.TEST, weights=FLAGS.weight_file) + net = caffe.Net(model_file, caffe.TEST, weights=weight_file) for i in range(len(input_names)): - input_value = load_data(FLAGS.input_file + "_" + - format_name(input_names[i])) + input_value = load_data(input_file + "_" + format_name(input_names[i])) input_value = input_value.reshape(input_shapes[i]).transpose((0, 3, 1, 2)) input_blob_name = input_names[i] @@ -126,28 +142,33 @@ def validate_caffe_model(input_names, input_shapes, output_names, out_shape[1], out_shape[2], out_shape[3] = out_shape[3], out_shape[ 1], out_shape[2] value = value.reshape(out_shape).transpose((0, 2, 3, 1)) - output_file_name = FLAGS.mace_out_file + "_" + format_name( + output_file_name = mace_out_file + "_" + format_name( output_names[i]) mace_out_value = load_data(output_file_name) - compare_output(output_names[i], mace_out_value, value) + compare_output(platform, mace_runtime, output_names[i], mace_out_value, + value) -def main(unused_args): - input_names = [name for name in FLAGS.input_node.split(',')] - input_shape_strs = [shape for shape in FLAGS.input_shape.split(':')] +def validate(platform, model_file, weight_file, input_file, mace_out_file, + mace_runtime, input_shape, output_shape, input_node, output_node): + input_names = [name for name in input_node.split(',')] + input_shape_strs = [shape for shape in input_shape.split(':')] input_shapes = [[int(x) for x in shape.split(',')] for shape in input_shape_strs] - output_names = [name for name in FLAGS.output_node.split(',')] + output_names = [name for name in output_node.split(',')] assert len(input_names) == len(input_shapes) - if FLAGS.platform == 'tensorflow': - validate_tf_model(input_names, input_shapes, output_names) - elif FLAGS.platform == 'caffe': - output_shape_strs = [shape for shape in FLAGS.output_shape.split(':')] + if platform == 'tensorflow': + validate_tf_model(platform, mace_runtime, model_file, input_file, + mace_out_file, input_names, input_shapes, + output_names) + elif platform == 'caffe': + output_shape_strs = [shape for shape in output_shape.split(':')] output_shapes = [[int(x) for x in shape.split(',')] for shape in output_shape_strs] - validate_caffe_model(input_names, input_shapes, output_names, - output_shapes) + validate_caffe_model(platform, mace_runtime, model_file, input_file, + mace_out_file, weight_file, input_names, + input_shapes, output_names, output_shapes) def parse_args(): @@ -189,4 +210,13 @@ def parse_args(): if __name__ == '__main__': FLAGS, unparsed = parse_args() - main(unused_args=[sys.argv[0]] + unparsed) + validate(FLAGS.platform, + FLAGS.model_file, + FLAGS.weight_file, + FLAGS.input_file, + FLAGS.mace_out_file, + FLAGS.mace_runtime, + FLAGS.input_shape, + FLAGS.output_shape, + FLAGS.input_node, + FLAGS.output_node) diff --git a/tools/validate_tools.sh b/tools/validate_tools.sh deleted file mode 100644 index a2864ee46773db2e7cf5e562eaee3044694f41e0..0000000000000000000000000000000000000000 --- a/tools/validate_tools.sh +++ /dev/null @@ -1,114 +0,0 @@ -#!/bin/bash - -Usage() { - echo "Usage: bash tools/validate_tools.sh target_soc model_output_dir generate_data_or_not" -} - -if [ $# -lt 3 ]; then - Usage - exit 1 -fi - -CURRENT_DIR=`dirname $0` -source ${CURRENT_DIR}/env.sh - -TARGET_SOC=$1 -MODEL_OUTPUT_DIR=$2 -GENERATE_DATA_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 - -IFS=',' read -r -a INPUT_NAMES <<< "${INPUT_NODES}" -IFS=',' read -r -a OUTPUT_NAMES <<< "${OUTPUT_NODES}" - -echo $MODEL_OUTPUT_DIR -if [ "$GENERATE_DATA_OR_NOT" = 1 ]; then - for NAME in "${INPUT_NAMES[@]}";do - FORMATTED_NAME=$(sed s/[^[:alnum:]]/_/g <<< ${NAME}) - rm -rf ${MODEL_OUTPUT_DIR}/${INPUT_FILE_NAME}_${FORMATTED_NAME} - done - python -u tools/generate_data.py --input_node=${INPUT_NODES} \ - --input_file=${MODEL_OUTPUT_DIR}/${INPUT_FILE_NAME} \ - --input_shape="${INPUT_SHAPES}" || exit 1 - exit 0 -fi - -if [ "$PLATFORM" == "tensorflow" ];then - 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 - 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 fc1c90d80876b57e3df1674c08e8f616a19a6567..130bcbe2901af6060463fe6951bee8b6b90634d8 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