From: @yeyunpeng2020 Reviewed-by: Signed-off-by:tags/v1.1.0
| @@ -55,7 +55,7 @@ if (BUILD_MINDDATA STREQUAL "lite") | |||
| endif () | |||
| if (BUILD_MINDDATA STREQUAL "lite_cv") | |||
| if (PLATFORM_ARM64) | |||
| if (PLATFORM_ARM64) | |||
| install(DIRECTORY ${TOP_DIR}/mindspore/ccsrc/minddata/dataset/kernels/image/lite_cv DESTINATION ${MIND_DATA_INC_DIR} COMPONENT ${COMPONENT_NAME} FILES_MATCHING PATTERN "*.h") | |||
| install(FILES ${TOP_DIR}/mindspore/lite/build/minddata/libminddata-lite.so DESTINATION ${MIND_DATA_LIB_DIR} COMPONENT ${COMPONENT_NAME}) | |||
| elseif (PLATFORM_ARM32) | |||
| @@ -81,7 +81,7 @@ if (PLATFORM_ARM64) | |||
| install(DIRECTORY ${flatbuffers_INC} DESTINATION ${FLATBF_DIR} COMPONENT ${COMPONENT_NAME}) | |||
| if (ENABLE_TOOLS) | |||
| install(TARGETS benchmark RUNTIME DESTINATION ${MAIN_DIR}-${COMPONENT_NAME}/benchmark COMPONENT ${COMPONENT_NAME}) | |||
| endif() | |||
| endif () | |||
| elseif (PLATFORM_ARM32) | |||
| if (SUPPORT_TRAIN) | |||
| install(DIRECTORY ${TOP_DIR}/mindspore/lite/include/ DESTINATION ${INC_DIR} COMPONENT ${COMPONENT_NAME} FILES_MATCHING PATTERN "*.h") | |||
| @@ -96,7 +96,7 @@ elseif (PLATFORM_ARM32) | |||
| install(DIRECTORY ${flatbuffers_INC} DESTINATION ${FLATBF_DIR} COMPONENT ${COMPONENT_NAME}) | |||
| if (ENABLE_TOOLS) | |||
| install(TARGETS benchmark RUNTIME DESTINATION ${MAIN_DIR}-${COMPONENT_NAME}/benchmark COMPONENT ${COMPONENT_NAME}) | |||
| endif() | |||
| endif () | |||
| elseif (WIN32) | |||
| get_filename_component(CXX_DIR ${CMAKE_CXX_COMPILER} PATH) | |||
| file(GLOB LIB_LIST ${CXX_DIR}/libstdc++-6.dll ${CXX_DIR}/libwinpthread-1.dll ${CXX_DIR}/libssp-0.dll ${CXX_DIR}/libgcc_s_seh-1.dll) | |||
| @@ -104,7 +104,7 @@ elseif (WIN32) | |||
| install(TARGETS converter_lite RUNTIME DESTINATION ${MAIN_DIR}-${COMPONENT_NAME}/converter COMPONENT ${COMPONENT_NAME}) | |||
| install(FILES ${LIB_LIST} DESTINATION ${MAIN_DIR}-${COMPONENT_NAME}/converter COMPONENT ${COMPONENT_NAME}) | |||
| install(FILES ${TOP_DIR}/build/mindspore/tools/converter/mindspore_core/gvar/libmindspore_gvar.dll DESTINATION ${MAIN_DIR}-${COMPONENT_NAME}/converter COMPONENT ${COMPONENT_NAME}) | |||
| install(FILES ${glog_LIBPATH}/../bin/libglog.dll DESTINATION ${MAIN_DIR}-${COMPONENT_NAME}/converter COMPONENT ${COMPONENT_NAME}) | |||
| install(FILES ${glog_LIBPATH}/../bin/libglog.dll DESTINATION ${MAIN_DIR}-${COMPONENT_NAME}/converter COMPONENT ${COMPONENT_NAME}) | |||
| endif () | |||
| if (ENABLE_TOOLS) | |||
| install(TARGETS benchmark RUNTIME DESTINATION ${MAIN_DIR}-${WIN_RUN_X86_NAME}/benchmark COMPONENT ${WIN_RUN_X86_NAME}) | |||
| @@ -123,7 +123,7 @@ elseif (WIN32) | |||
| install(FILES ${TOP_DIR}/build/mindspore/src/libmindspore-lite.a DESTINATION ${WIN_LIB_DIR_RUN_X86} COMPONENT ${WIN_RUN_X86_NAME}) | |||
| install(FILES ${TOP_DIR}/build/mindspore/src/libmindspore-lite.dll.a DESTINATION ${WIN_LIB_DIR_RUN_X86} COMPONENT ${WIN_RUN_X86_NAME}) | |||
| install(FILES ${TOP_DIR}/build/mindspore/src/libmindspore-lite.dll DESTINATION ${WIN_LIB_DIR_RUN_X86} COMPONENT ${WIN_RUN_X86_NAME}) | |||
| endif() | |||
| endif () | |||
| else () | |||
| if (SUPPORT_TRAIN) | |||
| install(DIRECTORY ${TOP_DIR}/mindspore/lite/include/ DESTINATION ${INC_DIR_RUN_X86} COMPONENT ${RUN_X86_COMPONENT_NAME} FILES_MATCHING PATTERN "*.h") | |||
| @@ -140,10 +140,12 @@ else () | |||
| install(TARGETS converter_lite RUNTIME DESTINATION ${MAIN_DIR}-${COMPONENT_NAME}/converter COMPONENT ${COMPONENT_NAME}) | |||
| install(FILES ${TOP_DIR}/mindspore/lite/build/tools/converter/mindspore_core/gvar/libmindspore_gvar.so DESTINATION ${MAIN_DIR}-${COMPONENT_NAME}/lib COMPONENT ${COMPONENT_NAME}) | |||
| install(FILES ${glog_LIBPATH}/libglog.so.0.4.0 DESTINATION ${MAIN_DIR}-${COMPONENT_NAME}/third_party/glog/lib RENAME libglog.so.0 COMPONENT ${COMPONENT_NAME}) | |||
| endif() | |||
| endif () | |||
| if (ENABLE_TOOLS) | |||
| install(TARGETS benchmark RUNTIME DESTINATION ${MAIN_DIR}-${RUN_X86_COMPONENT_NAME}/benchmark COMPONENT ${RUN_X86_COMPONENT_NAME}) | |||
| endif() | |||
| install(TARGETS lib_cropper RUNTIME DESTINATION ${MAIN_DIR}-${RUN_X86_COMPONENT_NAME}/lib_cropper COMPONENT ${RUN_X86_COMPONENT_NAME}) | |||
| install(FILES ${TOP_DIR}/mindspore/lite/build/tools/lib_cropper/cropper_mapping_cpu.cfg DESTINATION ${MAIN_DIR}-${RUN_X86_COMPONENT_NAME}/lib_cropper COMPONENT ${RUN_X86_COMPONENT_NAME}) | |||
| endif () | |||
| endif () | |||
| if (CMAKE_SYSTEM_NAME MATCHES "Windows") | |||
| @@ -164,6 +166,6 @@ if (WIN32) | |||
| set(CPACK_PACKAGE_DIRECTORY ${TOP_DIR}/output) | |||
| else () | |||
| set(CPACK_PACKAGE_DIRECTORY ${TOP_DIR}/output/tmp) | |||
| endif() | |||
| endif () | |||
| set(CPACK_PACKAGE_CHECKSUM SHA256) | |||
| include(CPack) | |||
| @@ -223,6 +223,7 @@ if (NOT WIN32) | |||
| if (ENABLE_TOOLS) | |||
| if (NOT PLATFORM_ARM32 AND NOT PLATFORM_ARM64) | |||
| add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tools/schema_gen) | |||
| add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tools/lib_cropper) | |||
| endif () | |||
| endif() | |||
| if (BUILD_TESTCASES) | |||
| @@ -0,0 +1,20 @@ | |||
| # add shared link library | |||
| set(COMMON_SRC | |||
| ${CMAKE_CURRENT_SOURCE_DIR}/../common/flag_parser.cc | |||
| ${CMAKE_CURRENT_SOURCE_DIR}/../../src/common/file_utils.cc | |||
| ${CMAKE_CURRENT_SOURCE_DIR}/../../src/common/utils.cc | |||
| ) | |||
| add_executable(lib_cropper | |||
| ${CMAKE_CURRENT_SOURCE_DIR}/main.cc | |||
| ${CMAKE_CURRENT_SOURCE_DIR}/lib_cropper.cc | |||
| ${CMAKE_CURRENT_SOURCE_DIR}/cropper_flags.cc | |||
| ${CMAKE_CURRENT_SOURCE_DIR}/cropper_utils.cc | |||
| ${COMMON_SRC}) | |||
| add_dependencies(lib_cropper fbs_src) | |||
| target_link_libraries(lib_cropper mindspore-lite_static) | |||
| add_custom_command(TARGET lib_cropper POST_BUILD COMMAND | |||
| bash build_cropper_config.sh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) | |||
| @@ -0,0 +1,170 @@ | |||
| #!/bin/bash | |||
| CURRENT_PATH=$(pwd) | |||
| MINDSPORE_HOME="${CURRENT_PATH}/../../../.." | |||
| echo "MINDSPORE_HOME path is ${MINDSPORE_HOME}" | |||
| CROPPER_OUTPUT_DIR=${MINDSPORE_HOME}/mindspore/lite/build/tools/lib_cropper | |||
| mkdir -p ${CROPPER_OUTPUT_DIR} | |||
| MAPPING_OUTPUT_FILE_NAME_TMP=${CROPPER_OUTPUT_DIR}/cropper_mapping_cpu_tmp.cfg | |||
| MAPPING_OUTPUT_FILE_NAME=${CROPPER_OUTPUT_DIR}/cropper_mapping_cpu.cfg | |||
| echo "MAPPING_OUTPUT_FILE_NAME is ${MAPPING_OUTPUT_FILE_NAME}" | |||
| [ -n "${MAPPING_OUTPUT_FILE_NAME_TMP}" ] && rm -f ${MAPPING_OUTPUT_FILE_NAME_TMP} | |||
| [ -n "${MAPPING_OUTPUT_FILE_NAME}" ] && rm -f ${MAPPING_OUTPUT_FILE_NAME} | |||
| ops_list=() | |||
| DEFINE_STR="-DENABLE_ANDROID -DENABLE_ARM -DENABLE_ARM64 -DENABLE_NEON -DNO_DLIB -DUSE_ANDROID_LOG -DANDROID" | |||
| # get the flatbuffers path | |||
| if [ ${MSLIBS_CACHE_PATH} ]; then | |||
| FLATBUFFERS_LIST=($(ls -d ${MSLIBS_CACHE_PATH}/flatbuffers_*/include)) | |||
| FLATBUFFERS=${FLATBUFFERS_LIST[0]} | |||
| echo "FLATBUFFERS path is ${FLATBUFFERS}" | |||
| else | |||
| FLATBUFFERS=$(ls -d ${MINDSPORE_HOME}/mindspore/lite/build/.mslib/flatbuffers_*/include) | |||
| echo "FLATBUFFERS path is ${FLATBUFFERS}" | |||
| fi | |||
| HEADER_LOCATION="-I${MINDSPORE_HOME} | |||
| -I${MINDSPORE_HOME}/mindspore/core | |||
| -I${MINDSPORE_HOME}/mindspore/core/ir | |||
| -I${MINDSPORE_HOME}/mindspore/ccsrc | |||
| -I${MINDSPORE_HOME}/mindspore/lite | |||
| -I${MINDSPORE_HOME}/mindspore/lite/src/runtime/kernel/arm | |||
| -I${MINDSPORE_HOME}/third_party | |||
| -I${MINDSPORE_HOME}/mindspore/lite/build | |||
| -I${MINDSPORE_HOME}/cmake/../third_party/securec/include | |||
| -I${FLATBUFFERS} | |||
| -I${MINDSPORE_HOME}/mindspore/lite/build/schema | |||
| -I${MINDSPORE_HOME}/mindspore/lite/build/schema/inner | |||
| -I${MINDSPORE_HOME}/mindspore/lite/src/../nnacl | |||
| -I${MINDSPORE_HOME}/mindspore/lite/src/../nnacl/optimize" | |||
| REMOVE_LISTS_STR="" | |||
| getDeep() { | |||
| map_files=$(gcc -MM ${2} ${DEFINE_STR} ${HEADER_LOCATION}) | |||
| # first is *.o second is *.cc | |||
| array_deep=($(echo ${map_files} | awk -F '\' '{for(i=3;i<=NF;i++){print $i}}' | grep -E 'src/runtime|nnacl' | egrep -v ${REMOVE_LISTS_STR})) | |||
| for array_deep_file in ${array_deep[@]}; do | |||
| # only add existing files | |||
| if [[ -e ${array_deep_file%h*}cc ]]; then | |||
| file_split=$(echo ${array_deep_file} | awk -F '/' '{print $NF}') | |||
| echo "${1},${3},${file_split%h*}cc.o" >>${MAPPING_OUTPUT_FILE_NAME_TMP} | |||
| fi | |||
| if [[ -e ${array_deep_file%h*}c ]]; then | |||
| file_split=$(echo ${array_deep_file} | awk -F '/' '{print $NF}') | |||
| echo "${1},${3},${file_split%h*}c.o" >>${MAPPING_OUTPUT_FILE_NAME_TMP} | |||
| fi | |||
| done | |||
| } | |||
| getOpsFile() { | |||
| echo "start get operator mapping file $3" | |||
| for type in ${ops_list[@]}; do | |||
| # get mapping | |||
| ret=$(egrep -r -l "$1${type}," $2) | |||
| array=(${ret}) | |||
| for file in ${array[@]}; do | |||
| # delete \n | |||
| out_file=$(echo ${file} | awk -F '/' '{print $NF}') | |||
| # concat schemaType + fileType + fileName append to files | |||
| echo "${type},${3},${out_file}.o" >>${MAPPING_OUTPUT_FILE_NAME_TMP} | |||
| map_files=$(gcc -MM ${file} ${DEFINE_STR} ${HEADER_LOCATION}) | |||
| # first is *.o second is *.cc | |||
| array_file=($(echo ${map_files} | awk -F '\' '{for(i=3;i<=NF;i++){print $i}}' | grep -E 'src/runtime|nnacl' | egrep -v ${REMOVE_LISTS_STR})) | |||
| for array_file in ${array_file[@]}; do | |||
| # only add existing files | |||
| if [[ -e ${array_file%h*}cc ]]; then | |||
| getDeep ${type} ${array_file%h*}cc ${3} & | |||
| array_file_split=$(echo ${array_file} | awk -F '/' '{print $NF}') | |||
| echo "${type},${3},${array_file_split%h*}cc.o" >>${MAPPING_OUTPUT_FILE_NAME_TMP} | |||
| fi | |||
| if [[ -e ${array_file%h*}c ]]; then | |||
| getDeep ${type} ${array_file%h*}c ${3} & | |||
| array_file_split=$(echo ${array_file} | awk -F '/' '{print $NF}') | |||
| echo "${type},${3},${array_file_split%h*}c.o" >>${MAPPING_OUTPUT_FILE_NAME_TMP} | |||
| fi | |||
| done | |||
| done | |||
| done | |||
| } | |||
| getCommonFile() { | |||
| echo "start get common files" | |||
| include_h=($(ls ${MINDSPORE_HOME}/mindspore/lite/include/*.h)) | |||
| src_files_h=($(ls ${MINDSPORE_HOME}/mindspore/lite/src/*.h)) | |||
| common_files_h=($(ls ${MINDSPORE_HOME}/mindspore/lite/src/common/*.h)) | |||
| runtime_files_h=($(ls ${MINDSPORE_HOME}/mindspore/lite/src/runtime/*.h)) | |||
| others_files=( | |||
| ${MINDSPORE_HOME}/mindspore/lite/src/populate/populate_register.h | |||
| ${MINDSPORE_HOME}/mindspore/lite/src/ops/primitive_c.h | |||
| ${MINDSPORE_HOME}/mindspore/lite/nnacl/nnacl_utils.h | |||
| ${MINDSPORE_HOME}/mindspore/lite/nnacl/pack.h | |||
| ${MINDSPORE_HOME}/mindspore/lite/src/runtime/kernel/arm/fp16/common_fp16.h | |||
| ) | |||
| all_files_h=(${include_h[@]} ${src_files_h[@]} ${common_files_h[@]} ${runtime_files_h[@]} ${others_files[@]}) | |||
| # concat regx | |||
| REMOVE_LISTS_STR="${all_files_h[0]}" | |||
| for val in ${all_files_h[@]:1}; do | |||
| REMOVE_LISTS_STR="$REMOVE_LISTS_STR|$val" | |||
| done | |||
| src_files=($(ls ${MINDSPORE_HOME}/mindspore/lite/src/*.cc)) | |||
| common_files=($(ls ${MINDSPORE_HOME}/mindspore/lite/src/common/*.cc)) | |||
| runtime_files_cc=($(ls ${MINDSPORE_HOME}/mindspore/lite/src/runtime/*.cc)) | |||
| runtime_files_c=($(ls ${MINDSPORE_HOME}/mindspore/lite/src/runtime/*.c)) | |||
| # sava all assembly files | |||
| assembly_files=("$(ls ${MINDSPORE_HOME}/mindspore/lite/nnacl/assembly/*/*.S)") | |||
| others_files=( | |||
| ${MINDSPORE_HOME}/mindspore/lite/src/ops/primitive_c.cc | |||
| ${MINDSPORE_HOME}/mindspore/lite/nnacl/nnacl_utils.c | |||
| ${MINDSPORE_HOME}/mindspore/lite/nnacl/pack.c | |||
| ${MINDSPORE_HOME}/mindspore/lite/src/runtime/kernel/arm/fp16/common_fp16.cc | |||
| ${MINDSPORE_HOME}/mindspore/lite/src/ops/populate/arithmetic_populate.cc | |||
| ${MINDSPORE_HOME}/mindspore/lite/src/ops/populate/arithmetic_self_populate.cc | |||
| ) | |||
| all_files=(${src_files[@]} ${common_files[@]} ${runtime_files_cc[@]} ${runtime_files_c[@]} ${others_files[@]} ${assembly_files[@]}) | |||
| for file in ${all_files[@]}; do | |||
| map_files=$(gcc -MM ${file} ${DEFINE_STR} ${HEADER_LOCATION}) | |||
| # first is *.o second is *.cc | |||
| array_runtime=($(echo ${map_files} | awk -F '\' '{for(i=3;i<=NF;i++){print $i}}' | grep -v "flatbuffers" | egrep -v ${REMOVE_LISTS_STR})) | |||
| # only add existing files | |||
| for array_runtime_file in "${array_runtime[@]}"; do | |||
| if [[ -e ${array_runtime_file%h*}cc && ! ${all_files[*]} =~ ${array_runtime_file%h*}cc ]]; then | |||
| all_files=("${all_files[@]}" "${array_runtime_file%h*}cc") | |||
| fi | |||
| if [[ -e ${array_runtime_file%h*}c && ! ${all_files[*]} =~ ${array_runtime_file%h*}c ]]; then | |||
| all_files=("${all_files[@]}" "${array_runtime_file%h*}c") | |||
| fi | |||
| done | |||
| done | |||
| for file in ${all_files[@]}; do | |||
| file=$(echo ${file} | awk -F '/' '{print $NF}') | |||
| echo "CommonFile,common,${file}.o" >>${MAPPING_OUTPUT_FILE_NAME_TMP} & | |||
| done | |||
| wait | |||
| } | |||
| # automatically generate operator list | |||
| generateOpsList() { | |||
| echo "start generate operator list" | |||
| ops=($(egrep "PrimitiveType_.* = " "${MINDSPORE_HOME}/mindspore/lite/build/schema/model_generated.h" | awk -F '_' '{print $2}' | awk -F ' ' '{print $1}')) | |||
| ops_num=$((${#ops[@]} - 3)) | |||
| echo "ops nums:${ops_num}" | |||
| ops_list=${ops[@]:1:$ops_num} | |||
| } | |||
| echo "Start getting all file associations." | |||
| generateOpsList | |||
| getCommonFile | |||
| # get src/ops | |||
| getOpsFile "Registry\(schema::PrimitiveType_" "${MINDSPORE_HOME}/mindspore/lite/src/ops" "prototype" & | |||
| getOpsFile "REG_KERNEL\(.*?, kNumberTypeFloat32, PrimitiveType_" "${MINDSPORE_HOME}/mindspore/lite/src/runtime/kernel/arm" "kNumberTypeFloat32" & | |||
| getOpsFile "REG_KERNEL\(.*?, kNumberTypeFloat16, PrimitiveType_" "${MINDSPORE_HOME}/mindspore/lite/src/runtime/kernel/arm" "kNumberTypeFloat16" & | |||
| getOpsFile "REG_KERNEL\(.*?, kNumberTypeInt8, PrimitiveType_" "${MINDSPORE_HOME}/mindspore/lite/src/runtime/kernel/arm" "kNumberTypeInt8" & | |||
| wait | |||
| echo "remove duplicate files" | |||
| # remove duplicate files | |||
| sort ${MAPPING_OUTPUT_FILE_NAME_TMP} | uniq >${MAPPING_OUTPUT_FILE_NAME} | |||
| # modify file permissions to read-only | |||
| [ -n "${MAPPING_OUTPUT_FILE_NAME_TMP}" ] && rm -f ${MAPPING_OUTPUT_FILE_NAME_TMP} | |||
| chmod 444 ${MAPPING_OUTPUT_FILE_NAME} | |||
| echo "Complete all tasks." | |||
| @@ -0,0 +1,105 @@ | |||
| /** | |||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||
| * | |||
| * 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. | |||
| */ | |||
| #include "tools/lib_cropper/cropper_flags.h" | |||
| #include <string> | |||
| #include "tools/lib_cropper/cropper_utils.h" | |||
| #include "src/common/file_utils.h" | |||
| namespace mindspore { | |||
| namespace lite { | |||
| namespace cropper { | |||
| CropperFlags::CropperFlags() { | |||
| AddFlag(&CropperFlags::package_file_, "packageFile", "The libmindspore-lite.a file that needs to be cropped", ""); | |||
| AddFlag(&CropperFlags::model_file_, "modelFile", "List of model files, separated by commas", ""); | |||
| AddFlag(&CropperFlags::model_folder_path_, "modelFolderPath", "Load all ms models in the folder", ""); | |||
| AddFlag(&CropperFlags::config_file_, "configFile", "The mapping configuration file path", ""); | |||
| AddFlag(&CropperFlags::output_file_, "outputFile", "Output library file path", ""); | |||
| } | |||
| int CropperFlags::Init(int argc, const char **argv) { | |||
| if (argc == 1) { | |||
| std::cout << this->Usage() << std::endl; | |||
| return RET_SUCCESS_EXIT; | |||
| } | |||
| Option<std::string> err = this->ParseFlags(argc, argv); | |||
| if (err.IsSome()) { | |||
| std::cerr << err.Get(); | |||
| std::cerr << this->Usage() << std::endl; | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } | |||
| if (this->help) { | |||
| std::cout << this->Usage() << std::endl; | |||
| return RET_SUCCESS_EXIT; | |||
| } | |||
| MS_LOG(INFO) << "packageFile = " << this->package_file_; | |||
| MS_LOG(INFO) << "modelFile = " << this->model_file_; | |||
| MS_LOG(INFO) << "modelFolderPath = " << this->model_folder_path_; | |||
| MS_LOG(INFO) << "configFile = " << this->config_file_; | |||
| MS_LOG(INFO) << "outputFile = " << this->output_file_; | |||
| if (this->package_file_.empty()) { | |||
| std::cerr << "INPUT MISSING: packageFile is necessary" << std::endl; | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } else { | |||
| // Verify whether it is a static library file(.a) | |||
| if (ValidFileSuffix(this->package_file_, "a") != RET_OK) { | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } | |||
| this->package_file_ = RealPath(this->package_file_.c_str()); | |||
| if (this->package_file_.empty()) { | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } | |||
| } | |||
| if (this->model_file_.empty() && this->model_folder_path_.empty()) { | |||
| std::cerr << "INPUT MISSING: modelFile or modelFolderPath is necessary" << std::endl; | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } else if (!this->model_file_.empty() && !this->model_folder_path_.empty()) { | |||
| std::cerr << "INPUT MISSING: modelFile and modelFolderPath must choose one" << std::endl; | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } else if (!this->model_folder_path_.empty()) { | |||
| this->model_folder_path_ = RealPath(this->model_folder_path_.c_str()); | |||
| if (this->model_folder_path_.empty()) { | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } | |||
| } | |||
| if (this->config_file_.empty()) { | |||
| std::cerr << "INPUT MISSING: configFile is necessary" << std::endl; | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } | |||
| this->config_file_ = RealPath(this->config_file_.c_str()); | |||
| if (this->config_file_.empty()) { | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } | |||
| if (this->output_file_.empty()) { | |||
| this->output_file_ = this->package_file_; | |||
| } | |||
| this->output_file_ = RealPath(this->output_file_.c_str()); | |||
| if (this->output_file_.empty()) { | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| } // namespace cropper | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,45 @@ | |||
| /** | |||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||
| * | |||
| * 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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_TOOLS_LIB_CROPPER_LIB_CROPPER_FLAGS_H | |||
| #define MINDSPORE_LITE_TOOLS_LIB_CROPPER_LIB_CROPPER_FLAGS_H | |||
| #include <string> | |||
| #include "tools/common/flag_parser.h" | |||
| #include "ir/dtype/type_id.h" | |||
| namespace mindspore { | |||
| namespace lite { | |||
| namespace cropper { | |||
| class CropperFlags : public virtual mindspore::lite::FlagParser { | |||
| public: | |||
| CropperFlags(); | |||
| ~CropperFlags() override = default; | |||
| int Init(int argc, const char **argv); | |||
| public: | |||
| std::string package_file_; | |||
| std::string model_file_; | |||
| std::string model_folder_path_; | |||
| std::string config_file_; | |||
| std::string output_file_; | |||
| }; | |||
| } // namespace cropper | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| #endif | |||
| @@ -0,0 +1,53 @@ | |||
| /** | |||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||
| * | |||
| * 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. | |||
| */ | |||
| #include "tools/lib_cropper/cropper_utils.h" | |||
| #include <fstream> | |||
| #include <iostream> | |||
| #include "src/common/log_adapter.h" | |||
| #include "include/errorcode.h" | |||
| namespace mindspore { | |||
| namespace lite { | |||
| namespace cropper { | |||
| int ValidFileSuffix(const std::string &filename, const std::string &suffix) { | |||
| std::string suffixStr = filename.substr(filename.find_last_of('.') + 1); | |||
| if (suffix == suffixStr) { | |||
| return RET_OK; | |||
| } else { | |||
| MS_LOG(ERROR) << "The file name suffix needs: " << suffix << ", but file is " << filename; | |||
| return RET_ERROR; | |||
| } | |||
| } | |||
| int ValidFile(std::ifstream &in_file, const char *file_path) { | |||
| if (!in_file.good()) { | |||
| std::cerr << "file: " << file_path << " is not exist" << std::endl; | |||
| MS_LOG(ERROR) << "file: " << file_path << " is not exist"; | |||
| return RET_ERROR; | |||
| } | |||
| if (!in_file.is_open()) { | |||
| std::cerr << "file: " << file_path << " open failed" << std::endl; | |||
| MS_LOG(ERROR) << "file: " << file_path << " open failed"; | |||
| in_file.close(); | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| } // namespace cropper | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,28 @@ | |||
| /** | |||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||
| * | |||
| * 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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_TOOLS_LIB_CROPPER_LIB_CROPPER_UTILS_H | |||
| #define MINDSPORE_LITE_TOOLS_LIB_CROPPER_LIB_CROPPER_UTILS_H | |||
| #include <string> | |||
| namespace mindspore { | |||
| namespace lite { | |||
| namespace cropper { | |||
| int ValidFileSuffix(const std::string &filename, const std::string &suffix); | |||
| int ValidFile(std::ifstream &in_file, const char *file_path); | |||
| } // namespace cropper | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| #endif // MINDSPORE_LITE_TOOLS_CROPPER_CROPPER_UTILS_H | |||
| @@ -0,0 +1,276 @@ | |||
| /** | |||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||
| * | |||
| * 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. | |||
| */ | |||
| #include <memory> | |||
| #include <string> | |||
| #include "tools/lib_cropper/lib_cropper.h" | |||
| #include "tools/lib_cropper/cropper_utils.h" | |||
| #define BUF_SIZE 1024 | |||
| namespace mindspore { | |||
| namespace lite { | |||
| namespace cropper { | |||
| static const char *DELIM_COMMA = ","; | |||
| int Cropper::ReadPackage() { | |||
| std::ifstream in_file(this->flags_->package_file_); | |||
| if (ValidFile(in_file, this->flags_->package_file_.c_str()) == RET_OK) { | |||
| in_file.close(); | |||
| char buf[BUF_SIZE]; | |||
| String cmd = "ar -t " + this->flags_->package_file_; | |||
| MS_LOG(DEBUG) << cmd; | |||
| FILE *p_file = popen(cmd.c_str(), "r"); | |||
| if (!p_file) { | |||
| MS_LOG(ERROR) << "Error to popen" << this->flags_->package_file_; | |||
| return RET_ERROR; | |||
| } | |||
| while (fgets(buf, BUF_SIZE, p_file) != nullptr) { | |||
| this->all_files_.push_back(String(buf).substr(0, String(buf).length() - 1)); | |||
| this->discard_files_.push_back(String(buf).substr(0, String(buf).length() - 1)); | |||
| } | |||
| pclose(p_file); | |||
| MS_LOG(DEBUG) << "file nums: " << this->all_files_.size(); | |||
| } else { | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int Cropper::RunCropper() { | |||
| int status; | |||
| status = ReadPackage(); | |||
| if (status != RET_OK) { | |||
| MS_LOG(ERROR) << "read package failed."; | |||
| return status; | |||
| } | |||
| status = GetModelFiles(); | |||
| if (status != RET_OK) { | |||
| MS_LOG(ERROR) << "get model files failed."; | |||
| return status; | |||
| } | |||
| status = GetModelOps(); | |||
| if (status != RET_OK) { | |||
| MS_LOG(ERROR) << "get model ops failed."; | |||
| return status; | |||
| } | |||
| status = GetOpMatchFiles(); | |||
| if (status != RET_OK) { | |||
| MS_LOG(ERROR) << "get op match files failed."; | |||
| return status; | |||
| } | |||
| status = GetDiscardFileList(); | |||
| if (status != RET_OK) { | |||
| MS_LOG(ERROR) << "get discard file list failed."; | |||
| return status; | |||
| } | |||
| status = CutPackage(); | |||
| if (status != RET_OK) { | |||
| MS_LOG(ERROR) << "cut package failed."; | |||
| return status; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int Cropper::GetModelOps() { | |||
| for (const auto &path : this->model_files_) { | |||
| auto context = std::make_shared<Context>(); | |||
| size_t buffer_lens; | |||
| char *graph_buf = ReadFile(path.c_str(), &buffer_lens); | |||
| if (graph_buf == nullptr) { | |||
| MS_LOG(ERROR) << "Read model file failed while running " << path.c_str(); | |||
| std::cerr << "Read model file failed while running " << path.c_str() << std::endl; | |||
| return RET_ERROR; | |||
| } | |||
| auto meta_graph = schema::GetMetaGraph(graph_buf); | |||
| if (meta_graph == nullptr) { | |||
| delete[] graph_buf; | |||
| MS_LOG(ERROR) << "meta_graph is nullptr!"; | |||
| std::cerr << "meta_graph is nullptr!" << std::endl; | |||
| return RET_ERROR; | |||
| } | |||
| auto nodes = meta_graph->nodes(); | |||
| for (auto node : *nodes) { | |||
| this->all_operators_.insert(node->primitive()->value_type()); | |||
| MS_LOG(DEBUG) << "PrimitiveType:" << schema::EnumNamePrimitiveType(node->primitive()->value_type()) | |||
| << " QuantType:" << schema::EnumNameQuantType(node->quantType()); | |||
| // QuantType_AwareTraining may change | |||
| if (node->quantType() == schema::QuantType_AwareTraining || node->quantType() == schema::QuantType_PostTraining) { | |||
| this->int8_operators_.insert(node->primitive()->value_type()); | |||
| } else { | |||
| this->fp32_operators_.insert(node->primitive()->value_type()); | |||
| } | |||
| } | |||
| delete[] graph_buf; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int Cropper::GetModelFiles() { | |||
| if (!this->flags_->model_file_.empty()) { | |||
| auto files = StringSplit(this->flags_->model_file_, std::string(DELIM_COMMA)); | |||
| for (const auto &file : files) { | |||
| if (ValidFileSuffix(file, "ms") != RET_OK) { | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } | |||
| MS_LOG(DEBUG) << file; | |||
| String realPath = RealPath(file.c_str()); | |||
| if (realPath.empty()) { | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } | |||
| this->model_files_.push_back(realPath); | |||
| } | |||
| } | |||
| // get models from folder | |||
| if (!this->flags_->model_folder_path_.empty()) { | |||
| String cmd = "ls " + this->flags_->model_folder_path_ + "/*.ms"; | |||
| MS_LOG(DEBUG) << cmd; | |||
| char buf[BUF_SIZE]; | |||
| FILE *p_file = popen(cmd.c_str(), "r"); | |||
| if (!p_file) { | |||
| MS_LOG(ERROR) << "Error to popen"; | |||
| return RET_ERROR; | |||
| } | |||
| while (fgets(buf, BUF_SIZE, p_file) != nullptr) { | |||
| String realPath = RealPath(String(buf).substr(0, String(buf).length() - 1).c_str()); | |||
| if (realPath.empty()) { | |||
| return RET_INPUT_PARAM_INVALID; | |||
| } | |||
| this->model_files_.emplace_back(realPath); | |||
| } | |||
| pclose(p_file); | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int Cropper::GetOpMatchFiles() { | |||
| std::ifstream in_file(this->flags_->config_file_); | |||
| if (ValidFile(in_file, this->flags_->config_file_.c_str()) == RET_OK) { | |||
| MS_LOG(DEBUG) << this->flags_->config_file_.c_str(); | |||
| char buf[BUF_SIZE]; | |||
| while (!in_file.eof()) { | |||
| in_file.getline(buf, BUF_SIZE); | |||
| auto mapping = StringSplit(buf, DELIM_COMMA); | |||
| if (!mapping.empty()) { | |||
| String primitive = mapping[0]; | |||
| String type = mapping[1]; | |||
| String file = mapping[2]; | |||
| if (type == "kNumberTypeFloat32" || type == "kNumberTypeFloat16") { | |||
| for (auto op : this->fp32_operators_) { | |||
| if (schema::EnumNamePrimitiveType(op) == primitive) { | |||
| MS_LOG(DEBUG) << "kNumberTypeFloat32:" << mapping[2]; | |||
| this->archive_files_.insert(mapping[2]); | |||
| break; | |||
| } | |||
| } | |||
| } else if (type == "kNumberTypeInt8") { | |||
| for (auto op : this->int8_operators_) { | |||
| if (schema::EnumNamePrimitiveType(op) == primitive) { | |||
| MS_LOG(DEBUG) << "int8_operators_:" << mapping[2]; | |||
| this->archive_files_.insert(mapping[2]); | |||
| break; | |||
| } | |||
| } | |||
| } else if (type == "prototype") { | |||
| for (auto op : this->all_operators_) { | |||
| if (schema::EnumNamePrimitiveType(op) == primitive) { | |||
| MS_LOG(DEBUG) << "prototype:" << mapping[2]; | |||
| this->archive_files_.insert(mapping[2]); | |||
| break; | |||
| } | |||
| } | |||
| } else if (type == "common") { | |||
| MS_LOG(DEBUG) << "common:" << mapping[2]; | |||
| this->archive_files_.insert(mapping[2]); | |||
| } else { | |||
| MS_LOG(ERROR) << "invalid type symbol:" << type; | |||
| return RET_ERROR; | |||
| } | |||
| } | |||
| } | |||
| in_file.close(); | |||
| } else { | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int Cropper::GetDiscardFileList() { | |||
| // discard_files_=all_files_-archive_files_ | |||
| for (const auto &archive : this->archive_files_) { | |||
| for (auto it = this->discard_files_.begin(); it != this->discard_files_.end();) { | |||
| if (*it == archive) { | |||
| it = this->discard_files_.erase(it); | |||
| } else { | |||
| it++; | |||
| } | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int Cropper::CutPackage() { | |||
| String copy_bak_cmd = "cp " + this->flags_->package_file_ + " " + this->flags_->package_file_ + ".bak"; | |||
| String ar_cmd = "ar -d " + this->flags_->package_file_ + ".bak "; | |||
| for (const auto &file : this->discard_files_) { | |||
| ar_cmd.append(file).append(" "); | |||
| } | |||
| String copy_to_output_cmd = "cp " + this->flags_->package_file_ + ".bak " + this->flags_->output_file_ + " && rm " + | |||
| this->flags_->package_file_ + ".bak"; | |||
| int status; | |||
| status = system(copy_bak_cmd.c_str()); | |||
| if (status != 0) { | |||
| MS_LOG(ERROR) << copy_bak_cmd << " executor failed."; | |||
| return RET_ERROR; | |||
| } | |||
| status = system(ar_cmd.c_str()); | |||
| if (status != 0) { | |||
| MS_LOG(ERROR) << ar_cmd << " executor failed."; | |||
| return RET_ERROR; | |||
| } | |||
| status = system(copy_to_output_cmd.c_str()); | |||
| if (status != 0) { | |||
| MS_LOG(ERROR) << copy_to_output_cmd << " executor failed."; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int RunCropper(int argc, const char **argv) { | |||
| CropperFlags flags; | |||
| int status; | |||
| status = flags.Init(argc, argv); | |||
| if (status == RET_SUCCESS_EXIT) { | |||
| return status; | |||
| } | |||
| if (status != RET_OK) { | |||
| MS_LOG(ERROR) << "Flags init Error : " << GetErrorInfo(status); | |||
| std::cerr << "Flags init Error : " << GetErrorInfo(status) << std::endl; | |||
| return status; | |||
| } | |||
| Cropper cropper(&flags); | |||
| status = cropper.RunCropper(); | |||
| if (status == RET_OK) { | |||
| MS_LOG(INFO) << "CROPPER RESULT SUCCESS:" << status; | |||
| std::cout << "CROPPER RESULT SUCCESS:" << status << std::endl; | |||
| } else { | |||
| MS_LOG(ERROR) << "CROPPER RESULT FAILED:" << status << " " << GetErrorInfo(status); | |||
| std::cout << "CROPPER RESULT FAILED:" << status << " " << GetErrorInfo(status) << std::endl; | |||
| } | |||
| return status; | |||
| } | |||
| } // namespace cropper | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,68 @@ | |||
| /** | |||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||
| * | |||
| * 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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_TOOLS_LIB_CROPPER_LIB_CROPPER_H_ | |||
| #define MINDSPORE_LITE_TOOLS_LIB_CROPPER_LIB_CROPPER_H_ | |||
| #include <set> | |||
| #include <string> | |||
| #include <vector> | |||
| #include "include/model.h" | |||
| #include "tools/common/flag_parser.h" | |||
| #include "src/common/file_utils.h" | |||
| #include "src/common/utils.h" | |||
| #include "include/lite_session.h" | |||
| #include "tools/lib_cropper/cropper_flags.h" | |||
| namespace mindspore::lite::cropper { | |||
| class MS_API Cropper { | |||
| public: | |||
| explicit Cropper(CropperFlags *flags) : flags_(flags) {} | |||
| ~Cropper() = default; | |||
| int RunCropper(); | |||
| int ReadPackage(); | |||
| int GetModelFiles(); | |||
| int GetModelOps(); | |||
| int GetOpMatchFiles(); | |||
| int GetDiscardFileList(); | |||
| int CutPackage(); | |||
| std::vector<std::string> model_files_; | |||
| std::vector<std::string> all_files_; | |||
| std::set<std::string> archive_files_; | |||
| std::vector<std::string> discard_files_; | |||
| std::set<schema::PrimitiveType> all_operators_; | |||
| std::set<schema::PrimitiveType> int8_operators_; | |||
| std::set<schema::PrimitiveType> fp16_operators_; | |||
| std::set<schema::PrimitiveType> fp32_operators_; | |||
| private: | |||
| CropperFlags *flags_; | |||
| }; | |||
| int MS_API RunCropper(int argc, const char **argv); | |||
| } // namespace mindspore::lite::cropper | |||
| #endif // MINDSPORE_LITE_TOOLS_CROPPER_CROPPER_H_ | |||
| @@ -0,0 +1,23 @@ | |||
| /** | |||
| * Copyright 2020 Huawei Technologies Co., Ltd | |||
| * | |||
| * 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. | |||
| */ | |||
| #include "tools/lib_cropper/lib_cropper.h" | |||
| #include "include/version.h" | |||
| int main(int argc, const char **argv) { | |||
| MS_LOG(INFO) << mindspore::lite::Version(); | |||
| return mindspore::lite::cropper::RunCropper(argc, argv); | |||
| } | |||