| @@ -203,9 +203,7 @@ if(ENABLE_CONVERTER) | |||
| include(${TOP_DIR}/cmake/external_libs/eigen.cmake) | |||
| include(${TOP_DIR}/cmake/external_libs/protobuf.cmake) | |||
| add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tools/converter) | |||
| if(NOT WIN32) | |||
| add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/micro/coder) | |||
| endif() | |||
| add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/micro/coder) | |||
| endif() | |||
| if(PLATFORM_ARM32 OR PLATFORM_ARM64) | |||
| @@ -1,13 +1,12 @@ | |||
| #### classify all .h .c .cc files to FILE_SET | |||
| set(CODER_SRC | |||
| ${MICRO_DIR}/coder/coder.cc | |||
| ${MICRO_DIR}/coder/coder_context.cc | |||
| ${MICRO_DIR}/coder/coder_graph.cc | |||
| ${MICRO_DIR}/coder/debug.cc | |||
| ${MICRO_DIR}/coder/session_coder.cc | |||
| ${MICRO_DIR}/coder/context.cc | |||
| ${MICRO_DIR}/coder/graph.cc | |||
| ${MICRO_DIR}/coder/session.cc | |||
| ) | |||
| set(CODER_ALLOC_SRC | |||
| set(CODER_ALLOCATOR_SRC | |||
| ${MICRO_DIR}/coder/allocator/allocator.cc | |||
| ${MICRO_DIR}/coder/allocator/memory_manager.cc | |||
| ) | |||
| @@ -15,7 +14,10 @@ set(CODER_ALLOC_SRC | |||
| set(CODER_GENERATOR_SRC | |||
| ${MICRO_DIR}/coder/generator/generator.cc | |||
| ${MICRO_DIR}/coder/generator/inference/inference_generator.cc | |||
| ${MICRO_DIR}/coder/generator/utils/generator_utils.cc | |||
| ${MICRO_DIR}/coder/generator/component/benchmark_component.cc | |||
| ${MICRO_DIR}/coder/generator/component/common_component.cc | |||
| ${MICRO_DIR}/coder/generator/component/weight_component.cc | |||
| ${MICRO_DIR}/coder/generator/component/cmake_component.cc | |||
| ) | |||
| set(CODER_OPCODERS_SRC | |||
| @@ -51,6 +53,9 @@ set(CODER_OPCODERS_SRC | |||
| ${MICRO_DIR}/coder/opcoders/nnacl/fp32/assign_add_fp32_coder.cc | |||
| ${MICRO_DIR}/coder/opcoders/nnacl/fp32/batchnorm_fp32_coder.cc | |||
| ${MICRO_DIR}/coder/opcoders/nnacl/fp32/concat_fp32_coder.cc | |||
| ${MICRO_DIR}/coder/opcoders/nnacl/fp32/convolution_fp32_coder.cc | |||
| ${MICRO_DIR}/coder/opcoders/nnacl/fp32/convolution_winograd_fp32_coder.cc | |||
| ${MICRO_DIR}/coder/opcoders/nnacl/fp32/convolution_depthwise_fp32_coder.cc | |||
| ${MICRO_DIR}/coder/opcoders/nnacl/fp32/expand_dims_fp32_coder.cc | |||
| ${MICRO_DIR}/coder/opcoders/nnacl/fp32/gather_fp32_coder.cc | |||
| ${MICRO_DIR}/coder/opcoders/nnacl/fp32/nchw2nhwc_fp32_coder.cc | |||
| @@ -77,19 +82,10 @@ set(CODER_OPCODERS_SRC | |||
| set(CODER_UTILS_SRC | |||
| ${MICRO_DIR}/coder/utils/coder_utils.cc | |||
| ${MICRO_DIR}/coder/utils/dir_utils.cc | |||
| ${MICRO_DIR}/coder/utils/print_utils.cc | |||
| ) | |||
| set(PRIMITIVE_OP_SRC | |||
| ${LITE_DIR}/src/ops/batch_norm.cc | |||
| ${LITE_DIR}/src/ops/primitive_c.cc | |||
| ${LITE_DIR}/src/ops/slice.cc | |||
| ${LITE_DIR}/src/ops/while.cc | |||
| ${MICRO_DIR}/coder/utils/type_cast.cc | |||
| ) | |||
| set(LITE_SRC | |||
| ${PRIMITIVE_OP_SRC} | |||
| ${LITE_DIR}/tools/common/flag_parser.cc | |||
| ${LITE_DIR}/src/common/file_utils.cc | |||
| ${LITE_DIR}/src/common/graph_util.cc | |||
| ${LITE_DIR}/src/common/string_util.cc | |||
| @@ -98,11 +94,25 @@ set(LITE_SRC | |||
| ${LITE_DIR}/src/tensorlist.cc | |||
| ${LITE_DIR}/src/tensor.cc | |||
| ${LITE_DIR}/src/common/log_adapter.cc | |||
| ### src/ops for parameter and infer shape | |||
| ${LITE_DIR}/src/ops/batch_norm.cc | |||
| ${LITE_DIR}/src/ops/conv2d.cc | |||
| ${LITE_DIR}/src/ops/primitive_c.cc | |||
| ${LITE_DIR}/src/ops/slice.cc | |||
| ${LITE_DIR}/src/ops/while.cc | |||
| ### populate operator parameter | |||
| ${LITE_DIR}/src/ops/populate/conv2d_populate.cc | |||
| ### nnacl | |||
| ${LITE_DIR}/nnacl/base/minimal_filtering_generator.c | |||
| ${LITE_DIR}/nnacl/fp32/winograd_utils.c | |||
| ${LITE_DIR}/nnacl/fp32/pack_fp32.c | |||
| ${LITE_DIR}/nnacl/int8/quantize.c | |||
| ${LITE_DIR}/nnacl/int8/pack_int8.c | |||
| ${LITE_DIR}/nnacl/int8/matmul_int8.c | |||
| ${LITE_DIR}/nnacl/int8/fixed_point.c | |||
| ### tools | |||
| ${LITE_DIR}/tools/common/flag_parser.cc | |||
| ) | |||
| list(APPEND FILE_SET ${CODER_SRC} ${CODER_UTILS_SRC} ${CODER_OPCODERS_SRC} ${CODER_GENERATOR_SRC} | |||
| ${CODER_ALLOC_SRC} ${LITE_SRC}) | |||
| ${CODER_ALLOCATOR_SRC} ${LITE_SRC}) | |||
| @@ -13,9 +13,7 @@ include_directories(${LITE_DIR}) | |||
| include_directories(${TOP_DIR}/mindspore/core/) | |||
| #include coder | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/utils) | |||
| include(${MICRO_DIR}/cmake/file_list.cmake) | |||
| add_executable(codegen main.cc ${FILE_SET}) | |||
| add_dependencies(codegen fbs_src) | |||
| @@ -19,25 +19,20 @@ | |||
| #include <map> | |||
| #include "coder/allocator/memory_manager.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "coder/coder_config.h" | |||
| namespace mindspore::lite::micro { | |||
| const std::map<std::type_index, std::pair<TypeId, size_t>> types_map = { | |||
| {std::type_index(typeid(float *)), {kNumberTypeFloat32, sizeof(float)}}, | |||
| {std::type_index(typeid(int *)), {kNumberTypeInt32, sizeof(int)}}, | |||
| {std::type_index(typeid(int32_t *)), {kNumberTypeInt32, sizeof(int32_t)}}, | |||
| {std::type_index(typeid(int16_t *)), {kNumberTypeInt16, sizeof(int16_t)}}, | |||
| {std::type_index(typeid(int8_t *)), {kNumberTypeInt8, sizeof(int8_t)}}, | |||
| }; | |||
| void *MemoryAllocator::MallocWeightTensor(TypeId type_id, size_t size, MallocType type) { | |||
| auto item = types_map.find(std::type_index(typeid(type_id))); | |||
| MS_CHECK_TRUE_RET_NULL(item != types_map.end(), "unsupported type idnex"); | |||
| TypeId typei = item->second.first; | |||
| size_t type_size = item->second.second; | |||
| static const std::map<TypeId, size_t> size_map = {{kNumberTypeFloat32, sizeof(float)}, | |||
| {kNumberTypeInt32, sizeof(int)}, | |||
| {kNumberTypeInt32, sizeof(int32_t)}, | |||
| {kNumberTypeInt16, sizeof(int16_t)}, | |||
| {kNumberTypeInt8, sizeof(int8_t)}}; | |||
| auto item = size_map.find(type_id); | |||
| MS_CHECK_TRUE_RET_NULL(item != size_map.end(), "unsupported type idnex"); | |||
| size_t type_size = item->second; | |||
| std::vector<int> shape = {1, static_cast<int>(size / type_size)}; | |||
| auto cate = type == kOfflinePackWeight ? Tensor::Category::CONST_TENSOR : Tensor::Category::VAR; | |||
| Tensor *weight = new (std::nothrow) lite::Tensor(typei, shape, schema::Format_NHWC, cate); | |||
| Tensor *weight = new (std::nothrow) lite::Tensor(type_id, shape, schema::Format_NHWC, cate); | |||
| MS_CHECK_PTR_RET_NULL(weight); | |||
| std::string runtime_addr = net_weight_addr_ + std::to_string(weight_index_++); | |||
| malloc_weights_addr_.insert(std::make_pair(weight, runtime_addr)); | |||
| @@ -23,7 +23,7 @@ | |||
| #include <string> | |||
| #include "coder/allocator/memory_manager.h" | |||
| #include "coder/log.h" | |||
| #include "coder/utils/print_utils.h" | |||
| #include "coder/utils/type_cast.h" | |||
| #include "src/tensor.h" | |||
| #include "src/common/log_adapter.h" | |||
| @@ -21,8 +21,8 @@ | |||
| #include <map> | |||
| #include "schema/inner/model_generated.h" | |||
| #include "tools/common/flag_parser.h" | |||
| #include "coder/session_coder.h" | |||
| #include "coder/coder_context.h" | |||
| #include "coder/session.h" | |||
| #include "coder/context.h" | |||
| #include "utils/dir_utils.h" | |||
| #include "securec/include/securec.h" | |||
| #include "src/common/file_utils.h" | |||
| @@ -14,11 +14,11 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_CODER_CODER_H_ | |||
| #define MICRO_CODER_CODER_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_CODER_H_ | |||
| #include <string> | |||
| #include <memory> | |||
| #include "coder/session_coder.h" | |||
| #include "coder/session.h" | |||
| namespace mindspore::lite::micro { | |||
| @@ -41,4 +41,4 @@ class Coder final { | |||
| int RunCoder(int argc, const char **argv); | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MICRO_CODER_CODER_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_CODER_H_ | |||
| @@ -14,8 +14,8 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_CODER_CONFIG_H | |||
| #define MICRO_CODER_CONFIG_H | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_CONFIG_H | |||
| #define MINDSPORE_LITE_MICRO_CODER_CONFIG_H | |||
| #include <string> | |||
| @@ -36,11 +36,13 @@ class Configurator { | |||
| void set_code_path(const std::string &code_path) { code_path_ = code_path; } | |||
| std::string code_path() const { return code_path_; } | |||
| void set_subgraph_(const std::string &subgraph) { sub_graph_ = subgraph; } | |||
| std::string sub_graph() { return sub_graph_; } | |||
| void set_target(Target target) { target_ = target; } | |||
| Target target() const { return target_; } | |||
| void set_code_mode(CodeMode code_mode) { code_mode_ = code_mode; } | |||
| CodeMode code_mode() const { return code_mode_; } | |||
| void set_debug_mode(bool debug) { debug_mode_ = debug; } | |||
| @@ -56,6 +58,7 @@ class Configurator { | |||
| bool is_weight_file_{false}; | |||
| std::string module_name_; | |||
| std::string code_path_; | |||
| std::string sub_graph_; | |||
| Target target_{kTargetUnknown}; | |||
| CodeMode code_mode_{Code_Unknown}; | |||
| bool debug_mode_{false}; | |||
| @@ -14,7 +14,7 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/coder_context.h" | |||
| #include "micro/coder/context.h" | |||
| #include "micro/coder/coder_config.h" | |||
| #include "micro/coder/allocator/allocator.h" | |||
| @@ -14,8 +14,8 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_CODER_CODER_CONTEXT_H_ | |||
| #define MICRO_CODER_CODER_CONTEXT_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_CODER_CONTEXT_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_CODER_CONTEXT_H_ | |||
| #include <map> | |||
| #include <memory> | |||
| #include <set> | |||
| @@ -24,8 +24,6 @@ | |||
| #include <utility> | |||
| #include <vector> | |||
| #include "src/tensor.h" | |||
| #include "coder/utils/coder_utils.h" | |||
| #include "coder/utils/print_utils.h" | |||
| namespace mindspore::lite::micro { | |||
| class CoderContext { | |||
| public: | |||
| @@ -36,7 +34,13 @@ class CoderContext { | |||
| std::vector<std::string> init_contents() const { return initialContent_; } | |||
| void set_code_blocks(const std::vector<std::string> &code_block) { code_blocks_ = code_block; } | |||
| std::vector<std::string> code_blocks() { return code_blocks_; } | |||
| std::vector<std::string> code_blocks() const { return code_blocks_; } | |||
| void set_inference_blocks(const std::vector<std::string> &inference_blocks) { inference_blocks_ = inference_blocks; } | |||
| std::vector<std::string> inference_blocks() const { return inference_blocks_; } | |||
| void set_train_blocks(const std::vector<std::string> &train_blocks) { train_blocks_ = train_blocks; } | |||
| std::vector<std::string> train_blocks() const { return train_blocks_; } | |||
| void set_tensor_map(const std::map<Tensor *, std::string> &tensor_map) { | |||
| tensors_map_.insert(tensor_map.begin(), tensor_map.end()); | |||
| @@ -64,16 +68,13 @@ class CoderContext { | |||
| void AppendInitCode(const std::string &codeBlock); | |||
| std::set<std::string> c_files() const { return c_files_; } | |||
| void set_c_files(const std::set<std::string> files) { c_files_.insert(files.begin(), files.end()); } | |||
| void set_c_files(const std::set<std::string> &files) { c_files_.insert(files.begin(), files.end()); } | |||
| std::set<std::string> h_files() const { return h_files_; } | |||
| void set_h_files(const std::set<std::string> files) { h_files_.insert(files.begin(), files.end()); } | |||
| void set_h_files(const std::set<std::string> &files) { h_files_.insert(files.begin(), files.end()); } | |||
| std::set<std::string> asm_files() const { return asm_files_; } | |||
| void set_asm_files(const std::set<std::string> files) { asm_files_.insert(files.begin(), files.end()); } | |||
| void set_asm_files(const std::set<std::string> &files) { asm_files_.insert(files.begin(), files.end()); } | |||
| private: | |||
| std::vector<Tensor *> graph_inputs_; | |||
| @@ -101,9 +102,11 @@ class CoderContext { | |||
| std::set<std::string> asm_files_; | |||
| // operator header files | |||
| std::set<std::string> h_files_; | |||
| // net.c's content, include the inference and prediction implementation | |||
| // net.c's content, include the Inference and Training implementation | |||
| std::vector<std::string> code_blocks_; | |||
| std::vector<std::string> train_blocks_; | |||
| std::vector<std::string> inference_blocks_; | |||
| }; | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MICRO_CODER_CODER_CONTEXT_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_CONTEXT_H_ | |||
| @@ -1,95 +0,0 @@ | |||
| /** | |||
| * Copyright 2021 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 "micro/coder/debug.h" | |||
| #include <memory> | |||
| #include <map> | |||
| #include <vector> | |||
| #include <utility> | |||
| #include "include/errorcode.h" | |||
| #include "micro/coder/utils/print_utils.h" | |||
| #include "micro/coder/coder_context.h" | |||
| namespace mindspore::lite::micro { | |||
| void MicroDebug::DumpTensorData(Tensor *tensor, const std::string &tensor_addr, std::string *code_block_str, | |||
| bool is_input) { | |||
| *code_block_str += "\t\t\t{\n\t\t\t\tMicroTensor tensor;\n"; | |||
| std::string format_str = "\t\t\t\ttensor.format = " + std::to_string(tensor->format()) + ";\n"; | |||
| std::string type_str = "\t\t\t\ttensor.type = " + GetMicroTensorDataType(tensor->data_type()) + ";\n"; | |||
| std::string ndim_str = "\t\t\t\ttensor.ndim = " + std::to_string(static_cast<int>(tensor->shape().size())) + ";\n"; | |||
| *code_block_str += "\t\t\t\tint dim[] = {"; | |||
| for (size_t i = 0; i < tensor->shape().size(); ++i) { | |||
| *code_block_str += std::to_string(tensor->shape().at(i)) + ", "; | |||
| } | |||
| *code_block_str += "};\n"; | |||
| *code_block_str += "\t\t\t\ttensor.dim = dim;\n"; | |||
| std::string data_str = "\t\t\t\ttensor.data = (void *)(" + tensor_addr + ");\n"; | |||
| std::string in_or_out = (is_input == 1 ? "input" : "output"); | |||
| std::string fprint_str = "\t\t\t\tfprintf(output_file, \"" + in_or_out + " Tensor:" + tensor_addr + "\\n\");\n"; | |||
| std::string print_str = "\t\t\t\tPrintTensor(&tensor,output_file," + std::to_string(is_input) + ");\n\t\t\t}\n"; | |||
| *code_block_str += ndim_str; | |||
| *code_block_str += type_str; | |||
| *code_block_str += format_str; | |||
| *code_block_str += data_str; | |||
| *code_block_str += fprint_str; | |||
| *code_block_str += print_str; | |||
| } | |||
| int MicroDebug::DumpNodeData(const std::unique_ptr<OperatorCoder> &op_coder, | |||
| const std::map<Tensor *, std::string> &tensor_addrs, std::string *code_block_str) { | |||
| auto config = Configurator::GetInstance(); | |||
| if (!config->debug_mode()) { | |||
| return RET_OK; | |||
| } | |||
| std::string node_name = op_coder->ID(); | |||
| std::string file_str = "\n\t\t{\n\t\t\tFILE *output_file = fopen( \"./" + node_name + | |||
| ".ir\", \"w\");\n\t\t\tfprintf(output_file, \"Node:" + op_coder->ID() + "\\n\");\n"; | |||
| *code_block_str += file_str; | |||
| auto runtime_tensor_iterator = [&op_coder, tensor_addrs, &code_block_str](const std::vector<Tensor *> &tensors, | |||
| bool dump_data) { | |||
| for (const auto &tensor : tensors) { | |||
| if (tensor->data_c() != nullptr) { | |||
| continue; | |||
| } | |||
| auto find_item = | |||
| std::find_if(tensor_addrs.begin(), tensor_addrs.end(), | |||
| [tensor](const std::pair<Tensor *, std::string> &item) { return item.first == tensor; }); | |||
| if (find_item != tensor_addrs.end()) { | |||
| DumpTensorData(tensor, find_item->second, code_block_str, dump_data); | |||
| } | |||
| } | |||
| return RET_OK; | |||
| }; | |||
| int status = runtime_tensor_iterator(op_coder->input_tensors(), true); | |||
| if (status != RET_OK) { | |||
| MS_LOG(ERROR) << "dump runtime input tensor failed!"; | |||
| return status; | |||
| } | |||
| status = runtime_tensor_iterator(op_coder->output_tensors(), false); | |||
| if (status != RET_OK) { | |||
| MS_LOG(ERROR) << "dump runtime input tensor failed!"; | |||
| return status; | |||
| } | |||
| std::string end_file_str = "\t\t\tfclose(output_file);\n\t\t}\n"; | |||
| *code_block_str += end_file_str; | |||
| return RET_OK; | |||
| } | |||
| } // namespace mindspore::lite::micro | |||
| @@ -0,0 +1,191 @@ | |||
| /** | |||
| * Copyright 2021 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 "coder/generator/component/benchmark_component.h" | |||
| #include <memory> | |||
| #include "coder/generator/component/const_blocks/license.h" | |||
| #include "coder/log.h" | |||
| #include "include/errorcode.h" | |||
| #include "nnacl/op_base.h" | |||
| namespace mindspore::lite::micro { | |||
| constexpr int kWarmUp = 3; | |||
| void CodeBenchmarkHeader(std::ofstream &ofs, const std::string &header) { | |||
| ofs << g_hwLicense; | |||
| ofs << "#include <stdio.h>\n" | |||
| "#include <string.h>\n" | |||
| "#include <stdlib.h>\n" | |||
| "#include <stdint.h>\n" | |||
| "#include \"microtensor.h\"\n" | |||
| "#include \"load_input.h\"\n" | |||
| "#include \"debug_utils.h\"\n"; | |||
| ofs << "#include \"" << header << "\"\n"; | |||
| } | |||
| void CodeBenchmarkUsage(std::ofstream &ofs) { | |||
| ofs << "void usage() {\n" | |||
| " printf(\n" | |||
| " \"-- mindspore micro params usage:\\n\"\n" | |||
| " \"args[0]: executable file\\n\"\n" | |||
| " \"args[1]: inputs binary file\\n\"\n" | |||
| " \"args[2]: model weight binary file\\n\"\n" | |||
| " \"args[3]: loop count for performance test\\n\"\n" | |||
| " \"args[4]: runtime thread num\\n\"\n" | |||
| " \"args[5]: runtime thread bind mode\\n\\n\");\n" | |||
| "}\n\n"; | |||
| } | |||
| void CodeBenchmarkWarmup(std::ofstream &ofs, const std::string &module_name) { | |||
| ofs << "// the default number of warm-ups is 3\n" | |||
| << "void " << module_name << "_WarmUp() {\n" | |||
| << " for (int i = 0; i < " << kWarmUp << "; ++i) {\n" | |||
| << " " << module_name << "_Inference();\n" | |||
| << " }\n" | |||
| << "}\n"; | |||
| } | |||
| void CodeBenchmarkSetInputs(std::ofstream &ofs, const std::string &module_name, | |||
| const std::unique_ptr<CoderContext> &ctx) { | |||
| ofs << "int main(int argc, char **argv) {\n" | |||
| " if (argc < 2) {\n" | |||
| " MICRO_ERROR(\"input command is invalid\\n\");\n" | |||
| " usage();\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n"; | |||
| std::vector<Tensor *> inputs = ctx->graph_inputs(); | |||
| size_t inputs_num = inputs.size(); | |||
| ofs << " // input shape: "; | |||
| std::for_each(inputs.begin(), inputs.end(), [&](Tensor *t) { | |||
| ofs << "[ "; | |||
| for (int i : t->shape()) { | |||
| ofs << i << ", "; | |||
| } | |||
| ofs << "], "; | |||
| }); | |||
| ofs << "\n"; | |||
| ofs << " void *inputs_binbuf[" << inputs_num << "];\n"; | |||
| ofs << " int inputs_size[" << inputs_num << "] = {"; | |||
| for (size_t i = 0; i < inputs_num; ++i) { | |||
| Tensor *input = inputs[i]; | |||
| ofs << input->Size() << ", "; | |||
| } | |||
| ofs << "};\n"; | |||
| ofs << " int ret = ReadInputsFile(argv[1], inputs_binbuf, inputs_size, " << inputs_num | |||
| << ");\n" | |||
| " if (ret != RET_OK) {\n" | |||
| " MICRO_ERROR(\"read inputs file failed\");\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n"; | |||
| ofs << " ret = " << module_name << "_SetInputs((const void **)inputs_binbuf, " << inputs_num | |||
| << ");\n" | |||
| " if (ret != RET_OK) {\n" | |||
| " MICRO_ERROR(\"set inputs failed\");\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n"; | |||
| } | |||
| void CodeBenchmarkSetBuffer(std::ofstream &ofs, const std::string &module_name) { | |||
| ofs << " int total_buffer_size = " << module_name << "_GetBufferSize();\n"; | |||
| ofs << " void *buffer = malloc(total_buffer_size);\n"; | |||
| ofs << " if (buffer == NULL ){\n" | |||
| " MICRO_ERROR(\"malloc memory buffer failed\");\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n"; | |||
| ofs << " ret = " << module_name | |||
| << "_SetBuffer(buffer);\n" | |||
| " if (ret != RET_OK) {\n" | |||
| " MICRO_ERROR(\"set inputs failed\");\n" | |||
| " return RET_ERROR;" | |||
| " }\n"; | |||
| } | |||
| void CodeBenchmarkInitWeight(std::ofstream &ofs, const std::string &module_name) { | |||
| ofs << " int weight_size = 0;\n" | |||
| " void *weight_buffer = ReadInputData(argv[2], &weight_size); \n" | |||
| " if(" | |||
| << module_name | |||
| << "_Init(weight_buffer, weight_size) != RET_OK) {\n" | |||
| " MICRO_ERROR(\"model init failed\");\n" | |||
| " " | |||
| << module_name | |||
| << "_FreeResource();\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n" | |||
| " free(weight_buffer);\n" | |||
| " weight_buffer = NULL;\n"; | |||
| } | |||
| void CodeBenchmarkConfigThread(std::ofstream &ofs) { | |||
| ofs << " int thread_num = 4;\n" | |||
| " BindMode bind_mode = NO_BIND_MODE;\n" | |||
| " if (argc >= 6) {\n" | |||
| " thread_num = atoi(argv[4]);\n" | |||
| " bind_mode = atoi(argv[5]);\n" | |||
| " }\n" | |||
| " ret = ConfigThreadPool(THREAD_POOL_DEFAULT, thread_num, bind_mode);\n" | |||
| " if (ret != 0) {\n" | |||
| " MICRO_ERROR(\"create thread pool failed\");\n" | |||
| " }\n"; | |||
| } | |||
| void CodeBenchmarkInference(std::ofstream &ofs, const std::string &module_name) { | |||
| ofs << " if (argc >= 4) {\n" | |||
| << " " << module_name << "_WarmUp();\n" | |||
| << " uint64_t timeAvg = 0;\n" | |||
| << " int loop_count = atoi(argv[3]);\n" | |||
| << " printf(\"======Inference Start======\\n\");\n" | |||
| << " printf(\"cycles: %d\", loop_count);\n" | |||
| << " for (int i = 0; i < loop_count; i++) {\n" | |||
| << " uint64_t runBegin = GetTimeUs();\n" | |||
| << " " << module_name << "_Inference();\n" | |||
| << " uint64_t runEnd = GetTimeUs();\n" | |||
| << " uint64_t time = runEnd - runBegin;\n" | |||
| << " timeAvg += time;\n" | |||
| << " }\n" | |||
| << " float cunCost = (float)timeAvg / 1000.0f;\n" | |||
| << " printf(\"=======Inference End=======\\n\");\n" | |||
| " printf(\"total time:\\t %.5fms, per time: \\t %.5fms\\n\", cunCost, cunCost/loop_count);\n" | |||
| << " }\n"; | |||
| ofs << " " << module_name << "_Inference();\n"; | |||
| } | |||
| void CodeBenchmarkPrintOutputs(std::ofstream &ofs, const std::string &module_name) { | |||
| ofs << " // print model outputs \n"; | |||
| ofs << " const MicroTensorList *outs = " << module_name << "_GetOutputs();\n"; | |||
| ofs << " for (int i = 0; i < outs->num; ++i) {\n" | |||
| " MicroTensor *tensor = outs->tensor + i;\n" | |||
| " PrintTensorData(tensor);\n" | |||
| " }\n"; | |||
| ofs << " printf(\"" << module_name << " inference success.\\n\");\n"; | |||
| ofs << " free(buffer);\n"; | |||
| } | |||
| /** | |||
| * 1. free malloc memory buffer | |||
| * 2. set input and buffer to NULL, and free packed weight memory | |||
| * 3. free input binary memory | |||
| */ | |||
| void CodeBenchmarkFreeResourse(std::ofstream &ofs, const std::string &module_name, size_t inputs_num) { | |||
| ofs << " free(buffer);\n"; | |||
| ofs << " " << module_name << "_FreeResource();\n"; | |||
| ofs << " for (int i = 0; i < " << inputs_num << "; ++i) {\n"; | |||
| ofs << " free(inputs_binbuf[i]);\n" | |||
| " }\n" | |||
| " return RET_OK;" | |||
| "}\n\n"; | |||
| } | |||
| } // namespace mindspore::lite::micro | |||
| @@ -0,0 +1,52 @@ | |||
| /** | |||
| * Copyright 2021 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_MICRO_CODER_GENERATOR_BENCHMARK_COMPONENT_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_GENERATOR_BENCHMARK_COMPONENT_H_ | |||
| #include <map> | |||
| #include <string> | |||
| #include <vector> | |||
| #include <memory> | |||
| #include <fstream> | |||
| #include "src/tensor.h" | |||
| #include "coder/context.h" | |||
| namespace mindspore::lite::micro { | |||
| void CodeBenchmarkHeader(std::ofstream &ofs, const std::string &header); | |||
| void CodeBenchmarkUsage(std::ofstream &ofs); | |||
| void CodeBenchmarkWarmup(std::ofstream &ofs, const std::string &module_name); | |||
| void CodeBenchmarkSetInputs(std::ofstream &ofs, const std::string &module_name, | |||
| const std::unique_ptr<CoderContext> &ctx); | |||
| void CodeBenchmarkSetBuffer(std::ofstream &ofs, const std::string &module_name); | |||
| void CodeBenchmarkInitWeight(std::ofstream &ofs, const std::string &module_name); | |||
| void CodeBenchmarkConfigThread(std::ofstream &ofs); | |||
| void CodeBenchmarkInference(std::ofstream &ofs, const std::string &module_name); | |||
| void CodeBenchmarkPrintOutputs(std::ofstream &ofs, const std::string &module_name); | |||
| void CodeBenchmarkFreeResourse(std::ofstream &ofs, const std::string &module_name, size_t inputs_num); | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_GENERATOR_BENCHMARK_COMPONENT_H_ | |||
| @@ -0,0 +1,55 @@ | |||
| /** | |||
| * Copyright 2021 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 "coder/generator/component/cmake_component.h" | |||
| #include <set> | |||
| #include <memory> | |||
| namespace mindspore::lite::micro { | |||
| void CodeCMakeNetLibrary(std::ofstream &ofs, const std::string &module_name, const std::unique_ptr<CoderContext> &ctx, | |||
| Target target) { | |||
| ofs << "include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include/)\n"; | |||
| if (target == kARM32M) { | |||
| ofs << "include_directories(${OP_HEADER_PATH}/cmsis)\n" | |||
| << "include_directories(${OP_HEADER_PATH}/cmsis/CMSIS/NN/Include)\n" | |||
| << "include_directories(${OP_HEADER_PATH}/cmsis/CMSIS/DSP/Include)\n" | |||
| << "include_directories(${OP_HEADER_PATH}/cmsis/CMSIS/Core/Include)\n"; | |||
| } | |||
| ofs << "set(OP_SRC\n"; | |||
| for (const std::string &c_file : ctx->c_files()) { | |||
| ofs << " " << c_file << ".o\n"; | |||
| } | |||
| ofs << " " << module_name << "_weight.c.o\n" | |||
| << " " << module_name << ".c.o\n" | |||
| << ")\n"; | |||
| std::set<std::string> kernel_cmake_asm_set_files = ctx->asm_files(); | |||
| if (!kernel_cmake_asm_set_files.empty()) { | |||
| ofs << "set(ASSEMBLY_SRC\n"; | |||
| for (const std::string &asm_file : kernel_cmake_asm_set_files) { | |||
| ofs << " " << asm_file << ".o\n"; | |||
| } | |||
| ofs << ")\n" | |||
| << "set_property(SOURCE ${ASSEMBLY_SRC} PROPERTY LANGUAGE C)\n" | |||
| << "list(APPEND OP_SRC ${ASSEMBLY_SRC})\n"; | |||
| } | |||
| ofs << "file(GLOB NET_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.c)\n" | |||
| << "add_library(${PROJ_NAME} STATIC ${NET_SRC})\n"; | |||
| } | |||
| } // namespace mindspore::lite::micro | |||
| @@ -14,30 +14,22 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MINDSPORE_MICRO_LITE_CODER_DEBUG_H_ | |||
| #define MINDSPORE_MICRO_LITE_CODER_DEBUG_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_GENERATOR_CMAKE_COMPONENT_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_GENERATOR_CMAKE_COMPONENT_H_ | |||
| #include <fstream> | |||
| #include <sstream> | |||
| #include <string> | |||
| #include <map> | |||
| #include <string> | |||
| #include <vector> | |||
| #include <memory> | |||
| #include <fstream> | |||
| #include "src/tensor.h" | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/coder_config.h" | |||
| #include "coder/context.h" | |||
| namespace mindspore::lite::micro { | |||
| void CodeCMakeNetLibrary(std::ofstream &ofs, const std::string &module_name, const std::unique_ptr<CoderContext> &ctx, | |||
| Target target); | |||
| class MicroDebug { | |||
| public: | |||
| MicroDebug() = default; | |||
| ~MicroDebug() = default; | |||
| static void DumpTensorData(Tensor *tensor, const std::string &tensor_addr, std::string *code_block_str, | |||
| bool is_input); | |||
| static int DumpNodeData(const std::unique_ptr<OperatorCoder> &op_coder, | |||
| const std::map<Tensor *, std::string> &tensor_addrs, std::string *code_block_str); | |||
| }; | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_DEBUG_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_GENERATOR_CMAKE_COMPONENT_H_ | |||
| @@ -0,0 +1,209 @@ | |||
| /** | |||
| * Copyright 2021 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 "coder/generator/component/common_component.h" | |||
| #include <memory> | |||
| #include "coder/generator/component/const_blocks/license.h" | |||
| #include "coder/utils/type_cast.h" | |||
| #include "coder/log.h" | |||
| #include "include/errorcode.h" | |||
| #include "nnacl/op_base.h" | |||
| namespace mindspore::lite::micro { | |||
| void CodeSourceFileInclude(std::ofstream &ofs, const std::string &weight_file, const std::string &header) { | |||
| ofs << g_hwLicense << "#include \"microtensor.h\"\n" | |||
| << "#include \"" << weight_file << "\"\n" | |||
| << "#include \"" << header << "\"\n"; | |||
| } | |||
| void CodeInputAndOutputState(std::ofstream &ofs, const std::string &module_name) { | |||
| ofs << "/**\n" | |||
| << " * set input tensors\n" | |||
| << " * @param inputs, the input data ptr's array of the model, the tensors' count of input may be greater than " | |||
| "one.\n" | |||
| << " * @param num, the input data's number of the model.\n" | |||
| << " **/\n" | |||
| << "int " << module_name << "_SetInputs(const void **inputs, int num);\n\n"; | |||
| ofs << "/**\n" | |||
| << " * get output tensor of the model \n" | |||
| << " **/\n" | |||
| << "const MicroTensorList *" << module_name << "_GetOutputs();\n\n"; | |||
| } | |||
| void PrintMicroTensors(std::ofstream &ofs, std::vector<Tensor *> tensors, const std::string &name, | |||
| const std::map<Tensor *, std::string> &tensors_map) { | |||
| for (size_t i = 0; i < tensors.size(); ++i) { | |||
| Tensor *tensor = tensors[i]; | |||
| auto item = tensors_map.find(tensor); | |||
| if (item == tensors_map.end()) { | |||
| MS_LOG(ERROR) << "nonexistent tensor"; | |||
| break; | |||
| } | |||
| ofs << " static int dim[] = {"; | |||
| for (size_t j = 0; j < tensor->shape().size(); ++j) { | |||
| ofs << tensor->shape()[j] << ", "; | |||
| } | |||
| ofs << "};\n" | |||
| << " " << name << "[" << i << "].ndim = " << tensor->shape().size() << ";\n" | |||
| << " " << name << "[" << i << "].dim = dim;\n" | |||
| << " " << name << "[" << i << "].type = " << EnumMicroTensorDataType(tensor->data_type()) << ";\n" | |||
| << " " << name << "[" << i << "].format = " << std::to_string(tensor->format()) << ";\n" | |||
| << " " << name << "[" << i << "].data =" << item->second << ";\n"; | |||
| } | |||
| } | |||
| void CodeInputAndOutputImplement(std::ofstream &ofs, const std::string &module_name, | |||
| const std::unique_ptr<CoderContext> &ctx) { | |||
| // input tensors | |||
| ofs << "\n// input tensors\n"; | |||
| std::vector<Tensor *> inputs = ctx->graph_inputs(); | |||
| for (size_t i = 0; i < inputs.size(); ++i) { | |||
| ofs << "static const unsigned char *" << ctx->input_name() + std::to_string(i) << " = 0;\n"; | |||
| } | |||
| size_t size = inputs.size(); | |||
| ofs << "int " << module_name << "_SetInputs(const void **inputs, int num) {\n" | |||
| << " if (inputs == NULL) {\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n" | |||
| << " if (num !=" << size << ") {\n" | |||
| << " return RET_ERROR;\n" | |||
| " }\n"; | |||
| for (size_t i = 0; i < size; ++i) { | |||
| ofs << "\t" << ctx->input_name() + std::to_string(i) << " = inputs[" << i << "];\n"; | |||
| } | |||
| ofs << " return RET_OK;\n}\n"; | |||
| // output tensors | |||
| ofs << "\n// output tensors\n"; | |||
| std::vector<Tensor *> outputs = ctx->graph_outputs(); | |||
| size_t output_num = outputs.size(); | |||
| std::string output_name = ctx->output_name(); | |||
| ofs << "const MicroTensorList* " << module_name << "_GetOutputs() {\n" | |||
| << " static MicroTensor " << output_name << "[" << output_num << "] ;\n"; | |||
| PrintMicroTensors(ofs, outputs, output_name, ctx->tensors_map()); | |||
| ofs << " static MicroTensorList " << module_name << "_TensorArray;\n" | |||
| << " " << module_name << "_TensorArray.num = " << output_num << ";\n" | |||
| << " " << module_name << "_TensorArray.tensor = &" << output_name << "[0];\n" | |||
| << " return &" << module_name << "_TensorArray; \n}\n"; | |||
| } | |||
| void CodeGraphQuantArgsState(std::ofstream &ofs, const std::string &module_name) { | |||
| ofs << "/**\n" | |||
| << " * get input and output QuantArgs of the model \n" | |||
| << " **/\n" | |||
| << "GraphQuantArgs " << module_name << "_GetInOutQuantArgs();\n\n"; | |||
| } | |||
| void CodeGraphQuantArgsImplement(std::ofstream &ofs, const std::string &module_name, | |||
| const std::unique_ptr<CoderContext> &ctx) { | |||
| std::vector<Tensor *> graph_inputs = ctx->graph_inputs(); | |||
| Tensor *in_tensor = graph_inputs.at(kInputIndex); | |||
| MS_CHECK_PTR_IF_NULL(in_tensor); | |||
| std::vector<Tensor *> graph_outputs = ctx->graph_outputs(); | |||
| Tensor *out_tensor = graph_outputs.at(kOutputIndex); | |||
| MS_CHECK_PTR_IF_NULL(out_tensor); | |||
| std::vector<QuantArg> in_quant_args = in_tensor->quant_params(); | |||
| std::vector<QuantArg> out_quant_args = out_tensor->quant_params(); | |||
| if (graph_inputs.empty() || graph_outputs.empty() || in_quant_args.empty() || out_quant_args.empty()) { | |||
| MS_LOG(ERROR) << "code model quant args failed"; | |||
| return; | |||
| } | |||
| ofs << "GraphQuantArgs " << module_name << "_GetInOutQuantArgs() {\n" | |||
| << "\t\tGraphQuantArgs quan_args = { " << in_quant_args.at(0).scale << ", " << out_quant_args.at(0).scale << ", " | |||
| << in_quant_args.at(0).zeroPoint << ", " << out_quant_args.at(0).zeroPoint << "};\n" | |||
| << "\t\treturn quan_args;\n" | |||
| << "}\n"; | |||
| } | |||
| void CodeInitWeightState(std::ofstream &ofs, const std::string &module_name) { | |||
| ofs << "/**\n" | |||
| << " * @param weight_buffer, the address of the weight binary file\n" | |||
| << " * @param weight_size, the size of the model file in bytes\n" | |||
| << " **/\n" | |||
| << "int " << module_name << "_Init(void *weight_buffer, int weight_size);\n\n"; | |||
| } | |||
| void CodeManageResourceState(std::ofstream &ofs, const std::string &module_name) { | |||
| ofs << "/**\n" | |||
| << " * get the memory space size of the inference.\n" | |||
| << " **/\n" | |||
| << "int " << module_name << "_GetBufferSize();\n"; | |||
| ofs << "/**\n" | |||
| << " * set the memory space for the inference\n" | |||
| << " **/\n" | |||
| << "int " << module_name << "_SetBuffer(void *buffer);\n\n"; | |||
| ofs << "/**\n" | |||
| << " * free the memory of packed weights, and set the membuf buffer and input address to NULL\n" | |||
| << " **/\n" | |||
| << "void " << module_name << "_FreeResource();\n"; | |||
| } | |||
| void CodeInitResourceImplement(std::ofstream &ofs, const std::string &module_name, | |||
| const std::unique_ptr<CoderContext> &ctx) { | |||
| ofs << "int " << module_name << "deconv_GetBufferSize() {\n" | |||
| << " return " << ctx->total_buffer_size() << ";\n" | |||
| << "}\n"; | |||
| ofs << "int " << module_name << "_SetBuffer( void *buffer) {\n"; | |||
| ofs << " if (buffer == NULL) {\n" | |||
| " MICRO_ERROR(\"memory buffer is NULL\");\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n"; | |||
| ofs << " " << ctx->buffer_name() | |||
| << " = buffer;\n" | |||
| " return RET_OK;\n" | |||
| "}\n"; | |||
| } | |||
| void CodeFreeResourceImplement(std::ofstream &ofs, const std::string &module_name, | |||
| const std::unique_ptr<CoderContext> &ctx) { | |||
| ofs << "void " << module_name << "_FreeResource() {\n"; | |||
| ofs << " " << ctx->buffer_name() << "= NULL;\n"; | |||
| std::vector<Tensor *> inputs = ctx->graph_inputs(); | |||
| size_t size = inputs.size(); | |||
| for (size_t i = 0; i < size; ++i) { | |||
| ofs << " " << ctx->input_name() + std::to_string(i) << " = NULL;\n"; | |||
| } | |||
| ofs << " void *allocated[] = {"; | |||
| size_t num = 0; | |||
| for (const auto &item : ctx->tensors_map()) { | |||
| Tensor *tensor = item.first; | |||
| std::string name = item.second; | |||
| if (tensor->data_c() != nullptr && tensor->category() != Tensor::Category::CONST_TENSOR) { | |||
| ofs << name << ", "; | |||
| num++; | |||
| } | |||
| } | |||
| ofs << " };\n"; | |||
| ofs << " for (int i = 0; i < " << num << "; ++i) {\n" | |||
| << " free(allocated[i]);\n" | |||
| << " allocated[i] = NULL;\n" | |||
| << " }\n"; | |||
| ofs << "}\n"; | |||
| } | |||
| void CodeInferenceState(std::ofstream &ofs, const std::string &module_name) { | |||
| ofs << "/**\n" | |||
| << " * net inference function\n" | |||
| << " **/\n" | |||
| << "void " << module_name << "_Inference();\n\n"; | |||
| } | |||
| } // namespace mindspore::lite::micro | |||
| @@ -0,0 +1,51 @@ | |||
| /** | |||
| * Copyright 2021 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_MICRO_CODER_GENERATOR_COMMON_COMPONENT_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_GENERATOR_COMMON_COMPONENT_H_ | |||
| #include <map> | |||
| #include <string> | |||
| #include <vector> | |||
| #include <memory> | |||
| #include <fstream> | |||
| #include "src/tensor.h" | |||
| #include "coder/context.h" | |||
| namespace mindspore::lite::micro { | |||
| void CodeSourceFileInclude(std::ofstream &ofs, const std::string &weight_file, const std::string &header); | |||
| void CodeInputAndOutputState(std::ofstream &ofs, const std::string &module_name); | |||
| void CodeInputAndOutputImplement(std::ofstream &ofs, const std::string &module_name, | |||
| const std::unique_ptr<CoderContext> &ctx); | |||
| void CodeGraphQuantArgsState(std::ofstream &ofs, const std::string &module_name); | |||
| void CodeGraphQuantArgsImplement(std::ofstream &ofs, const std::string &module_name, | |||
| const std::unique_ptr<CoderContext> &ctx); | |||
| void CodeInitWeightState(std::ofstream &ofs, const std::string &module_name); | |||
| void CodeManageResourceState(std::ofstream &ofs, const std::string &module_name); | |||
| void CodeInitResourceImplement(std::ofstream &ofs, const std::string &module_name, | |||
| const std::unique_ptr<CoderContext> &ctx); | |||
| void CodeFreeResourceImplement(std::ofstream &ofs, const std::string &module_name, | |||
| const std::unique_ptr<CoderContext> &ctx); | |||
| void CodeInferenceState(std::ofstream &ofs, const std::string &module_name); | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_GENERATOR_COMMON_COMPONENT_H_ | |||
| @@ -42,11 +42,11 @@ static const char debug_utils_h[] = | |||
| "#include <stdint.h>\n" | |||
| "#include \"microtensor.h\"\n" | |||
| "\n" | |||
| "void PrintTensor(MicroTensor *tensor, FILE *output_file, int isInput);\n" | |||
| "void PrintTensor(MicroTensor *tensor, FILE *output_file, const char *is_input);\n" | |||
| "\n" | |||
| "void PrintTensorData(MicroTensor *tensor);\n" | |||
| "\n" | |||
| "uint64_t GetTimeUs(void);\n" | |||
| "uint64_t GetTimeUs();\n" | |||
| "\n" | |||
| "#endif // MINDSPORE_LITE_MICRO_MICRODEBUGUTIL_H_\n"; | |||
| @@ -238,31 +238,27 @@ static const char debug_utils_c[] = | |||
| " fprintf(file, \"\\n\");\n" | |||
| "}\n" | |||
| "\n" | |||
| "void PrintTensor(MicroTensor *tensor, FILE *output_file, int isInput) {\n" | |||
| "void PrintTensor(MicroTensor *tensor, FILE *output_file, const char *is_input) {\n" | |||
| " if (output_file != NULL) {\n" | |||
| " const char *tips = NULL;\n" | |||
| " if (isInput) {\n" | |||
| " tips = \"input\";\n" | |||
| " } else {\n" | |||
| " tips = \"output\";\n" | |||
| " }\n" | |||
| " fprintf(output_file, \"%s \", tips);\n" | |||
| " for (int i = 0; i < tensor->ndim; ++i) {\n" | |||
| " fprintf(output_file, \"%u, \", tensor->dim[i]);\n" | |||
| " }\n" | |||
| " fprintf(output_file, \"\\n\");\n" | |||
| "\n" | |||
| " const char *type = TypeNames[tensor->type];\n" | |||
| " const char *format = EnumNameFormat(tensor->format);\n" | |||
| " unsigned int tensorSize = GetTensorElementSize(tensor);\n" | |||
| " fprintf(output_file, \"%s type:%s, format:%s, elementSize: %u\\n\", tips, type, format, tensorSize);\n" | |||
| " fprintf(output_file, \"%s Data:\\n\", tips);\n" | |||
| " PrintDataToFile(tensor->data, tensorSize, tensor->type, output_file);\n" | |||
| " (void)fflush(output_file);\n" | |||
| " MICRO_ERROR(\"output file is NULL\");\n" | |||
| " return;\n" | |||
| " }\n" | |||
| " fprintf(output_file, \"%s \", is_input);\n" | |||
| " for (int i = 0; i < tensor->ndim; ++i) {\n" | |||
| " fprintf(output_file, \"%u, \", tensor->dim[i]);\n" | |||
| " }\n" | |||
| " fprintf(output_file, \"\\n\");\n" | |||
| "\n" | |||
| " const char *type = TypeNames[tensor->type];\n" | |||
| " const char *format = EnumNameFormat(tensor->format);\n" | |||
| " unsigned int tensorSize = GetTensorElementSize(tensor);\n" | |||
| " fprintf(output_file, \"%s type:%s, format:%s, elementSize: %u\\n\", is_input, type, format, tensorSize);\n" | |||
| " fprintf(output_file, \"%s Data:\\n\", is_input);\n" | |||
| " PrintDataToFile(tensor->data, tensorSize, tensor->type, output_file);\n" | |||
| " (void)fflush(output_file);\n" | |||
| "}\n" | |||
| "\n" | |||
| "uint64_t GetTimeUs(void) {\n" | |||
| "uint64_t GetTimeUs() {\n" | |||
| " const int USEC = 1000000;\n" | |||
| " const int MSEC = 1000;\n" | |||
| " struct timespec ts = {0, 0};\n" | |||
| @@ -0,0 +1,150 @@ | |||
| /** | |||
| * Copyright 2021 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 "coder/generator/component/weight_component.h" | |||
| #include <memory> | |||
| #include <utility> | |||
| #include <algorithm> | |||
| #include "coder/generator/component/const_blocks/license.h" | |||
| #include "coder/utils/coder_utils.h" | |||
| namespace mindspore::lite::micro { | |||
| void CodeWeightFileHeader(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx) { | |||
| ofs << g_hwLicense; | |||
| // include all operator header | |||
| for (const auto &h_file : ctx->h_files()) { | |||
| ofs << "#include \"" << h_file << "\"\n"; | |||
| } | |||
| ofs << "#include <stdlib.h>\n" | |||
| << "#include <string.h>\n" | |||
| << "#include \"microtensor.h\"\n\n" | |||
| << "extern unsigned char *" << ctx->buffer_name() << ";\n"; | |||
| } | |||
| void CodeModelParamsState(std::ofstream &ofs, const std::map<std::string, Tensor *> &weights) { | |||
| for (auto &item : weights) { | |||
| std::string name = item.first; | |||
| Tensor *tensor = item.second; | |||
| if (tensor->category() == Tensor::Category::CONST_TENSOR) { | |||
| if (tensor->data_c() == nullptr) { | |||
| continue; | |||
| } | |||
| ofs << "extern const " << GetTensorDataType(tensor->data_type()) << name << "[];\n"; | |||
| } | |||
| } | |||
| } | |||
| void CodeModelParamsData(std::ofstream &ofs, const std::map<std::string, Tensor *> &weights) { | |||
| for (auto &item : weights) { | |||
| std::string name = item.first; | |||
| Tensor *tensor = item.second; | |||
| if (tensor->category() == Tensor::Category::CONST_TENSOR) { | |||
| if (tensor->data_c() == nullptr) { | |||
| continue; | |||
| } | |||
| ofs << "const " << GetTensorDataType(tensor->data_type()) << name << "[] = "; | |||
| PrintTensorData(tensor, ofs); | |||
| } | |||
| } | |||
| } | |||
| void CodeModelParamsForNet(std::ofstream &hofs, std::ofstream &cofs, const std::unique_ptr<CoderContext> &ctx) { | |||
| // reverse key and value of tensors_map | |||
| std::map<std::string, Tensor *> address_map; | |||
| for (const auto &item : ctx->tensors_map()) { | |||
| address_map.insert(std::make_pair(item.second, item.first)); | |||
| } | |||
| for (auto &item : address_map) { | |||
| std::string name = item.first; | |||
| Tensor *tensor = item.second; | |||
| if (tensor->data_c() == nullptr) { | |||
| continue; | |||
| } | |||
| if (tensor->category() == Tensor::Category::CONST_TENSOR) { | |||
| hofs << "extern " << GetTensorDataType(tensor->data_type()) << name << " = [];\n"; | |||
| cofs << GetTensorDataType(tensor->data_type()) << name << " = [" << tensor->ElementsNum() << "];\n"; | |||
| } else if (tensor->category() == Tensor::Category::VAR) { | |||
| hofs << "extern " << GetTensorDataType(tensor->data_type()) << " *" << name << ";\n"; | |||
| cofs << GetTensorDataType(tensor->data_type()) << "*" << name << " = NULL;\n"; | |||
| } | |||
| } | |||
| cofs << "\n"; | |||
| } | |||
| void CodeWeightInitFunc(std::ofstream &ofs, const std::string &module_name, const std::unique_ptr<CoderContext> &ctx) { | |||
| ofs << "int " << module_name << "_Init(void *weight_buffer, int weight_size) {\n" | |||
| << " if (weight_buffer == NULL) {\n" | |||
| " MICRO_ERROR(\"weight buffer is NULL\");\n" | |||
| << " return RET_ERROR;\n" | |||
| << " }\n"; | |||
| ofs << " struct ModelParameter {\n" | |||
| << " void *addr;\n" | |||
| << " size_t size;\n" | |||
| << " size_t offset;\n" | |||
| << " };\n"; | |||
| size_t params_num = 0; | |||
| size_t offset = 0; | |||
| std::string params; | |||
| std::string origins; | |||
| for (const auto &item : ctx->saved_weights()) { | |||
| std::string name = item.first; | |||
| Tensor *tensor = item.second; | |||
| if (tensor->category() != Tensor::Category::CONST_TENSOR) { | |||
| continue; | |||
| } | |||
| auto iter = ctx->tensors_map().find(tensor); | |||
| if (iter != ctx->tensors_map().end()) { | |||
| origins += " {" + name + ", " + std::to_string(tensor->Size()) + ", " + std::to_string(offset) + "},\n"; | |||
| params_num++; | |||
| } else { | |||
| TypeId data_type = tensor->data_type(); | |||
| params += | |||
| " " + GetTensorDataType(data_type) + "*" + name + " = (weight_buffer + " + std::to_string(offset) + ");\n"; | |||
| } | |||
| } | |||
| ofs << " struct ModelParameter model_params[] = {\n" << origins << " };\n"; | |||
| ofs << params << "\n"; | |||
| ofs << "\n"; | |||
| ofs << " for(int i = 0; i < " << params_num << "; ++i) {\n" | |||
| << " if (model_params[i].offset + model_params[i].size > weight_size) {\n" | |||
| " MICRO_ERROR(\"buffer is invalid, size: %d, offset: %lu\", weight_size, model_params[i].offset);\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n" | |||
| << " memcpy(model_params[i].addr, (weight_buffer + model_params[i].offset), model_params[i].size);\n" | |||
| << " }\n"; | |||
| for (const auto &block : ctx->init_contents()) { | |||
| ofs << "{\n" << block << "}\n"; | |||
| } | |||
| ofs << " return RET_OK;\n"; | |||
| ofs << "}\n\n"; | |||
| } | |||
| void SaveDataToNet(const std::map<std::string, Tensor *> &saved_weights, const std::string &net_file) { | |||
| std::ofstream net(net_file, std::ios::out | std::ios::trunc | std::ios::binary); | |||
| MS_CHECK_TRUE_WITHOUT_RET(net.is_open(), "net file open failed!"); | |||
| for (auto &item : saved_weights) { | |||
| std::string name = item.first; | |||
| Tensor *tensor = item.second; | |||
| if (tensor->category() == Tensor::Category::CONST_TENSOR && tensor->data_c() != nullptr) { | |||
| net.write(reinterpret_cast<const char *>(tensor->data_c()), tensor->Size()); | |||
| } | |||
| } | |||
| net.close(); | |||
| } | |||
| } // namespace mindspore::lite::micro | |||
| @@ -0,0 +1,41 @@ | |||
| /** | |||
| * Copyright 2021 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_MICRO_CODER_GENERATOR_WEIGHT_COMPONENT_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_GENERATOR_WEIGHT_COMPONENT_H_ | |||
| #include <map> | |||
| #include <string> | |||
| #include <vector> | |||
| #include <memory> | |||
| #include <fstream> | |||
| #include "src/tensor.h" | |||
| #include "coder/coder_config.h" | |||
| #include "coder/context.h" | |||
| namespace mindspore::lite::micro { | |||
| void CodeWeightFileHeader(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx); | |||
| void CodeModelParamsState(std::ofstream &ofs, const std::map<std::string, Tensor *> &weights); | |||
| void CodeModelParamsData(std::ofstream &ofs, const std::map<std::string, Tensor *> &weights); | |||
| void SaveDataToNet(const std::map<std::string, Tensor *> &saved_weights, const std::string &net_file); | |||
| void CodeModelParamsForNet(std::ofstream &hofs, std::ofstream &cofs, const std::unique_ptr<CoderContext> &ctx); | |||
| void CodeWeightInitFunc(std::ofstream &ofs, const std::string &module_name, const std::unique_ptr<CoderContext> &ctx); | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_GENERATOR_WEIGHT_COMPONENT_H_ | |||
| @@ -18,15 +18,27 @@ | |||
| #include <map> | |||
| #include <set> | |||
| #include <fstream> | |||
| #include "coder/generator/utils/generator_utils.h" | |||
| #include "coder/generator/const_blocks/cmake_lists_code.h" | |||
| #include "coder/generator/const_blocks/bench_debug_utils.h" | |||
| #include "coder/generator/const_blocks/bench_load_input.h" | |||
| #include "coder/generator/const_blocks/micro_tensor.h" | |||
| #include "coder/generator/const_blocks/license.h" | |||
| #include "coder/generator/component/cmake_component.h" | |||
| #include "coder/generator/component/weight_component.h" | |||
| #include "coder/generator/component/const_blocks/micro_tensor.h" | |||
| #include "coder/generator/component/const_blocks/cmake_lists.h" | |||
| #include "coder/generator/component/const_blocks/debug_utils.h" | |||
| #include "coder/generator/component/const_blocks/load_input.h" | |||
| #include "coder/generator/component/const_blocks/license.h" | |||
| #include "micro/coder/log.h" | |||
| namespace mindspore::lite::micro { | |||
| int WriteContentToFile(const std::string &file, const std::string &content) { | |||
| std::ofstream of(file); | |||
| if (of.bad()) { | |||
| MS_LOG(ERROR) << "open file error " << file; | |||
| return RET_ERROR; | |||
| } | |||
| MS_LOG(INFO) << "write " << file; | |||
| of << content; | |||
| of.close(); | |||
| return RET_OK; | |||
| } | |||
| Generator::Generator(std::unique_ptr<CoderContext> ctx) { | |||
| ctx_ = std::move(ctx); | |||
| @@ -46,104 +58,6 @@ Generator::Generator(std::unique_ptr<CoderContext> ctx) { | |||
| Generator::~Generator() { (void)umask(origin_umask_); } | |||
| int Generator::CodeGraphInOutQuanArgs(std::ofstream &ofs) { | |||
| std::vector<Tensor *> graph_inputs = ctx_->graph_inputs(); | |||
| if (graph_inputs.empty()) { | |||
| MS_LOG(ERROR) << "this graph has no input tensor"; | |||
| return RET_ERROR; | |||
| } | |||
| Tensor *in_tensor = graph_inputs.at(kInputIndex); | |||
| MS_CHECK_PTR(in_tensor); | |||
| std::vector<Tensor *> graph_outputs = ctx_->graph_outputs(); | |||
| if (graph_outputs.empty()) { | |||
| MS_LOG(ERROR) << "this graph has no output tensor"; | |||
| return RET_ERROR; | |||
| } | |||
| Tensor *out_tensor = graph_outputs.at(kOutputIndex); | |||
| MS_CHECK_PTR(out_tensor); | |||
| std::vector<QuantArg> in_quant_args = in_tensor->quant_params(); | |||
| std::vector<QuantArg> out_quant_args = out_tensor->quant_params(); | |||
| if (in_quant_args.empty() || out_quant_args.empty()) { | |||
| MS_LOG(WARNING) << "in_quant_args or out_quant_args is empty"; | |||
| return RET_OK; | |||
| } | |||
| ofs << "GraphQuantArgs " << config_->module_name() << "_GetInOutQuantArgs() {\n" | |||
| << "\t\t" | |||
| << "GraphQuantArgs quan_args = { " << in_quant_args.at(0).scale << ", " << out_quant_args.at(0).scale << ", " | |||
| << in_quant_args.at(0).zeroPoint << ", " << out_quant_args.at(0).zeroPoint << "};\n" | |||
| << "\t\t" | |||
| << "return quan_args;\n" | |||
| << "}\n"; | |||
| return RET_OK; | |||
| } | |||
| int Generator::CodeNetFileInputOutput(std::ofstream &ofs) { | |||
| // input tensors | |||
| ofs << "\n// set input tensors\n"; | |||
| std::vector<Tensor *> inputs = ctx_->graph_inputs(); | |||
| for (size_t i = 0; i < inputs.size(); ++i) { | |||
| ofs << "\nstatic const unsigned char *" << ctx_->input_name() + std::to_string(i) << " = 0;\n"; | |||
| } | |||
| size_t size = inputs.size(); | |||
| ofs << "int " << config_->module_name() << "_SetInputs(const void **inputs, int num) {\n" | |||
| << "if (inputs == NULL) {\n" | |||
| "\treturn RET_ERROR;\n" | |||
| "\t}\n" | |||
| << "\tif (num !=" << size << ") { return RET_ERROR;}\n"; | |||
| for (size_t i = 0; i < size; ++i) { | |||
| ofs << "\t" << ctx_->input_name() + std::to_string(i) << " = inputs[" << i << "];\n"; | |||
| } | |||
| ofs << "\treturn RET_OK;\n}\n"; | |||
| // output tensors | |||
| ofs << "\n// output tensors\n"; | |||
| std::vector<Tensor *> outputs = ctx_->graph_outputs(); | |||
| size_t output_num = outputs.size(); | |||
| std::string output_name = ctx_->output_name(); | |||
| ofs << "const MicroTensorList* " << config_->module_name() << "_GetOutputs() {\n" | |||
| << " static MicroTensor " << output_name << "[" << output_num << "] ;\n"; | |||
| if (PrintMicroTensors(ofs, outputs, output_name, ctx_->tensors_map()) != RET_OK) { | |||
| return RET_ERROR; | |||
| } | |||
| ofs << " static MicroTensorList " << config_->module_name() << "_TensorArray;\n" | |||
| << " " << config_->module_name() << "_TensorArray.num = " << output_num << ";\n" | |||
| << " " << config_->module_name() << "_TensorArray.tensor = &" << output_name << "[0];\n" | |||
| << " return &" << config_->module_name() << "_TensorArray; \n}\n"; | |||
| return RET_OK; | |||
| } | |||
| void Generator::CodeNetFileMembuffer(std::ofstream &ofs) { | |||
| // memory buffer | |||
| ofs << "\n// Get MemBuffer Size\n" | |||
| << "unsigned int " << config_->module_name() << "_GetBufferSize() {\n" | |||
| << "\t return " << ctx_->total_buffer_size() << "; \n}\n"; | |||
| ofs << "\n// set Membuffer address\n"; | |||
| ofs << "int " << config_->module_name() << "_SetBuffer( void *buffer) { \n"; | |||
| ofs << "\tif (buffer == NULL) {\n" | |||
| "\t\tMICRO_ERROR(\"memory buffer is NULL\");\n" | |||
| "\t\treturn RET_ERROR;\n" | |||
| "\t}\n"; | |||
| ofs << "\t" << ctx_->buffer_name() | |||
| << "= buffer; \n" | |||
| "\treturn RET_OK;"; | |||
| ofs << "}\n"; | |||
| } | |||
| void Generator::CodeNetFileInclude(std::ofstream &ofs) { | |||
| ofs << g_hwLicense; | |||
| // need copy head file of microtensor ro dst'dirs | |||
| ofs << "#include \"microtensor.h\"\n"; | |||
| // copy debug head files to cmake include files | |||
| ofs << "#include \"" << net_weight_hfile_ << "\"\n" | |||
| << "#include \"" << net_inc_hfile_ << "\"\n"; | |||
| if (config_->debug_mode()) { | |||
| ofs << "#include \"../benchmark/debug_utils.h\"\n"; | |||
| } | |||
| } | |||
| void Generator::CodeNetRunFunc(std::ofstream &ofs) { | |||
| // generate net predict code | |||
| ofs << "void " << config_->module_name() << "_Inference() {\n"; | |||
| @@ -158,69 +72,30 @@ void Generator::CodeNetRunFunc(std::ofstream &ofs) { | |||
| ofs << "}\n"; | |||
| } | |||
| int Generator::CodeTestCMakeFile() { | |||
| int Generator::CodeBenchmarkCMakeFile() { | |||
| std::string net_main_cmake_file_path = net_main_file_path_; | |||
| std::string test_cmake_file = net_main_cmake_file_path + "benchmark.cmake"; | |||
| std::ofstream of(test_cmake_file); | |||
| if (of.bad()) { | |||
| MS_LOG(ERROR) << "open file error " << test_cmake_file; | |||
| return RET_ERROR; | |||
| } | |||
| std::ofstream ofs(test_cmake_file); | |||
| MS_CHECK_TRUE(!ofs.bad(), "filed to open file"); | |||
| MS_LOG(INFO) << "write " << test_cmake_file; | |||
| of << "include_directories(${CMAKE_CURRENT_SOURCE_DIR})\n"; | |||
| of << "include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include/)\n"; | |||
| of << "set(SRC_FILES\n"; | |||
| of << "\t\t" << config_->module_name() + "_benchmark.c\n"; | |||
| of << "\t\tload_input.c\n"; | |||
| of << "\t\tdebug_utils.c\n"; | |||
| of << ")\n"; | |||
| of.close(); | |||
| return RET_OK; | |||
| } | |||
| int Generator::CodeCMakeExecutableFile(std::ofstream &ofs) const { | |||
| ofs << "include_directories(${CMAKE_CURRENT_SOURCE_DIR})\n"; | |||
| ofs << "include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include/)\n"; | |||
| if (config_->target() == kARM32M) { | |||
| IncludeCmsisDirectories(ofs); | |||
| } | |||
| ofs << "set(OP_SRC\n"; | |||
| for (const std::string &c_file : ctx_->c_files()) { | |||
| ofs << " " << c_file << ".o\n"; | |||
| } | |||
| ofs << " " << config_->module_name() << "_weight.c.o\n"; | |||
| ofs << " " << config_->module_name() << ".c.o\n"; | |||
| ofs << "set(SRC_FILES\n"; | |||
| ofs << "\t\t" << config_->module_name() + "_benchmark.c\n"; | |||
| ofs << "\t\tload_input.c\n"; | |||
| ofs << "\t\tdebug_utils.c\n"; | |||
| ofs << ")\n"; | |||
| std::set<std::string> kernel_cmake_asm_set_files = ctx_->asm_files(); | |||
| if (!kernel_cmake_asm_set_files.empty()) { | |||
| ofs << "set(ASSEMBLY_SRC\n"; | |||
| for (const std::string &asm_file : kernel_cmake_asm_set_files) { | |||
| ofs << " " << asm_file << ".o\n"; | |||
| } | |||
| ofs << ")\n"; | |||
| ofs << "set_property(SOURCE ${ASSEMBLY_SRC} PROPERTY LANGUAGE C)\n"; | |||
| ofs << "list(APPEND OP_SRC ${ASSEMBLY_SRC})\n"; | |||
| } | |||
| ofs << "file(GLOB NET_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.c)\n"; | |||
| ofs << "add_library(${PROJ_NAME} STATIC ${NET_SRC})\n"; | |||
| ofs.close(); | |||
| return RET_OK; | |||
| } | |||
| int Generator::CodeCMakeFile() { | |||
| int Generator::CodeSourceCMakeFile() { | |||
| std::string src_cmake_file = net_src_file_path_ + cmake_file_name_; | |||
| std::ofstream of(src_cmake_file); | |||
| if (of.bad()) { | |||
| MS_LOG(ERROR) << "open file error " << src_cmake_file; | |||
| return RET_ERROR; | |||
| } | |||
| MS_LOG(INFO) << "write " << src_cmake_file.c_str(); | |||
| if (CodeCMakeExecutableFile(of) != RET_OK) { | |||
| of.close(); | |||
| return RET_ERROR; | |||
| } | |||
| of.close(); | |||
| std::ofstream ofs(src_cmake_file); | |||
| MS_CHECK_TRUE(!ofs.bad(), "filed to open file"); | |||
| MS_LOG(INFO) << "write " << src_cmake_file; | |||
| CodeCMakeNetLibrary(ofs, config_->module_name(), ctx_, config_->target()); | |||
| ofs.close(); | |||
| return RET_OK; | |||
| } | |||
| @@ -243,86 +118,32 @@ int Generator::CodeStaticContent() { | |||
| return RET_OK; | |||
| } | |||
| void Generator::CodeWeightInitFunc(const std::map<std::string, Tensor *> &address_map, std::ofstream &ofs) { | |||
| ofs << "int " << config_->module_name() << "_Init(void *weight_buffer, int weight_size) {\n" | |||
| << "\tif (weight_buffer == NULL) {\n" | |||
| "\t\tMICRO_ERROR(\"weight buffer is NULL\");\n" | |||
| << "\t\treturn RET_ERROR;\n" | |||
| << "\t}\n"; | |||
| CodeReadModelParams(ctx_->saved_weights(), ctx_->tensors_map(), ofs); | |||
| for (const auto &block : ctx_->init_contents()) { | |||
| ofs << "{\n" << block << "\n}\n"; | |||
| } | |||
| ofs << "return RET_OK;"; | |||
| ofs << "}\n\n"; | |||
| } | |||
| void Generator::CodeFreeResource(const std::map<std::string, Tensor *> &address_map, std::ofstream &ofs) const { | |||
| ofs << "\tvoid *allocated[] = {"; | |||
| size_t num = 0; | |||
| for (const auto &item : address_map) { | |||
| std::string name = item.first; | |||
| Tensor *tensor = item.second; | |||
| if (tensor->data_c() != nullptr && tensor->category() != Tensor::Category::CONST_TENSOR) { | |||
| ofs << name << ", "; | |||
| num++; | |||
| } | |||
| } | |||
| ofs << "\t};\n"; | |||
| ofs << "\tfor (int i = 0; i < " << num << "; ++i) {\n"; | |||
| ofs << "\t\tfree(allocated[i]);\n"; | |||
| ofs << "\t\tallocated[i] = NULL;\n"; | |||
| ofs << "\t}\n"; | |||
| } | |||
| int Generator::CodeWeightFile() { | |||
| // weight header file | |||
| std::string hfile = net_src_file_path_ + net_weight_hfile_; | |||
| std::ofstream hofs(hfile); | |||
| if (hofs.bad()) { | |||
| MS_LOG(ERROR) << "open file error" << hfile; | |||
| return RET_ERROR; | |||
| } | |||
| hofs << g_hwLicense; | |||
| for (const auto &h_file : ctx_->h_files()) { | |||
| hofs << "#include \"" << h_file << "\"\n"; | |||
| } | |||
| hofs << "#include <stdlib.h>\n"; | |||
| hofs << "#include <string.h>\n"; | |||
| hofs << "#include \"microtensor.h\"\n\n"; | |||
| hofs << "extern unsigned char *" << ctx_->buffer_name() << ";\n"; | |||
| MS_CHECK_TRUE(!hofs.bad(), "filed to open file"); | |||
| MS_LOG(INFO) << "write " << hfile; | |||
| CodeWeightFileHeader(hofs, ctx_); | |||
| // weight source file | |||
| std::string cfile = net_src_file_path_ + config_->module_name() + "_weight.c"; | |||
| std::ofstream cofs(cfile); | |||
| if (cofs.bad()) { | |||
| MS_LOG(ERROR) << "open file error" << cfile; | |||
| return RET_ERROR; | |||
| } | |||
| MS_CHECK_TRUE(!cofs.bad(), "filed to open file"); | |||
| MS_LOG(INFO) << "write " << cfile; | |||
| cofs << g_hwLicense; | |||
| cofs << "#include \"" << net_weight_hfile_ << "\"\n\n"; | |||
| cofs << "unsigned char * " << ctx_->buffer_name() << " = 0 ; \n"; | |||
| // reverse key and value of tensors_map | |||
| std::map<std::string, Tensor *> address_map; | |||
| for (const auto &item : ctx_->tensors_map()) { | |||
| address_map.insert(std::make_pair(item.second, item.first)); | |||
| } | |||
| if (config_->is_weight_file()) { | |||
| std::string net_file = net_src_file_path_ + config_->module_name() + ".net"; | |||
| if (SaveDataToNet(ctx_->saved_weights(), net_file) != RET_OK) { | |||
| hofs.close(); | |||
| cofs.close(); | |||
| return RET_ERROR; | |||
| } | |||
| CodeModelParamsDefine(address_map, hofs, cofs); | |||
| CodeWeightInitFunc(address_map, cofs); | |||
| SaveDataToNet(ctx_->saved_weights(), net_file); | |||
| CodeModelParamsForNet(hofs, cofs, ctx_); | |||
| CodeWeightInitFunc(cofs, config_->module_name(), ctx_); | |||
| } else { | |||
| CodeModelParamsDefineAndData(ctx_->saved_weights(), hofs, cofs); | |||
| CodeModelParamsState(hofs, ctx_->saved_weights()); | |||
| CodeModelParamsData(cofs, ctx_->saved_weights()); | |||
| } | |||
| hofs.close(); | |||
| cofs.close(); | |||
| return RET_OK; | |||
| @@ -332,9 +153,9 @@ int Generator::GenerateCode() { | |||
| MS_CHECK_RET_CODE(CodeNetHFile(), "code net h file failed."); | |||
| MS_CHECK_RET_CODE(CodeNetCFile(), "code net c file failed."); | |||
| MS_CHECK_RET_CODE(CodeWeightFile(), "code weight file failed."); | |||
| MS_CHECK_RET_CODE(CodeCMakeFile(), "code net cmake file failed."); | |||
| MS_CHECK_RET_CODE(CodeTestFile(), "code test file failed."); | |||
| MS_CHECK_RET_CODE(CodeTestCMakeFile(), "code test cmake file failed."); | |||
| MS_CHECK_RET_CODE(CodeSourceCMakeFile(), "code net cmake file failed."); | |||
| MS_CHECK_RET_CODE(CodeBenchmarkFile(), "code benchmark file failed."); | |||
| MS_CHECK_RET_CODE(CodeBenchmarkCMakeFile(), "code benchmark cmake file failed."); | |||
| MS_CHECK_RET_CODE(CodeStaticContent(), "code static content failed."); | |||
| return RET_OK; | |||
| } | |||
| @@ -14,8 +14,8 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MINDSPORE_MICRO_CODER_GENERATOR_H_ | |||
| #define MINDSPORE_MICRO_CODER_GENERATOR_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_GENERATOR_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_GENERATOR_H_ | |||
| #include <sys/stat.h> | |||
| #include <fstream> | |||
| @@ -28,13 +28,12 @@ | |||
| #include <vector> | |||
| #include "include/errorcode.h" | |||
| #include "src/tensor.h" | |||
| #include "coder/log.h" | |||
| #include "coder/coder_config.h" | |||
| #include "coder/coder_context.h" | |||
| #include "coder/utils/print_utils.h" | |||
| #include "coder/context.h" | |||
| #include "coder/utils/type_cast.h" | |||
| namespace mindspore::lite::micro { | |||
| constexpr int kWarmUp = 3; | |||
| class Generator { | |||
| public: | |||
| explicit Generator(std::unique_ptr<CoderContext> ctx); | |||
| @@ -43,18 +42,12 @@ class Generator { | |||
| int GenerateCode(); | |||
| protected: | |||
| virtual int CodeTestFile() = 0; | |||
| virtual int CodeBenchmarkFile() = 0; | |||
| virtual int CodeNetHFile() = 0; | |||
| virtual int CodeNetCFile() = 0; | |||
| virtual int CodeCMakeFile(); | |||
| virtual int CodeWeightFile(); | |||
| void CodeNetFileInclude(std::ofstream &ofs); | |||
| int CodeNetFileInputOutput(std::ofstream &ofs); | |||
| void CodeNetFileMembuffer(std::ofstream &ofs); | |||
| void CodeNetRunFunc(std::ofstream &ofs); | |||
| int CodeGraphInOutQuanArgs(std::ofstream &ofs); | |||
| void CodeFreeResource(const std::map<std::string, Tensor *> &address_map, std::ofstream &ofs) const; | |||
| Configurator *config_{nullptr}; | |||
| std::unique_ptr<CoderContext> ctx_{nullptr}; | |||
| @@ -70,10 +63,9 @@ class Generator { | |||
| std::string net_main_file_path_; | |||
| private: | |||
| int CodeTestCMakeFile(); | |||
| int CodeBenchmarkCMakeFile(); | |||
| int CodeSourceCMakeFile(); | |||
| int CodeStaticContent(); | |||
| int CodeCMakeExecutableFile(std::ofstream &ofs) const; | |||
| void CodeWeightInitFunc(const std::map<std::string, Tensor *> &address_map, std::ofstream &ofs); | |||
| std::string cmake_file_name_{"net.cmake"}; | |||
| // the user's generated file's permission | |||
| @@ -84,4 +76,4 @@ class Generator { | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MINDSPORE_MICRO_CODER_GENERATOR_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_GENERATOR_H_ | |||
| @@ -16,284 +16,75 @@ | |||
| #include "coder/generator/inference/inference_generator.h" | |||
| #include <vector> | |||
| #include <map> | |||
| #include <set> | |||
| #include <string> | |||
| #include "coder/generator/const_blocks/license.h" | |||
| #include "coder/generator/component/common_component.h" | |||
| #include "coder/generator/component/benchmark_component.h" | |||
| #include "coder/generator/component/const_blocks/license.h" | |||
| namespace mindspore::lite::micro { | |||
| int InferenceGenerator::CodeNetHFile() { | |||
| std::string net_include_file = net_inc_file_path_ + net_inc_hfile_; | |||
| std::ofstream ofs(net_include_file); | |||
| if (ofs.bad()) { | |||
| MS_LOG(ERROR) << "open file error " << net_include_file.c_str(); | |||
| return RET_ERROR; | |||
| } | |||
| MS_CHECK_TRUE(!ofs.bad(), "filed to open file"); | |||
| MS_LOG(INFO) << "write " << net_include_file; | |||
| ofs << g_hwLicense; | |||
| if (config_->code_mode() == CodeMode::Code_Android) { | |||
| ofs << "#include \"src/runtime/thread_pool.h\"\n"; | |||
| } | |||
| ofs << "#include \"microtensor.h\"\n\n"; | |||
| ofs << "/**\n" | |||
| << " * set input tensors\n" | |||
| << " * @param inputs, the input data ptr's array of the model, the tensors' count of input may be greater than " | |||
| "one.\n" | |||
| << " * @param num, the input data's number of the model.\n" | |||
| << " **/\n" | |||
| << "int " << config_->module_name() << "_SetInputs(const void **inputs, int num);\n\n"; | |||
| ofs << "/**\n" | |||
| << " * get output tensor of the model \n" | |||
| << " **/\n" | |||
| << "const MicroTensorList *" << config_->module_name() << "_GetOutputs();\n\n"; | |||
| CodeInputAndOutputState(ofs, config_->module_name()); | |||
| if (is_get_quant_args_) { | |||
| std::vector<Tensor *> graph_inputs = ctx_->graph_inputs(); | |||
| if (graph_inputs.empty()) { | |||
| MS_LOG(ERROR) << "this graph has no input tensor"; | |||
| ofs.close(); | |||
| return RET_ERROR; | |||
| } | |||
| size_t total_input_size = std::accumulate( | |||
| graph_inputs.begin(), graph_inputs.end(), 0UL, | |||
| [](size_t total_input_size, const Tensor *const tensor) { return total_input_size += tensor->Size(); }); | |||
| ofs << "/**\n"; | |||
| ofs << " * get input sizes of the model \n"; | |||
| ofs << " **/\n"; | |||
| ofs << "inline int " << config_->module_name() << "_GetInputSizes() {\n" | |||
| << "\t\t" | |||
| << "return " << total_input_size << ";\n" | |||
| << "}\n\n"; | |||
| ofs << "/**\n"; | |||
| ofs << " * get input and output QuantArgs of the model \n"; | |||
| ofs << " **/\n"; | |||
| ofs << "GraphQuantArgs " << config_->module_name() << "_GetInOutQuantArgs();\n\n"; | |||
| CodeGraphQuantArgsState(ofs, config_->module_name()); | |||
| } | |||
| if (config_->is_weight_file()) { | |||
| ofs << "/**\n" | |||
| << " * @param weightBuffer, the ptr of the model's parameters\n" | |||
| << " * @param weightSize, the size of the model's parameters\n" | |||
| << " **/\n" | |||
| << "int " << config_->module_name() << "_Init(void *weightBuffer, int weightSize);\n\n"; | |||
| CodeInitWeightState(ofs, config_->module_name()); | |||
| } | |||
| ofs << "/**\n" | |||
| << " * free the memory of packed weights and model's workspace buffer, input address\n" | |||
| << " **/\n" | |||
| << "void " << config_->module_name() << "_FreeResource();\n"; | |||
| ofs << "/**\n" | |||
| << " * get the memory space size of the inference.\n" | |||
| << " **/\n" | |||
| << "unsigned int " << config_->module_name() << "_GetBufferSize();\n"; | |||
| ofs << "/**\n" | |||
| << " * set the memory space for the inference\n" | |||
| << " **/\n" | |||
| << "int " << config_->module_name() << "_SetBuffer(void *buffer);\n\n"; | |||
| ofs << "/**\n" | |||
| << " * net inference function\n" | |||
| << " **/\n" | |||
| << "void " << config_->module_name() << "_Inference();\n\n"; | |||
| CodeManageResourceState(ofs, config_->module_name()); | |||
| CodeInferenceState(ofs, config_->module_name()); | |||
| return RET_OK; | |||
| } | |||
| int InferenceGenerator::CodeNetCFile() { | |||
| std::string net_impl_file = net_src_file_path_ + net_src_cfile_; | |||
| std::ofstream ofs(net_impl_file); | |||
| if (ofs.bad()) { | |||
| MS_LOG(ERROR) << "open file error" << net_impl_file.c_str(); | |||
| return RET_ERROR; | |||
| } | |||
| MS_LOG(DEBUG) << "write " << net_impl_file.c_str(); | |||
| CodeNetFileInclude(ofs); | |||
| CodeNetFileMembuffer(ofs); | |||
| MS_CHECK_TRUE(!ofs.bad(), "filed to open file"); | |||
| MS_LOG(INFO) << "write " << net_impl_file; | |||
| CodeSourceFileInclude(ofs, net_weight_hfile_, net_inc_hfile_); | |||
| CodeInputAndOutputImplement(ofs, config_->module_name(), ctx_); | |||
| CodeInitResourceImplement(ofs, config_->module_name(), ctx_); | |||
| CodeFreeResourceImplement(ofs, config_->module_name(), ctx_); | |||
| if (is_get_quant_args_) { | |||
| if (CodeGraphInOutQuanArgs(ofs) != RET_OK) { | |||
| MS_LOG(ERROR) << "CodeGraphInOutQuanArgs failed"; | |||
| ofs.close(); | |||
| return RET_ERROR; | |||
| } | |||
| } | |||
| if (CodeNetFileInputOutput(ofs) != RET_OK) { | |||
| ofs.close(); | |||
| return RET_ERROR; | |||
| CodeGraphQuantArgsImplement(ofs, config_->module_name(), ctx_); | |||
| } | |||
| ofs << "void " << config_->module_name() << "_FreeResource() {\n"; | |||
| ofs << "\t" << ctx_->buffer_name() << "= NULL;\n"; | |||
| std::vector<Tensor *> inputs = ctx_->graph_inputs(); | |||
| size_t size = inputs.size(); | |||
| for (size_t i = 0; i < size; ++i) { | |||
| ofs << "\t" << ctx_->input_name() + std::to_string(i) << " = NULL;\n"; | |||
| } | |||
| std::map<std::string, Tensor *> address_map; | |||
| for (const auto &item : ctx_->tensors_map()) { | |||
| address_map.insert(std::make_pair(item.second, item.first)); | |||
| } | |||
| if (config_->is_weight_file()) { | |||
| CodeFreeResource(address_map, ofs); | |||
| } | |||
| ofs << "}\n"; | |||
| CodeNetRunFunc(ofs); | |||
| ofs.close(); | |||
| return RET_OK; | |||
| } | |||
| void InferenceGenerator::CodeTestRelevantHeader(std::ofstream &code_test_ofs) { | |||
| code_test_ofs << g_hwLicense; | |||
| code_test_ofs << "#include <stdio.h>\n" | |||
| "#include <string.h>\n" | |||
| "#include <stdlib.h>\n" | |||
| "#include <stdint.h>\n" | |||
| "#include \"microtensor.h\"\n" | |||
| "#include \"load_input.h\"\n" | |||
| "#include \"debug_utils.h\"\n"; | |||
| code_test_ofs << "#include \"" << net_inc_hfile_ << "\"\n"; | |||
| code_test_ofs << "/**\n" | |||
| " * mindspore micro params usage:\n" | |||
| " * args[0]: executable file\n" | |||
| " * args[1]: inputs .bin file\n" | |||
| " * args[2]: model weight .net file\n" | |||
| " * args[3]: loop count for performance testing\n" | |||
| " * args[4]: runtime thread num\n" | |||
| " * args[5]: runtime thread bind mode\n" | |||
| " */\n"; | |||
| code_test_ofs << "\n// Warm up. \n" | |||
| << "void " << config_->module_name() << "_WarmUp() {\n" | |||
| << "\tfor (int i = 0; i < " << kWarmUp << "; ++i) {\n" | |||
| << "\t\t" << config_->module_name() << "_Inference();\n" | |||
| << "\t}\n" | |||
| << "}\n"; | |||
| } | |||
| void InferenceGenerator::CodeTestRelevantTile(std::ofstream &code_test_ofs) { | |||
| if (config_->code_mode() == Code_Android) { | |||
| code_test_ofs << " DestroyThreadPool(THREAD_POOL_DEFAULT);\n"; | |||
| } | |||
| code_test_ofs << " // print model outputs \n"; | |||
| code_test_ofs << " const MicroTensorList *outs = " << config_->module_name() << "_GetOutputs();\n"; | |||
| code_test_ofs << " for (int i = 0; i < outs->num; ++i) {\n" | |||
| " MicroTensor *tensor = outs->tensor + i;\n" | |||
| " PrintTensorData(tensor);\n" | |||
| " }\n"; | |||
| code_test_ofs << " printf(\"" << config_->module_name() << " inference End.\\n\");\n"; | |||
| code_test_ofs << " free(buffer);\n"; | |||
| code_test_ofs << " " << config_->module_name() << "_FreeResource();\n"; | |||
| std::vector<Tensor *> inputs = ctx_->graph_inputs(); | |||
| size_t inputs_num = inputs.size(); | |||
| code_test_ofs << " // this code_block can be ignore \n"; | |||
| code_test_ofs << " for (int i = 0; i < " << inputs_num | |||
| << "; ++i) {\n" | |||
| " free(inputs_binbuf[i]);\n" | |||
| " }\n"; | |||
| code_test_ofs << " return 0;\n"; | |||
| code_test_ofs << "}\n"; | |||
| } | |||
| int InferenceGenerator::CodeTestFile() { | |||
| int InferenceGenerator::CodeBenchmarkFile() { | |||
| std::string net_main_impl_file = net_main_file_path_ + net_main_cfile_; | |||
| std::ofstream ofs(net_main_impl_file); | |||
| if (ofs.bad()) { | |||
| MS_LOG(ERROR) << "open file error " << net_main_impl_file.c_str(); | |||
| return RET_ERROR; | |||
| } | |||
| MS_LOG(INFO) << "write " << net_main_impl_file.c_str(); | |||
| CodeTestRelevantHeader(ofs); | |||
| ofs << "int main(int argc, char **argv) {\n" | |||
| " if (argc < 2) { printf(\"There is not input and out file.\\n\"); }\n"; | |||
| ofs << " printf(\"" << config_->module_name() << " inference Start.\\n\");\n"; | |||
| MS_LOG(INFO) << "write " << net_main_impl_file; | |||
| MS_CHECK_TRUE(!ofs.bad(), "filed to open file"); | |||
| std::vector<Tensor *> inputs = ctx_->graph_inputs(); | |||
| size_t inputs_num = inputs.size(); | |||
| for (size_t i = 0; i < inputs_num; ++i) { | |||
| Tensor *input = inputs[i]; | |||
| std::vector<int> shape = input->shape(); | |||
| ofs << " // model's input_shape is [ "; | |||
| for (int sh : shape) { | |||
| ofs << sh << ", "; | |||
| } | |||
| ofs << "];\n"; | |||
| } | |||
| ofs << " void *inputs_binbuf[" << inputs_num << "];\n"; | |||
| ofs << " int inputs_size[" << inputs_num << "] = {"; | |||
| for (size_t i = 0; i < inputs_num; ++i) { | |||
| Tensor *input = inputs[i]; | |||
| ofs << input->Size() << ", "; | |||
| } | |||
| ofs << "};\n"; | |||
| ofs << " int ret = ReadInputsFile(argv[1], inputs_binbuf, inputs_size, " << inputs_num | |||
| << ");\n" | |||
| " if (ret != RET_OK) {\n" | |||
| " MICRO_ERROR(\"read inputs file failed\");\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n"; | |||
| ofs << " ret = " << config_->module_name() << "_SetInputs((const void **)inputs_binbuf, " << inputs_num | |||
| << ");\n" | |||
| " if (ret != RET_OK) {\n" | |||
| " MICRO_ERROR(\"set inputs failed\");\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n"; | |||
| ofs << " unsigned int total_buffer_size = " << config_->module_name() << "_GetBufferSize();\n"; | |||
| ofs << " void *buffer = malloc(total_buffer_size);\n"; | |||
| ofs << " if (buffer == NULL ){\n" | |||
| " MICRO_ERROR(\"malloc memory buffer failed\");\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n"; | |||
| ofs << " ret = " << config_->module_name() | |||
| << "_SetBuffer(buffer);\n" | |||
| " if (ret != RET_OK) {\n" | |||
| " MICRO_ERROR(\"set inputs failed\");\n" | |||
| " return RET_ERROR;" | |||
| " }\n"; | |||
| CodeBenchmarkHeader(ofs, net_inc_hfile_); | |||
| CodeBenchmarkUsage(ofs); | |||
| CodeBenchmarkWarmup(ofs, config_->module_name()); | |||
| CodeBenchmarkSetInputs(ofs, config_->module_name(), ctx_); | |||
| CodeBenchmarkSetBuffer(ofs, config_->module_name()); | |||
| if (config_->is_weight_file()) { | |||
| ofs << " int weightSize = 0;\n"; | |||
| ofs << " void *weightBuffer = ReadInputData(argv[2], &weightSize); \n"; | |||
| ofs << " if(" << config_->module_name() << "_Init(weightBuffer, weightSize) != RET_OK) {\n"; | |||
| ofs << " printf(\"model init failed\");\n"; | |||
| ofs << " " << config_->module_name() << "_FreeResource();\n"; | |||
| ofs << " return RET_ERROR;\n"; | |||
| ofs << " }\n"; | |||
| ofs << " free(weightBuffer);\n"; | |||
| ofs << " weightBuffer = NULL;\n"; | |||
| CodeBenchmarkInitWeight(ofs, config_->module_name()); | |||
| } | |||
| if (config_->code_mode() == CodeMode::Code_Android) { | |||
| ofs << " int thread_num = 4;\n" | |||
| " BindMode bind_mode = NO_BIND_MODE;\n" | |||
| " if (argc >= 6) {\n" | |||
| " thread_num = atoi(argv[4]);\n" | |||
| " bind_mode = atoi(argv[5]);\n" | |||
| " }\n" | |||
| " ret = ConfigThreadPool(THREAD_POOL_DEFAULT, thread_num, bind_mode);\n" | |||
| " if (ret != 0) {\n" | |||
| " printf(\"create thread pool failed\");\n" | |||
| " }\n"; | |||
| CodeBenchmarkConfigThread(ofs); | |||
| } | |||
| ofs << " if (argc >= 4) {\n" | |||
| << " " << config_->module_name() << "_WarmUp();\n" | |||
| << " uint64_t timeAvg = 0;\n" | |||
| << " int loop_count = atoi(argv[3]);\n" | |||
| << " printf(\"\\n### begin to run %d\", loop_count);\n" | |||
| << " for (int i = 0; i < loop_count; i++) {\n" | |||
| << " uint64_t runBegin = GetTimeUs();\n" | |||
| << " " << config_->module_name() << "_Inference();\n" | |||
| << " uint64_t runEnd = GetTimeUs();\n" | |||
| << " uint64_t time = runEnd - runBegin;\n" | |||
| << " timeAvg += time;\n" | |||
| << " }\n" | |||
| << " float cunCost = (float)timeAvg / 1000.0f;\n" | |||
| << " printf(\"\\n###Run over, total time:\\t %5.5f ms.\\n\", cunCost);\n" | |||
| << " printf(\"\\n###Run over, predict per time:\\t %5.5f ms.\\n\", cunCost / loop_count);\n" | |||
| << " }\n"; | |||
| ofs << " " << config_->module_name() << "_Inference();\n"; | |||
| CodeTestRelevantTile(ofs); | |||
| CodeBenchmarkInference(ofs, config_->module_name()); | |||
| CodeBenchmarkPrintOutputs(ofs, config_->module_name()); | |||
| CodeBenchmarkFreeResourse(ofs, config_->module_name(), inputs_num); | |||
| ofs.close(); | |||
| return RET_OK; | |||
| } | |||
| @@ -14,8 +14,8 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MINDSPORE_MICRO_CODER_ANDROID_GENERATOR_H_ | |||
| #define MINDSPORE_MICRO_CODER_ANDROID_GENERATOR_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_GENERATOR_INFERENCE_GENERATOR_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_GENERATOR_INFERENCE_GENERATOR_H_ | |||
| #include <utility> | |||
| #include <memory> | |||
| @@ -27,15 +27,11 @@ class InferenceGenerator : public Generator { | |||
| explicit InferenceGenerator(std::unique_ptr<CoderContext> ctx) : Generator(std::move(ctx)) {} | |||
| ~InferenceGenerator() override = default; | |||
| protected: | |||
| private: | |||
| int CodeNetHFile() override; | |||
| int CodeNetCFile() override; | |||
| int CodeTestFile() override; | |||
| private: | |||
| void CodeTestRelevantHeader(std::ofstream &code_test_ofs); | |||
| void CodeTestRelevantTile(std::ofstream &code_test_ofs); | |||
| int CodeBenchmarkFile() override; | |||
| }; | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MINDSPORE_MICRO_CODER_ANDROID_GENERATOR_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_GENERATOR_INFERENCE_GENERATOR_H_ | |||
| @@ -1,172 +0,0 @@ | |||
| /** | |||
| * Copyright 2021 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 "coder/generator/utils/generator_utils.h" | |||
| #include <map> | |||
| #include <fstream> | |||
| #include <vector> | |||
| #include <utility> | |||
| #include <string> | |||
| #include "include/errorcode.h" | |||
| #include "coder/log.h" | |||
| #include "coder/utils/print_utils.h" | |||
| #include "src/common/file_utils.h" | |||
| namespace mindspore::lite::micro { | |||
| int WriteContentToFile(const std::string &file, const std::string &content) { | |||
| std::ofstream of(file); | |||
| if (of.bad()) { | |||
| MS_LOG(ERROR) << "open file error " << file.c_str(); | |||
| return RET_ERROR; | |||
| } | |||
| MS_LOG(INFO) << "write " << file.c_str(); | |||
| of << content; | |||
| of.close(); | |||
| return RET_OK; | |||
| } | |||
| void CodeReadModelParams(const std::map<std::string, Tensor *> &saved_weights, | |||
| const std::map<Tensor *, std::string> &tensors_map, std::ofstream &ofs) { | |||
| ofs << "\n\tstruct ModelParameter {\n" | |||
| << "\t\tvoid *addr;\n" | |||
| << "\t\tsize_t size;\n" | |||
| << "\t\tsize_t offset;\n" | |||
| << "\t};\n"; | |||
| size_t params_num = 0; | |||
| size_t offset = 0; | |||
| ofs << "\n\tstruct ModelParameter model_params[] = {\n"; | |||
| for (const auto &item : saved_weights) { | |||
| std::string name = item.first; | |||
| Tensor *tensor = item.second; | |||
| if (tensor->category() == Tensor::Category::CONST_TENSOR) { | |||
| auto iter = std::find_if(tensors_map.begin(), tensors_map.end(), | |||
| [&tensor](const std::pair<Tensor *, std::string> &t) { return t.first == tensor; }); | |||
| if (iter != tensors_map.end()) { | |||
| ofs << "\t\t{" << name << ", " << tensor->Size() << ", " << offset << "},\n"; | |||
| params_num++; | |||
| } | |||
| offset += tensor->Size(); | |||
| } | |||
| } | |||
| ofs << "\t};\n"; | |||
| offset = 0; | |||
| for (const auto &item : saved_weights) { | |||
| std::string name = item.first; | |||
| Tensor *tensor = item.second; | |||
| if (tensor->category() == Tensor::Category::CONST_TENSOR) { | |||
| auto iter = std::find_if(tensors_map.begin(), tensors_map.end(), | |||
| [&tensor](const std::pair<Tensor *, std::string> &t) { return t.first == tensor; }); | |||
| if (iter == tensors_map.end()) { | |||
| TypeId data_type = tensor->data_type(); | |||
| ofs << "\t" << GetTensorDataType(data_type) << "*" << name << " = (weight_buffer + " << offset << ");\n"; | |||
| } | |||
| offset += tensor->Size(); | |||
| } | |||
| } | |||
| ofs << "\n"; | |||
| ofs << "\tfor(int i = 0; i < " << params_num << "; ++i) {\n" | |||
| << "\t\tif (model_params[i].offset + model_params[i].size > weight_size) {\n" | |||
| "\t\t\tMICRO_ERROR(\"buffer is invalid, size: %d, offset: %lu\", weight_size, model_params[i].offset);\n" | |||
| "\t\t\treturn RET_ERROR;\n" | |||
| "\t\t}\n" | |||
| << "\t\tmemcpy(model_params[i].addr, (weight_buffer + model_params[i].offset), model_params[i].size);\n" | |||
| << "\t}\n"; | |||
| } | |||
| int SaveDataToNet(const std::map<std::string, Tensor *> &tensors_map, const std::string &net_file) { | |||
| std::ofstream out(net_file, std::ios::out | std::ios::trunc | std::ios::binary); | |||
| MS_CHECK_TRUE(out.is_open(), "net file open failed!"); | |||
| for (auto &item : tensors_map) { | |||
| std::string name = item.first; | |||
| Tensor *tensor = item.second; | |||
| if (tensor->category() == Tensor::Category::CONST_TENSOR) { | |||
| if (tensor->data_c() == nullptr) { | |||
| continue; | |||
| } | |||
| out.write(reinterpret_cast<const char *>(tensor->data_c()), tensor->Size()); | |||
| } | |||
| } | |||
| out.close(); | |||
| return RET_OK; | |||
| } | |||
| void CodeModelParamsDefine(const std::map<std::string, Tensor *> &address_map, std::ofstream &hfile, | |||
| std::ofstream &cfile) { | |||
| for (auto &item : address_map) { | |||
| std::string name = item.first; | |||
| Tensor *tensor = item.second; | |||
| if (tensor->data_c() == nullptr) { | |||
| continue; | |||
| } | |||
| if (tensor->category() == Tensor::Category::CONST_TENSOR) { | |||
| PrintTensorForNet(tensor, cfile, hfile, name); | |||
| } else if (tensor->category() == Tensor::Category::VAR) { | |||
| hfile << "extern " << GetTensorDataType(tensor->data_type()) << " *" << name << ";\n"; | |||
| cfile << GetTensorDataType(tensor->data_type()) << "*" << name << " = NULL;\n"; | |||
| } | |||
| } | |||
| cfile << "\n"; | |||
| } | |||
| void CodeModelParamsDefineAndData(const std::map<std::string, Tensor *> &address_map, std::ofstream &hfile, | |||
| std::ofstream &cfile) { | |||
| for (auto &item : address_map) { | |||
| std::string name = item.first; | |||
| Tensor *tensor = item.second; | |||
| if (tensor->category() == Tensor::Category::CONST_TENSOR) { | |||
| if (tensor->data_c() == nullptr) { | |||
| continue; | |||
| } | |||
| PrintTensor(tensor, cfile, hfile, name); | |||
| } | |||
| } | |||
| } | |||
| int PrintMicroTensors(std::ofstream &ofs, std::vector<Tensor *> tensors, const std::string &name, | |||
| const std::map<Tensor *, std::string> &tensors_map) { | |||
| for (size_t index = 0; index < tensors.size(); ++index) { | |||
| Tensor *tensor = tensors[index]; | |||
| auto item = tensors_map.find(tensor); | |||
| if (item == tensors_map.end()) { | |||
| MS_LOG(ERROR) << "nonexistent tensor"; | |||
| return RET_ERROR; | |||
| } | |||
| ofs << " static int dim[] = {"; | |||
| for (size_t i = 0; i < tensor->shape().size(); ++i) { | |||
| ofs << tensor->shape()[i] << ", "; | |||
| } | |||
| ofs << "};\n"; | |||
| ofs << " " << name << "[" << index << "].ndim = " << tensor->shape().size() << ";\n"; | |||
| ofs << " " << name << "[" << index << "].dim = dim;\n"; | |||
| ofs << " " << name << "[" << index << "].type = " << GetMicroTensorDataType(tensor->data_type()) << ";\n"; | |||
| ofs << " " << name << "[" << index << "].format = " << std::to_string(tensor->format()) << ";\n"; | |||
| ofs << " " << name << "[" << index << "].data =" << item->second << ";\n"; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| void IncludeCmsisDirectories(std::ofstream &ofs) { | |||
| ofs << "include_directories(${OP_HEADER_PATH}/cmsis)\n"; | |||
| ofs << "include_directories(${OP_HEADER_PATH}/cmsis/CMSIS/NN/Include)\n"; | |||
| ofs << "include_directories(${OP_HEADER_PATH}/cmsis/CMSIS/DSP/Include)\n"; | |||
| ofs << "include_directories(${OP_HEADER_PATH}/cmsis/CMSIS/Core/Include)\n"; | |||
| } | |||
| } // namespace mindspore::lite::micro | |||
| @@ -1,47 +0,0 @@ | |||
| /** | |||
| * Copyright 2021 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_MICRO_CODER_GENERATOR_GENERATOR_UTILS_H_ | |||
| #define MINDSPORE_MICRO_CODER_GENERATOR_GENERATOR_UTILS_H_ | |||
| #include <map> | |||
| #include <string> | |||
| #include <vector> | |||
| #include "src/tensor.h" | |||
| namespace mindspore::lite::micro { | |||
| int WriteContentToFile(const std::string &file, const std::string &content); | |||
| void CodeReadModelParams(const std::map<std::string, Tensor *> &saved_weights, | |||
| const std::map<Tensor *, std::string> &tensors_map, std::ofstream &ofs); | |||
| int SaveDataToNet(const std::map<std::string, Tensor *> &tensors_map, const std::string &net_file); | |||
| void CodeModelParamsDefine(const std::map<std::string, Tensor *> &address_map, std::ofstream &hfile, | |||
| std::ofstream &cfile); | |||
| void CodeModelParamsDefineAndData(const std::map<std::string, Tensor *> &address_map, std::ofstream &hfile, | |||
| std::ofstream &cfile); | |||
| int PrintMicroTensors(std::ofstream &ofs, std::vector<Tensor *> tensors, const std::string &name, | |||
| const std::map<Tensor *, std::string> &tensors_map); | |||
| void IncludeCmsisDirectories(std::ofstream &ofs); | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MINDSPORE_MICRO_CODER_GENERATOR_GENERATOR_UTILS_H_ | |||
| @@ -14,7 +14,7 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/coder_graph.h" | |||
| #include "micro/coder/graph.h" | |||
| #include <queue> | |||
| #include <deque> | |||
| #include <string> | |||
| @@ -14,8 +14,8 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_CODER_GRAPH_NODE_H_ | |||
| #define MICRO_CODER_GRAPH_NODE_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_GRAPH_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_GRAPH_H_ | |||
| #include <map> | |||
| #include <memory> | |||
| @@ -28,6 +28,7 @@ | |||
| #include "schema/inner/model_generated.h" | |||
| #include "src/common/graph_util.h" | |||
| #include "src/tensor.h" | |||
| namespace mindspore::lite::micro { | |||
| class CoderGraph { | |||
| public: | |||
| @@ -80,4 +81,4 @@ class CoderGraph { | |||
| Model *model_{nullptr}; | |||
| }; | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MICRO_CODER_GRAPH_NODE_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_GRAPH_H_ | |||
| @@ -14,8 +14,8 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_LOG_H_ | |||
| #define MICRO_LOG_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_LOG_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_LOG_H_ | |||
| #include "src/common/log_adapter.h" | |||
| #include "include/errorcode.h" | |||
| @@ -86,6 +86,23 @@ | |||
| } \ | |||
| } while (0) | |||
| #define MS_CHECK_TRUE_WITH_EXE(code, msg, FUNC) \ | |||
| do { \ | |||
| if (!(code)) { \ | |||
| MS_LOG(ERROR) << msg; \ | |||
| FUNC; \ | |||
| return mindspore::lite::RET_ERROR; \ | |||
| } \ | |||
| } while (0) | |||
| #define MS_CHECK_TRUE_WITHOUT_RET(code, msg) \ | |||
| do { \ | |||
| if (!(code)) { \ | |||
| MS_LOG(ERROR) << msg; \ | |||
| return; \ | |||
| } \ | |||
| } while (0) | |||
| #define MS_CHECK_TRUE_RET_NULL(code, msg) \ | |||
| do { \ | |||
| if (!(code)) { \ | |||
| @@ -102,4 +119,4 @@ | |||
| } \ | |||
| } while (0) | |||
| #endif // MICRO_LOG_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_LOG_H_ | |||
| @@ -14,14 +14,14 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/add_int8_coder.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/add_int8_coder.h" | |||
| #include <algorithm> | |||
| #include <limits> | |||
| #include "micro/coder/opcoders/serializers/serializer.h" | |||
| #include "nnacl/arithmetic.h" | |||
| #include "nnacl/int8/quantize.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "micro/coder/log.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| #include "coder/log.h" | |||
| using mindspore::schema::PrimitiveType_Add; | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_CMSIS_NN_ADD_INT8_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::cmsis { | |||
| @@ -14,7 +14,7 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/conv2d_base_coder.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/conv2d_base_coder.h" | |||
| #include "nnacl/int8/quantize.h" | |||
| namespace mindspore::lite::micro::cmsis { | |||
| @@ -19,7 +19,7 @@ | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/base/conv2d_base_coder.h" | |||
| #include "coder/opcoders/base/conv2d_base_coder.h" | |||
| #include "nnacl/conv_parameter.h" | |||
| namespace mindspore::lite::micro::cmsis { | |||
| @@ -14,13 +14,13 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/conv2d_int8_coder.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/conv2d_int8_coder.h" | |||
| #include <memory> | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/dwconv_int8_coder.h" | |||
| #include "micro/coder/opcoders/serializers/serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/dwconv_int8_coder.h" | |||
| #include "coder/opcoders/serializers/serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Conv2D; | |||
| @@ -19,7 +19,7 @@ | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/conv2d_base_coder.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/conv2d_base_coder.h" | |||
| #include "nnacl/conv_parameter.h" | |||
| namespace mindspore::lite::micro::cmsis { | |||
| @@ -14,11 +14,11 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/dwconv_int8_coder.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/dwconv_int8_coder.h" | |||
| #include <string> | |||
| #include "micro/coder/opcoders/serializers/serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "micro/coder/log.h" | |||
| #include "coder/opcoders/serializers/serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| #include "coder/log.h" | |||
| using mindspore::schema::PrimitiveType_DepthwiseConv2D; | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_CMSIS_NN_DWCONV_INT8_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/conv2d_base_coder.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/conv2d_base_coder.h" | |||
| #include "src/runtime/kernel/arm/int8/convolution_depthwise_int8.h" | |||
| namespace mindspore::lite::micro::cmsis { | |||
| @@ -14,9 +14,9 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/fullconnection_int8_coder.h" | |||
| #include "micro/coder/opcoders/serializers/serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/fullconnection_int8_coder.h" | |||
| #include "coder/opcoders/serializers/serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_FullConnection; | |||
| @@ -14,11 +14,11 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/mul_int8_coder.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/mul_int8_coder.h" | |||
| #include <string> | |||
| #include "micro/coder/opcoders/serializers/serializer.h" | |||
| #include "coder/opcoders/serializers/serializer.h" | |||
| #include "nnacl/int8/quantize.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Mul; | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_CMSIS_NN_MUL_INT8_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::cmsis { | |||
| class MulInt8Coder final : public OperatorCoder { | |||
| @@ -16,9 +16,9 @@ | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/pooling_int8_coder.h" | |||
| #include "micro/coder/opcoders/serializers/serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/pooling_int8_coder.h" | |||
| #include "coder/opcoders/serializers/serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Pooling; | |||
| @@ -20,7 +20,7 @@ | |||
| #include <string> | |||
| #include <memory> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/int8/pooling_int8.h" | |||
| namespace mindspore::lite::micro::cmsis { | |||
| @@ -14,10 +14,10 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/reshape_int8_coder.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/reshape_int8_coder.h" | |||
| #include <vector> | |||
| #include <string> | |||
| #include "micro/coder/opcoders/serializers/serializer.h" | |||
| #include "coder/opcoders/serializers/serializer.h" | |||
| using mindspore::schema::PrimitiveType_Reshape; | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_CMSIS_NN_RESHAPE_INT8_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::cmsis { | |||
| class ReshapeInt8Coder final : public OperatorCoder { | |||
| @@ -14,10 +14,10 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/cmsis-nn/int8/softmax_int8_coder.h" | |||
| #include "coder/opcoders/cmsis-nn/int8/softmax_int8_coder.h" | |||
| #include <limits> | |||
| #include "micro/coder/opcoders/serializers/serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_SoftMax; | |||
| namespace mindspore::lite::micro::cmsis { | |||
| @@ -20,7 +20,7 @@ | |||
| #include <string> | |||
| #include <memory> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/base/softmax_base_coder.h" | |||
| #include "coder/opcoders/base/softmax_base_coder.h" | |||
| namespace mindspore::lite::micro::cmsis { | |||
| @@ -19,7 +19,7 @@ | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/coder_context.h" | |||
| #include "coder/context.h" | |||
| namespace mindspore::lite::micro { | |||
| void Collect(CoderContext *const ctx, const std::vector<std::string> &headers, | |||
| @@ -14,11 +14,11 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_CODER_OPCODERS_FP32_ACTIVATIONFP32_CODER_H_ | |||
| #define MICRO_CODER_OPCODERS_FP32_ACTIVATIONFP32_CODER_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_ACTIVATIONFP32_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_ACTIVATIONFP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -17,7 +17,7 @@ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_ADDN_FP32_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_ADDN_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| class AddNFP32Coder final : public OperatorCoder { | |||
| @@ -13,13 +13,13 @@ | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/arithmetic_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/arithmetic_fp32_coder.h" | |||
| #include <string> | |||
| #include <map> | |||
| #include <type_traits> | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| #include "nnacl/fp32/arithmetic_fp32.h" | |||
| #include "micro/coder/log.h" | |||
| #include "coder/log.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -14,14 +14,14 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_CODER_OPCODERS_FP32_ARITHMETIC_FP32_CODER_H_ | |||
| #define MICRO_CODER_OPCODERS_FP32_ARITHMETIC_FP32_CODER_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_ARITHMETIC_FP32_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_ARITHMETIC_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include <string> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/fp32/arithmetic_fp32.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #define DEFAULT_ARITHMETIC_NDIMS 10 | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -106,4 +106,4 @@ class ArithmeticFP32Coder final : public OperatorCoder { | |||
| LiteDataType data_type_{kDataTypeFloat}; | |||
| }; | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| #endif // MICRO_CODER_OPCODERS_FP32_ARITHMETIC_FP32_CODER_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_ARITHMETIC_FP32_CODER_H_ | |||
| @@ -14,12 +14,12 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/arithmetic_self_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/arithmetic_self_fp32_coder.h" | |||
| #include <string> | |||
| #include <map> | |||
| #include "nnacl/fp32/arithmetic_fp32.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -14,12 +14,12 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_CODER_OPCODERS_FP32_ARITHMETIC_SELF_FP32_CODER_H_ | |||
| #define MICRO_CODER_OPCODERS_FP32_ARITHMETIC_SELF_FP32_CODER_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_ARITHMETIC_SELF_FP32_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_ARITHMETIC_SELF_FP32_CODER_H_ | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/fp32/arithmetic_self_fp32.h" | |||
| #include "nnacl/arithmetic_self_parameter.h" | |||
| @@ -106,4 +106,4 @@ class ArithmeticSelfFP32Coder final : public OperatorCoder { | |||
| std::string arithmetic_self_run_; | |||
| }; | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| #endif // MICRO_CODER_OPCODERS_FP32_ARITHMETIC_SELF_FP32_CODER_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_ARITHMETIC_SELF_FP32_CODER_H_ | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_ASSIGN_ADD_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/base/tile_base.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -13,14 +13,14 @@ | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/batchnorm_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/batchnorm_fp32_coder.h" | |||
| #include <string> | |||
| #include <vector> | |||
| #include "nnacl/fp32/batchnorm_fp32.h" | |||
| #include "src/ops/batch_norm.h" | |||
| #include "nnacl/op_base.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| using mindspore::schema::PrimitiveType_BatchNorm; | |||
| @@ -14,11 +14,11 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_CODER_OPCODERS_FP32_BATCHNORM_FP32_CODER_H_ | |||
| #define MICRO_CODER_OPCODERS_FP32_BATCHNORM_FP32_CODER_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_BATCHNORM_FP32_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_BATCHNORM_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -40,4 +40,4 @@ class BatchnormFP32Coder final : public OperatorCoder { | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| #endif // MICRO_CODER_OPCODERS_FP32_CODER_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_CODER_H_ | |||
| @@ -13,11 +13,11 @@ | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/concat_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/concat_fp32_coder.h" | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Concat; | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_CONCAT_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/concat_parameter.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -0,0 +1,78 @@ | |||
| /** | |||
| * 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 "micro/coder/opcoders/nnacl/fp32/convolution_depthwise_fp32_coder.h" | |||
| #include <string> | |||
| #include "micro/coder/log.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| using mindspore::schema::PrimitiveType_DepthwiseConv2D; | |||
| namespace mindspore::lite::micro::nnacl { | |||
| int ConvolutionDepthwiseFP32Coder::Prepare(CoderContext *const context) { | |||
| Conv2DBaseCoder::Init(); | |||
| MS_CHECK_RET_CODE(InitWeightBias(), "dwconvolution do init weightbais failed"); | |||
| conv_param_->thread_num_ = MSMIN(thread_num_, conv_param_->output_h_); | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionDepthwiseFP32Coder::InitWeightBias() { | |||
| // init weight: o, h, w, i; o == group, i == 1 | |||
| auto *origin_weight = reinterpret_cast<float *>(filter_tensor_->data_c()); | |||
| int channel = filter_tensor_->Batch(); | |||
| size_t pack_weight_size = filter_tensor_->Batch() * filter_tensor_->Height() * filter_tensor_->Width(); | |||
| size_t packed_weight_data_size = pack_weight_size * sizeof(float); | |||
| packed_weight_ = | |||
| reinterpret_cast<float *>(allocator_->Malloc(kNumberTypeFloat32, packed_weight_data_size, kOfflinePackWeight)); | |||
| MS_CHECK_PTR(packed_weight_); | |||
| MS_CHECK_RET_CODE(memset_s(packed_weight_, packed_weight_data_size, 0, packed_weight_data_size), | |||
| "memset packed weight failed!"); | |||
| PackNCHWToNHWCFp32(origin_weight, packed_weight_, 1, filter_tensor_->Height() * filter_tensor_->Width(), channel); | |||
| auto channel_size = static_cast<size_t>(channel); | |||
| auto bias_size = static_cast<size_t>(channel_size * sizeof(float)); | |||
| bias_ = reinterpret_cast<float *>(allocator_->Malloc(kNumberTypeFloat32, bias_size, kOfflinePackWeight)); | |||
| MS_CHECK_PTR(bias_); | |||
| MS_CHECK_RET_CODE(memset_s(bias_, bias_size, 0, bias_size), "memset bias failed!"); | |||
| // init bias | |||
| if (input_tensors_.size() == kInputSize2) { | |||
| auto *ori_bias = reinterpret_cast<float *>(bias_tensor_->data_c()); | |||
| MS_CHECK_TRUE(bias_tensor_->ElementsNum() > 0, "invalid bias length"); | |||
| MS_CHECK_RET_CODE(memcpy_s(bias_, static_cast<size_t>(bias_tensor_->ElementsNum() * sizeof(float)), ori_bias, | |||
| static_cast<size_t>(bias_tensor_->ElementsNum() * sizeof(float))), | |||
| "memcpy_s bias failed!"); | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionDepthwiseFP32Coder::DoCode(CoderContext *const context) { | |||
| MS_CHECK_TRUE(conv_param_->input_channel_ == conv_param_->output_channel_, | |||
| "Only support input channel equals output channel."); | |||
| // generate code .h .c | |||
| Collect(context, {"nnacl/fp32/conv_depthwise.h"}, {"conv_depthwise.c"}); | |||
| nnacl::NNaclFp32Serializer code; | |||
| // call the op function | |||
| code.CodeStruct("conv_parameter", *conv_param_); | |||
| int task_id = 0; | |||
| code.CodeFunction("ConvDw", output_tensor_, input_tensor_, packed_weight_, bias_, "&conv_parameter", task_id); | |||
| context->AppendCode(code.str()); | |||
| return RET_OK; | |||
| } | |||
| REG_OPERATOR_CODER(kAllTargets, kNumberTypeFloat32, PrimitiveType_DepthwiseConv2D, | |||
| CPUOpCoderCreator<ConvolutionDepthwiseFP32Coder>) | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| @@ -0,0 +1,42 @@ | |||
| /** | |||
| * 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_MICRO_CODER_OPCODERS_FP32_CONVOLUTION_DEPTHWISE_FP32_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_CONVOLUTION_DEPTHWISE_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/base/conv2d_base_coder.h" | |||
| #include "src/runtime/kernel/arm/fp32/convolution_depthwise_fp32.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| class ConvolutionDepthwiseFP32Coder final : public Conv2DBaseCoder { | |||
| public: | |||
| ConvolutionDepthwiseFP32Coder(const std::vector<Tensor *> &in_tensors, const std::vector<Tensor *> &out_tensors, | |||
| const Model::Node *node, size_t node_index, Target target) | |||
| : Conv2DBaseCoder(in_tensors, out_tensors, node, node_index, target) {} | |||
| ~ConvolutionDepthwiseFP32Coder() override = default; | |||
| int Prepare(CoderContext *const context) override; | |||
| int DoCode(CoderContext *const context) override; | |||
| private: | |||
| int InitWeightBias(); | |||
| float *packed_weight_{nullptr}; | |||
| float *bias_{nullptr}; | |||
| }; | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_CONVOLUTION_DEPTHWISE_FP32_CODER_H_ | |||
| @@ -0,0 +1,179 @@ | |||
| /** | |||
| * Copyright 2021 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 "micro/coder/opcoders/nnacl/fp32/convolution_fp32_coder.h" | |||
| #include <memory> | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/nnacl/fp32/convolution_winograd_fp32_coder.h" | |||
| #include "nnacl/fp32/winograd_utils.h" | |||
| #include "src/ops/populate/populate_register.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "micro/coder/log.h" | |||
| using mindspore::schema::PrimitiveType_Conv2D; | |||
| namespace mindspore::lite::micro::nnacl { | |||
| int ConvolutionFP32Coder::InitTmpBuffer() { | |||
| int in_channel = conv_param_->input_channel_; | |||
| int uint_size; | |||
| if (target_ == kARM32A) { | |||
| uint_size = conv_param_->kernel_h_ * conv_param_->kernel_w_ * in_channel * C4NUM * thread_num_; | |||
| } else { | |||
| uint_size = conv_param_->kernel_h_ * conv_param_->kernel_w_ * in_channel * C12NUM * thread_num_; | |||
| } | |||
| packed_input_size_ = uint_size * sizeof(float); | |||
| packed_input_ = reinterpret_cast<float *>(allocator_->Malloc(kNumberTypeFloat32, packed_input_size_, kWorkspace)); | |||
| col_major_input_size_ = uint_size * sizeof(float); | |||
| col_major_input_ = | |||
| reinterpret_cast<float *>(allocator_->Malloc(kNumberTypeFloat32, col_major_input_size_, kWorkspace)); | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionFP32Coder::Prepare(CoderContext *const context) { | |||
| int ret = Conv2DBaseCoder::Init(); | |||
| MS_CHECK_RET_CODE(ret, "Conv2DBaseCoder::Init() failed."); | |||
| ret = InitWeightBias(context); | |||
| MS_CHECK_RET_CODE(ret, "Init weight bias failed."); | |||
| return Resize(); | |||
| } | |||
| int ConvolutionFP32Coder::Resize() { | |||
| int ret = Conv2DBaseCoder::CheckResizeValid(); | |||
| MS_CHECK_RET_CODE(ret, "Resize is invalid."); | |||
| ret = Conv2DBaseCoder::Init(); | |||
| MS_CHECK_RET_CODE(ret, "init failed."); | |||
| ret = InitTmpBuffer(); | |||
| MS_CHECK_RET_CODE(ret, "init tmp buffer failed."); | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionFP32Coder::InitWeightBias(CoderContext *const context) { | |||
| int kernel_h = filter_tensor_->Height(); | |||
| int kernel_w = filter_tensor_->Width(); | |||
| int in_channel = filter_tensor_->Channel(); | |||
| int out_channel = filter_tensor_->Batch(); | |||
| conv_param_->input_channel_ = in_channel; | |||
| conv_param_->output_channel_ = out_channel; | |||
| int kernel_plane = kernel_h * kernel_w; | |||
| const int oc_block = C8NUM; | |||
| int oc_block_num = UP_DIV(out_channel, C8NUM); | |||
| int pack_weight_size = oc_block_num * oc_block * in_channel * kernel_plane; | |||
| auto origin_weight = reinterpret_cast<float *>(filter_tensor_->MutableData()); | |||
| MS_CHECK_PTR(origin_weight); | |||
| packed_weight_ = reinterpret_cast<float *>( | |||
| allocator_->Malloc(kNumberTypeFloat32, pack_weight_size * sizeof(float), kOnlinePackWeight)); | |||
| MS_CHECK_PTR(packed_weight_); | |||
| auto out_channel_size = static_cast<size_t>(out_channel); | |||
| NNaclFp32Serializer code; | |||
| code.CodeMallocExpression(packed_weight_, pack_weight_size * sizeof(float)); | |||
| code.CodeFunction("memset", packed_weight_, 0, pack_weight_size * sizeof(float)); | |||
| code.CodeFunction("RowMajor2Col8Major", filter_tensor_, packed_weight_, out_channel_size, in_channel * kernel_plane); | |||
| auto bias_data_size = static_cast<size_t>(oc_block_num * oc_block * sizeof(float)); | |||
| bias_data_ = reinterpret_cast<float *>(allocator_->Malloc(kNumberTypeFloat32, bias_data_size, kOnlinePackWeight)); | |||
| MS_CHECK_PTR(bias_data_); | |||
| if (input_tensors_.size() == kInputSize2) { | |||
| code.CodeMallocExpression(bias_data_, bias_data_size); | |||
| code.CodeFunction("memset", bias_data_, 0, bias_data_size); | |||
| code.CodeFunction("memcpy", bias_data_, bias_tensor_, out_channel_size * sizeof(float)); | |||
| } else { | |||
| return RET_ERROR; | |||
| } | |||
| context->AppendInitCode(code.str()); | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionFP32Coder::DoCode(CoderContext *const context) { | |||
| { | |||
| std::vector<string> asmFiles; | |||
| if (target_ == kARM32A) { | |||
| asmFiles = {"MatmulFp32.S", | |||
| "MatmulFp32Opt.S", | |||
| "PreSum4x16Int8Peroc.S", | |||
| "PreSum4x16Int8Pert.S", | |||
| "IndirectGemmInt16to32_8x4.S", | |||
| "MatmulInt8.S"}; | |||
| } else if (target_ == kARM64) { | |||
| asmFiles = {"MatmulFp32.S", "MatmulFp32Opt.S", "PreSum4x16Int8Peroc.S", "MatVecMulFp32.S", | |||
| "PreSum4x16Int8Peroc.S", "PreSum4x16Int8Pert.S", "IndirectGemmInt16to32_8x4.S", "MatmulInt8.S"}; | |||
| } | |||
| Collect(context, | |||
| {"nnacl/kernel/fp32/conv_fp32_slim.h", "nnacl/fp32/matmul.h", "nnacl/conv_parameter.h", "nnacl/op_base.h"}, | |||
| {"common_func.c", "conv_fp32_slim.c", "matmul.c"}, asmFiles); | |||
| } | |||
| NNaclFp32Serializer code; | |||
| // call the op function | |||
| code.CodeFunction("memset", packed_input_, "0", packed_input_size_); | |||
| code.CodeFunction("memset", col_major_input_, "0", col_major_input_size_); | |||
| code.CodeStruct("conv_parameter", *conv_param_); | |||
| int task_id = 0; | |||
| code.CodeFunction("ConvFp32Slim", input_tensor_, packed_input_, packed_weight_, bias_data_, col_major_input_, | |||
| output_tensor_, task_id, "(ConvParameter *)&conv_parameter"); | |||
| context->AppendCode(code.str()); | |||
| return RET_OK; | |||
| } | |||
| std::unique_ptr<OperatorCoder> CPUConvolutionFP32CoderCreator(const std::vector<Tensor *> &in_tensors, | |||
| const std::vector<Tensor *> &out_tensors, | |||
| const Model::Node *node, size_t node_index, | |||
| Target target) { | |||
| std::vector<Tensor *> inputs = in_tensors; | |||
| std::vector<Tensor *> outputs = out_tensors; | |||
| auto primitive = node->primitive_; | |||
| if (!primitive) { | |||
| return nullptr; | |||
| } | |||
| OpParameter *parameter = | |||
| PopulateRegistry::GetInstance()->GetParameterCreator((schema::PrimitiveType(primitive->Type())))(primitive); | |||
| if (parameter == nullptr) { | |||
| MS_LOG(ERROR) << "PopulateParameter return nullptr, type: " | |||
| << schema::EnumNamePrimitiveType((schema::PrimitiveType)(primitive->Type())); | |||
| return nullptr; | |||
| } | |||
| auto conv_param = reinterpret_cast<ConvParameter *>(parameter); | |||
| bool use_winograd = false; | |||
| int out_unit = 0; | |||
| int kernel_h = conv_param->kernel_h_; | |||
| int kernel_w = conv_param->kernel_w_; | |||
| conv_param->input_h_ = inputs.at(kInputIndex)->Height(); | |||
| conv_param->input_w_ = inputs.at(kInputIndex)->Width(); | |||
| conv_param->input_channel_ = inputs.at(kInputIndex)->Channel(); | |||
| conv_param->output_h_ = outputs.at(kOutputIndex)->Height(); | |||
| conv_param->output_w_ = outputs.at(kOutputIndex)->Width(); | |||
| conv_param->output_channel_ = outputs.at(kOutputIndex)->Channel(); | |||
| conv_param->op_parameter_.thread_num_ = 1; | |||
| CheckIfUseWinograd(&use_winograd, &out_unit, conv_param); | |||
| free(parameter); | |||
| // weight de quant | |||
| std::unique_ptr<OperatorCoder> coder; | |||
| if (kernel_h == 1 && kernel_w == 1) { | |||
| MS_LOG(DEBUG) << "create ConvolutionFP32Coder"; | |||
| coder = CPUOpCoderCreator<ConvolutionFP32Coder>(in_tensors, out_tensors, node, node_index, target); | |||
| } else if (use_winograd) { | |||
| MS_LOG(DEBUG) << "create Conv2DWinogradFP32Coder"; | |||
| coder = std::make_unique<ConvolutionWinogradFP32Coder>(in_tensors, out_tensors, node, node_index, target, out_unit); | |||
| } else { | |||
| MS_LOG(DEBUG) << "create ConvolutionFP32Coder"; | |||
| coder = CPUOpCoderCreator<ConvolutionFP32Coder>(in_tensors, out_tensors, node, node_index, target); | |||
| } | |||
| return coder; | |||
| } | |||
| REG_OPERATOR_CODER(kAllTargets, kNumberTypeFloat32, PrimitiveType_Conv2D, CPUConvolutionFP32CoderCreator) | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| @@ -0,0 +1,62 @@ | |||
| /** | |||
| * Copyright 2021 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_MICRO_CODER_OPCODERS_FP32_CONVOLUTION_FP32_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_CONVOLUTION_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include <string> | |||
| #include "nnacl/conv_parameter.h" | |||
| #include "micro/coder/opcoders/base/conv2d_base_coder.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| class ConvolutionFP32Coder final : public Conv2DBaseCoder { | |||
| public: | |||
| ConvolutionFP32Coder(const std::vector<Tensor *> &in_tensors, const std::vector<Tensor *> &out_tensors, | |||
| const Model::Node *node, size_t node_index, Target target) | |||
| : Conv2DBaseCoder(in_tensors, out_tensors, node, node_index, target) {} | |||
| int Prepare(CoderContext *const context) override; | |||
| int DoCode(CoderContext *const context) override; | |||
| ~ConvolutionFP32Coder() override = default; | |||
| private: | |||
| int InitWeightBias(CoderContext *const context); | |||
| int InitTmpBuffer(); | |||
| int Resize(); | |||
| float *packed_weight_{nullptr}; | |||
| float *bias_data_{nullptr}; | |||
| float *packed_input_{nullptr}; | |||
| size_t packed_input_size_{0}; | |||
| int thread_stride_{0}; | |||
| int thread_count_{0}; | |||
| float *col_major_input_{nullptr}; | |||
| size_t col_major_input_size_{0}; | |||
| }; | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_CONVOLUTION_FP32_CODER_H_ | |||
| @@ -0,0 +1,247 @@ | |||
| /** | |||
| * Copyright 2021 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 "micro/coder/opcoders/nnacl/fp32/convolution_winograd_fp32_coder.h" | |||
| #include <array> | |||
| #include "nnacl/base/minimal_filtering_generator.h" | |||
| #include "micro/coder/log.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| const std::array<std::string, 9> InputTransFuncList = { | |||
| "", "", "", "", "InputTransform4x4Unit", "", "InputTransform6x6Unit", "", "InputTransform8x8Unit"}; | |||
| const std::array<std::string, 4> OutputTransFuncList4 = {"", "", "OutputTransform4x2Unit", "OutputTransform4x3Unit"}; | |||
| const std::array<std::string, 4> OutputTransFuncReluList4 = {"", "", "OutputTransform4x2ReluUnit", | |||
| "OutputTransform4x3ReluUnit"}; | |||
| const std::array<std::string, 4> OutputTransFuncRelu6List4 = {"", "", "OutputTransform4x2Relu6Unit", | |||
| "OutputTransform4x3Relu6Unit"}; | |||
| const std::array<std::string, 6> OutputTransFuncList6 = { | |||
| "", "", "OutputTransform6x2Unit", "OutputTransform6x3Unit", "OutputTransform6x4Unit", "OutputTransform6x5Unit"}; | |||
| const std::array<std::string, 8> OutputTransFuncReluList6 = {"", | |||
| "", | |||
| "OutputTransform6x2ReluUnit", | |||
| "OutputTransform6x3ReluUnit", | |||
| "OutputTransform6x4ReluUnit", | |||
| "OutputTransform6x5ReluUnit"}; | |||
| const std::array<std::string, 8> OutputTransFuncRelu6List6 = {"", | |||
| "", | |||
| "OutputTransform6x2Relu6Unit", | |||
| "OutputTransform6x3Relu6Unit", | |||
| "OutputTransform6x4Relu6Unit", | |||
| "OutputTransform6x5Relu6Unit"}; | |||
| const std::array<std::string, 8> OutputTransFuncList8 = {"", | |||
| "", | |||
| "OutputTransform8x2Unit", | |||
| "OutputTransform8x3Unit", | |||
| "OutputTransform8x4Unit", | |||
| "OutputTransform8x5Unit", | |||
| "OutputTransform8x6Unit", | |||
| "OutputTransform8x7Unit"}; | |||
| const std::array<std::string, 8> OutputTransFuncReluList8 = {"", | |||
| "", | |||
| "OutputTransform8x2ReluUnit", | |||
| "OutputTransform8x3ReluUnit", | |||
| "OutputTransform8x4ReluUnit", | |||
| "OutputTransform8x5ReluUnit", | |||
| "OutputTransform8x6ReluUnit", | |||
| "OutputTransform8x7ReluUnit"}; | |||
| const std::array<std::string, 8> OutputTransFuncRelu6List8 = {"", | |||
| "", | |||
| "OutputTransform8x2Relu6Unit", | |||
| "OutputTransform8x3Relu6Unit", | |||
| "OutputTransform8x4Relu6Unit", | |||
| "OutputTransform8x5Relu6Unit", | |||
| "OutputTransform8x6Relu6Unit", | |||
| "OutputTransform8x7Relu6Unit"}; | |||
| int ConvolutionWinogradFP32Coder::WinogradFilterTransform(const float *weight_data, float *matrix_g, | |||
| const float *matrix_gt, int oc_block) { | |||
| MS_CHECK_TRUE(oc_block, "Divide by zero!"); | |||
| return WinogradWeightTransform(weight_data, trans_weight_, matrix_g, matrix_gt, oc_block, input_unit_, kernel_unit_, | |||
| conv_param_->input_channel_, conv_param_->output_channel_, true); | |||
| } | |||
| int ConvolutionWinogradFP32Coder::InitTmpBuffer() { | |||
| int channel_out = conv_param_->output_channel_; | |||
| int oc8 = UP_DIV(channel_out, C8NUM); | |||
| int tile_num = C12NUM; | |||
| tile_buffer_size_ = thread_num_ * tile_num * input_unit_ * input_unit_ * conv_param_->input_channel_ * sizeof(float); | |||
| trans_input_ = reinterpret_cast<float *>(allocator_->Malloc(kNumberTypeFloat32, tile_buffer_size_, kWorkspace)); | |||
| gemm_out_size_ = thread_num_ * tile_num * input_unit_ * input_unit_ * oc8 * C8NUM * sizeof(float); | |||
| gemm_out_ = reinterpret_cast<float *>(allocator_->Malloc(kNumberTypeFloat32, gemm_out_size_, kWorkspace)); | |||
| tmp_data_size_ = thread_num_ * C4NUM * input_unit_ * input_unit_ * sizeof(float); | |||
| tmp_data_ = reinterpret_cast<float *>(allocator_->Malloc(kNumberTypeFloat32, tmp_data_size_, kWorkspace)); | |||
| col_buffer_size_ = thread_num_ * tile_num * conv_param_->input_channel_ * sizeof(float); | |||
| col_buffer_ = reinterpret_cast<float *>(allocator_->Malloc(kNumberTypeFloat32, col_buffer_size_, kWorkspace)); | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionWinogradFP32Coder::ReSize() { | |||
| // malloc tmp buffer | |||
| int ret = ConfigInputOutput(); | |||
| MS_CHECK_RET_CODE(ret, "ConfigInputOutput failed."); | |||
| ret = InitTmpBuffer(); | |||
| MS_CHECK_RET_CODE(ret, "Init tmp buffer failed."); | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionWinogradFP32Coder::Prepare(CoderContext *const context) { | |||
| int ret = Conv2DBaseCoder::Init(); | |||
| MS_CHECK_RET_CODE(ret, "convolution base coder init failed."); | |||
| kernel_unit_ = conv_param_->kernel_h_; | |||
| input_unit_ = output_unit_ + kernel_unit_ - 1; | |||
| conv_param_->input_unit_ = input_unit_; | |||
| conv_param_->output_unit_ = output_unit_; | |||
| ret = InitWeightBias(); | |||
| MS_CHECK_RET_CODE(ret, "Init weight bias failed."); | |||
| return ReSize(); | |||
| } // namespace micro | |||
| int ConvolutionWinogradFP32Coder::InitWeightBias() { | |||
| int in_channel = filter_tensor_->Channel(); | |||
| int out_channel = filter_tensor_->Batch(); | |||
| MS_CHECK_TRUE(in_channel > 0, "invalid in channel size"); | |||
| MS_CHECK_TRUE(out_channel > 0, "invalid out channel size"); | |||
| conv_param_->input_channel_ = in_channel; | |||
| conv_param_->output_channel_ = out_channel; | |||
| int oc4 = UP_DIV(out_channel, C4NUM); | |||
| const int oc_block = C8NUM; | |||
| int oc_block_num = UP_DIV(out_channel, C8NUM); | |||
| // init weight | |||
| int trans_matrix_data_size = input_unit_ * input_unit_ * in_channel * oc_block_num * oc_block; | |||
| trans_weight_ = reinterpret_cast<float *>( | |||
| allocator_->Malloc(kNumberTypeFloat32, trans_matrix_data_size * sizeof(float), kOfflinePackWeight)); | |||
| MS_CHECK_PTR(trans_weight_); | |||
| int ret = memset_s(trans_weight_, trans_matrix_data_size * sizeof(float), 0, trans_matrix_data_size * sizeof(float)); | |||
| MS_CHECK_RET_CODE(ret, "memset_s failed!"); | |||
| float matrix_g[64]; | |||
| float matrix_gt[64]; | |||
| float matrix_a[64]; | |||
| float matrix_at[64]; | |||
| float matrix_b[64]; | |||
| float matrix_bt[64]; | |||
| float coef = 1.0f; | |||
| if (input_unit_ == 8) { | |||
| coef = 0.5f; | |||
| } | |||
| CookToomFilter(matrix_a, matrix_at, matrix_b, matrix_bt, matrix_g, matrix_gt, coef, output_unit_, kernel_unit_); | |||
| auto out_channel_size = static_cast<size_t>(out_channel); | |||
| auto weight_data = reinterpret_cast<float *>(filter_tensor_->MutableData()); | |||
| ret = WinogradFilterTransform(weight_data, matrix_g, matrix_gt, oc_block); | |||
| MS_CHECK_RET_CODE(ret, "winograd filter transform failed!"); | |||
| // init bias | |||
| int new_bias_ele_num = oc4 * C4NUM; | |||
| auto new_bias_ele_size = static_cast<size_t>(new_bias_ele_num * sizeof(float)); | |||
| new_bias_ = reinterpret_cast<float *>(allocator_->Malloc(kNumberTypeFloat32, new_bias_ele_size, kOfflinePackWeight)); | |||
| MS_CHECK_PTR(new_bias_); | |||
| ret = memset_s(new_bias_, new_bias_ele_size, 0, new_bias_ele_size); | |||
| MS_CHECK_RET_CODE(ret, "memset_s failed!"); | |||
| if (input_tensors_.size() == kInputSize2) { | |||
| auto ori_bias_addr = reinterpret_cast<float *>(bias_tensor_->data_c()); | |||
| MS_CHECK_RET_CODE(memcpy_s(new_bias_, static_cast<size_t>(out_channel_size * sizeof(float)), ori_bias_addr, | |||
| static_cast<size_t>(out_channel_size * sizeof(float))), | |||
| "memset_s failed!"); | |||
| } else { | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionWinogradFP32Coder::ConfigInputOutput() { | |||
| in_func_ = GetInputTransFunc(input_unit_); | |||
| MS_CHECK_TRUE(!in_func_.empty(), "Get input_trans_func failed."); | |||
| out_func_ = GetOutputTransFunc(input_unit_, output_unit_, conv_param_->act_type_); | |||
| MS_CHECK_TRUE(!out_func_.empty(), "Get output_trans_func_ failed."); | |||
| return RET_OK; | |||
| } | |||
| std::string ConvolutionWinogradFP32Coder::GetInputTransFunc(int input_unit) { | |||
| return InputTransFuncList.at(input_unit); | |||
| } | |||
| std::string ConvolutionWinogradFP32Coder::GetOutputTransFunc(int input_unit, int output_unit, ActType act_type) { | |||
| std::string res; | |||
| if (input_unit == 4 && output_unit < 4) { | |||
| if (act_type == ActType_Relu) { | |||
| return OutputTransFuncReluList4.at(output_unit); | |||
| } else if (act_type == ActType_Relu6) { | |||
| return OutputTransFuncRelu6List4.at(output_unit); | |||
| } else { | |||
| return OutputTransFuncList4.at(output_unit); | |||
| } | |||
| } else if (input_unit == 6 && output_unit < 6) { | |||
| if (act_type == ActType_Relu) { | |||
| return OutputTransFuncReluList6.at(output_unit); | |||
| } else if (act_type == ActType_Relu6) { | |||
| return OutputTransFuncRelu6List6.at(output_unit); | |||
| } else { | |||
| return OutputTransFuncList6.at(output_unit); | |||
| } | |||
| } else if (input_unit == 8 && output_unit < 8) { | |||
| if (act_type == ActType_Relu) { | |||
| return OutputTransFuncReluList8.at(output_unit); | |||
| } else if (act_type == ActType_Relu6) { | |||
| return OutputTransFuncRelu6List8.at(output_unit); | |||
| } else { | |||
| return OutputTransFuncList8.at(output_unit); | |||
| } | |||
| } else { | |||
| return res; | |||
| } | |||
| } | |||
| int ConvolutionWinogradFP32Coder::DoCode(CoderContext *const context) { | |||
| std::vector<std::string> asmFiles; | |||
| if (target_ == kARM32A) { | |||
| asmFiles = { | |||
| "MatmulFp32.S", "MatmulFp32Opt.S", "PreSum4x16Int8Peroc.S", "PreSum4x16Int8Pert.S", "IndirectGemmInt16to32_8x4.S", | |||
| "MatmulInt8.S"}; | |||
| } else if (target_ == kARM64) { | |||
| asmFiles = {"MatmulFp32.S", "MatmulFp32Opt.S", "PreSum4x16Int8Peroc.S", "MatVecMulFp32.S", | |||
| "PreSum4x16Int8Peroc.S", "PreSum4x16Int8Pert.S", "IndirectGemmInt16to32_8x4.S", "MatmulInt8.S"}; | |||
| } | |||
| Collect(context, {"nnacl/fp32/conv.h", "nnacl/common_func.h"}, | |||
| {"common_func.c", "conv_int8.c", "matmul_int8.c", "pack.c", "conv.c", "winograd_transform.c", | |||
| "common_func_fp32.c", "fixed_point.c", "winograd_utils.c", "minimal_filtering_generator.c"}, | |||
| asmFiles); | |||
| NNaclFp32Serializer code; | |||
| // call the op function | |||
| code.CodeFunction("memset", trans_input_, "0", tile_buffer_size_); | |||
| code.CodeFunction("memset", gemm_out_, "0", gemm_out_size_); | |||
| code.CodeFunction("memset", tmp_data_, "0", tmp_data_size_); | |||
| code.CodeFunction("memset", col_buffer_, "0", col_buffer_size_); | |||
| code << "\t\tfloat *tmp_buffer_address_list[4] = {" << allocator_->GetRuntimeAddr(trans_input_) << ", " | |||
| << allocator_->GetRuntimeAddr(gemm_out_) << ", " << allocator_->GetRuntimeAddr(tmp_data_) << ", " | |||
| << allocator_->GetRuntimeAddr(col_buffer_) << "};\n"; | |||
| code.CodeStruct("conv_parameter", *conv_param_); | |||
| // code operator func | |||
| int task_id = 0; | |||
| code.CodeFunction("ConvWinogardFp32", input_tensor_, trans_weight_, new_bias_, output_tensor_, | |||
| "tmp_buffer_address_list", task_id, "&conv_parameter", in_func_, out_func_); | |||
| context->AppendCode(code.str()); | |||
| return RET_OK; | |||
| } | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| @@ -0,0 +1,75 @@ | |||
| /** | |||
| * Copyright 2021 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_MICRO_CODER_OPCODERS_FP32_CONVOLUTION_WINOGRAD_FP32_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_CONVOLUTION_WINOGRAD_FP32_CODER_H_ | |||
| #include <memory> | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/base/conv2d_base_coder.h" | |||
| #include "nnacl/conv_parameter.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| class ConvolutionWinogradFP32Coder : public Conv2DBaseCoder { | |||
| public: | |||
| ConvolutionWinogradFP32Coder(const std::vector<Tensor *> &in_tensors, const std::vector<Tensor *> &out_tensors, | |||
| const Model::Node *node, size_t node_index, Target target, int output_unit) | |||
| : Conv2DBaseCoder(in_tensors, out_tensors, node, node_index, target), output_unit_(output_unit) {} | |||
| int Prepare(CoderContext *const context) override; | |||
| int DoCode(CoderContext *const context) override; | |||
| ~ConvolutionWinogradFP32Coder() override = default; | |||
| private: | |||
| int InitWeightBias(); | |||
| int ConfigInputOutput(); | |||
| int InitTmpBuffer(); | |||
| int ReSize(); | |||
| int WinogradFilterTransform(const float *weight_data, float *matrix_g, const float *matrix_gt, int oc_block); | |||
| std::string GetInputTransFunc(int input_unit); | |||
| std::string GetOutputTransFunc(int input_unit, int output_unit, ActType act_type); | |||
| float *trans_weight_{nullptr}; | |||
| float *new_bias_{nullptr}; | |||
| int kernel_unit_{0}; | |||
| int input_unit_{0}; | |||
| int output_unit_{0}; | |||
| size_t tmp_data_size_{0}; | |||
| size_t tile_buffer_size_{0}; | |||
| size_t gemm_out_size_{0}; | |||
| size_t col_buffer_size_{0}; | |||
| float *tmp_data_{nullptr}; | |||
| float *trans_input_{nullptr}; | |||
| float *gemm_out_{nullptr}; | |||
| float *col_buffer_{nullptr}; | |||
| std::string in_func_; | |||
| std::string out_func_; | |||
| }; | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_CONVOLUTION_WINOGRAD_FP32_CODER_H_ | |||
| @@ -14,10 +14,10 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/expand_dims_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/expand_dims_fp32_coder.h" | |||
| #include <string> | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| using mindspore::schema::PrimitiveType_ExpandDims; | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_EXPANDDIMS_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| class ExpandDimsFP32Coder final : public OperatorCoder { | |||
| @@ -14,12 +14,12 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/gather_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/gather_fp32_coder.h" | |||
| #include <string> | |||
| #include "nnacl/gather_parameter.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/log.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/log.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Gather; | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_GATHER_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/base/tile_base.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -14,11 +14,11 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/nchw2nhwc_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/nchw2nhwc_fp32_coder.h" | |||
| #include <vector> | |||
| #include <string> | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Nchw2Nhwc; | |||
| @@ -19,7 +19,7 @@ | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/base/tile_base.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -14,10 +14,10 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/nhwc2nchw_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/nhwc2nchw_fp32_coder.h" | |||
| #include <string> | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Nhwc2Nchw; | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_NHWC2NCHW_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/base/tile_base.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_PAD_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/fp32/pad_fp32.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -13,13 +13,13 @@ | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/pooling_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/pooling_fp32_coder.h" | |||
| #include <cfloat> | |||
| #include <string> | |||
| #include "nnacl/fp32/pooling_fp32.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/log.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/log.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Pooling; | |||
| @@ -14,8 +14,8 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_CODER_OPCODERS_FP32_POOLFP32_CODER_H_ | |||
| #define MICRO_CODER_OPCODERS_FP32_POOLFP32_CODER_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_OPCODERS_POOLFP32_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_POOLFP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| @@ -36,4 +36,4 @@ class PoolingFP32Coder final : public OperatorCoder { | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| #endif // MICRO_CODER_OPCODERS_FP32__CODER_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_OPCODERS_FP32_CODER_H_ | |||
| @@ -14,11 +14,11 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/power_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/power_fp32_coder.h" | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Power; | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_POWER_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/power_parameter.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -14,11 +14,11 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/reduce_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/reduce_fp32_coder.h" | |||
| #include <string> | |||
| #include "micro/coder/log.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/log.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Reduce; | |||
| @@ -19,8 +19,8 @@ | |||
| #include <string> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/base/reduce_base_coder.h" | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/base/reduce_base_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| class ReduceFP32Coder final : public ReduceBaseCoder { | |||
| @@ -14,10 +14,10 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/reshape_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/reshape_fp32_coder.h" | |||
| #include <string> | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Reshape; | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_RESHAPE_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| class ReshapeFP32Coder final : public OperatorCoder { | |||
| @@ -13,11 +13,11 @@ | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/scale_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/scale_fp32_coder.h" | |||
| #include <string> | |||
| #include "micro/coder/log.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/log.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Scale; | |||
| @@ -18,7 +18,7 @@ | |||
| #define MICRO_CODER_OPCODERS_FP32_SCALEFP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/scale.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -14,12 +14,12 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/slice_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/slice_fp32_coder.h" | |||
| #include <string> | |||
| #include "nnacl/slice_parameter.h" | |||
| #include "src/ops/slice.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Slice; | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_SLICE_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| class SliceFP32Coder final : public OperatorCoder { | |||
| @@ -14,11 +14,11 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/softmax_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/softmax_fp32_coder.h" | |||
| #include <string> | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "schema/inner/ops_generated.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_SoftMax; | |||
| @@ -14,10 +14,10 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/squeeze_dims_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/squeeze_dims_fp32_coder.h" | |||
| #include <string> | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Squeeze; | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_SQUEEZE_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| class SqueezeFP32Coder final : public OperatorCoder { | |||
| @@ -14,11 +14,11 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/fp32/tile_fp32_coder.h" | |||
| #include "coder/opcoders/nnacl/fp32/tile_fp32_coder.h" | |||
| #include <string> | |||
| #include <type_traits> | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using mindspore::schema::PrimitiveType_Tile; | |||
| @@ -18,7 +18,7 @@ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_TILE_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/base/tile_base.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -14,10 +14,10 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_LITE_MICRO_CODER_OPCODERS_NNACL_FP32_TRANSPOSE_FP32_CODER_H_ | |||
| #define MICRO_LITE_MICRO_CODER_OPCODERS_NNACL_FP32_TRANSPOSE_FP32_CODER_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_FP32_TRANSPOSE_FP32_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_FP32_TRANSPOSE_FP32_CODER_H_ | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/transpose.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -50,4 +50,4 @@ class TransposeFp32Coder final : public OperatorCoder { | |||
| }; | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| #endif // MICRO_LITE_MICRO_CODER_OPCODERS_NNACL_FP32_TRANSPOSE_FP32_CODER_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_FP32_TRANSPOSE_FP32_CODER_H_ | |||
| @@ -14,14 +14,14 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/int8/concat_int8_coder.h" | |||
| #include "coder/opcoders/nnacl/int8/concat_int8_coder.h" | |||
| #include <limits> | |||
| #include "nnacl/int8/concat_int8.h" | |||
| #include "nnacl/int8/arithmetic_int8.h" | |||
| #include "nnacl/int8/quantize.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "micro/coder/log.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_int8_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| #include "coder/log.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_int8_serializer.h" | |||
| int MallocQuantArgForConcat(ConcatQuantArg *quant_arg, size_t input_num) { | |||
| quant_arg->in_args_ = static_cast<QuantArg *>(malloc(sizeof(QuantArg) * input_num)); | |||
| @@ -13,14 +13,14 @@ | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/int8/pooling_int8_coder.h" | |||
| #include "coder/opcoders/nnacl/int8/pooling_int8_coder.h" | |||
| #include <memory> | |||
| #include <string> | |||
| #include <vector> | |||
| #include "nnacl/int8/pooling_int8.h" | |||
| #include "micro/coder/log.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_int8_serializer.h" | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "coder/log.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_int8_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| using std::string; | |||
| @@ -20,7 +20,7 @@ | |||
| #include <string> | |||
| #include <memory> | |||
| #include <vector> | |||
| #include "micro/coder/opcoders/op_coder.h" | |||
| #include "coder/opcoders/op_coder.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -13,12 +13,12 @@ | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #include "micro/coder/opcoders/nnacl/int8/reduce_int8_coder.h" | |||
| #include "coder/opcoders/nnacl/int8/reduce_int8_coder.h" | |||
| #include <vector> | |||
| #include <string> | |||
| #include "micro/coder/opcoders/file_collector.h" | |||
| #include "micro/coder/log.h" | |||
| #include "micro/coder/opcoders/serializers/nnacl_serializer/nnacl_int8_serializer.h" | |||
| #include "coder/opcoders/file_collector.h" | |||
| #include "coder/log.h" | |||
| #include "coder/opcoders/serializers/nnacl_serializer/nnacl_int8_serializer.h" | |||
| using mindspore::schema::PrimitiveType_Reduce; | |||
| namespace mindspore::lite::micro::nnacl { | |||
| @@ -14,15 +14,15 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MICRO_LITE_MICRO_CODER_OPCODERS_INT8_REDUCE_INT8_CODER_H_ | |||
| #define MICRO_LITE_MICRO_CODER_OPCODERS_INT8_REDUCE_INT8_CODER_H_ | |||
| #ifndef MINDSPORE_LITE_MICRO_CODER_OPCODERS_INT8_REDUCE_INT8_CODER_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_INT8_REDUCE_INT8_CODER_H_ | |||
| #include <string> | |||
| #include <vector> | |||
| #include "coder/opcoders/op_coder.h" | |||
| #include "nnacl/int8/quantize.h" | |||
| #include "nnacl/int8/reduce_int8.h" | |||
| #include "micro/coder/opcoders/base/reduce_base_coder.h" | |||
| #include "coder/opcoders/base/reduce_base_coder.h" | |||
| namespace mindspore::lite::micro::nnacl { | |||
| class ReduceInt8Coder final : public ReduceBaseCoder { | |||
| public: | |||
| @@ -52,4 +52,4 @@ class ReduceInt8Coder final : public ReduceBaseCoder { | |||
| std::vector<QuantMulArg *> sum_square_multipliers_; | |||
| }; | |||
| } // namespace mindspore::lite::micro::nnacl | |||
| #endif // MICRO_LITE_MICRO_CODER_OPCODERS_INT8_REDUCE_INT8_CODER_H_ | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_OPCODERS_INT8_REDUCE_INT8_CODER_H_ | |||