From: @yangjie159 Reviewed-by: @wangchengyuan Signed-off-by:tags/v1.2.0-rc1
| @@ -19,6 +19,7 @@ set(CODER_GENERATOR_SRC | |||
| ${MICRO_DIR}/coder/generator/generator.cc | |||
| ${MICRO_DIR}/coder/generator/inference/inference_generator.cc | |||
| ${MICRO_DIR}/coder/generator/train/train_generator.cc | |||
| ${MICRO_DIR}/coder/generator/component/component.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 | |||
| @@ -27,8 +28,11 @@ set(CODER_GENERATOR_SRC | |||
| ${MICRO_DIR}/coder/generator/component/parallel_component.cc | |||
| ${MICRO_DIR}/coder/generator/component/const_blocks/cmake_lists.cc | |||
| ${MICRO_DIR}/coder/generator/component/const_blocks/debug_utils.cc | |||
| ${MICRO_DIR}/coder/generator/component/const_blocks/msession.cc | |||
| ${MICRO_DIR}/coder/generator/component/const_blocks/mtensor.cc | |||
| ${MICRO_DIR}/coder/generator/component/const_blocks/license.cc | |||
| ${MICRO_DIR}/coder/generator/component/const_blocks/load_input.cc | |||
| ${MICRO_DIR}/coder/generator/component/const_blocks/benchmark.cc | |||
| ${MICRO_DIR}/coder/generator/component/const_blocks/micro_tensor.cc | |||
| ${MICRO_DIR}/coder/generator/component/const_blocks/thread_pool.cc | |||
| ) | |||
| @@ -96,7 +96,7 @@ void MemoryAllocator::RecordTensorsAddr(const std::map<Tensor *, size_t> &offset | |||
| void MemoryAllocator::AssignGraphInputs(const std::vector<Tensor *> &inputs) { | |||
| size_t num = inputs.size(); | |||
| for (size_t i = 0; i < num; ++i) { | |||
| inputs_addr_.insert(std::make_pair(inputs.at(i), net_input_addr_ + std::to_string(i))); | |||
| tensors_addr_.insert(std::make_pair(inputs.at(i), net_input_addr_ + std::to_string(i))); | |||
| } | |||
| } | |||
| @@ -104,11 +104,7 @@ class MemoryAllocator { | |||
| } | |||
| std::string type_info = wrap(type_name); | |||
| void *variable = reinterpret_cast<void *>(t); | |||
| auto item = inputs_addr_.find(variable); | |||
| if (item != inputs_addr_.end()) { | |||
| return type_info + item->second; | |||
| } | |||
| item = workspaces_addr_.find(variable); | |||
| auto item = workspaces_addr_.find(variable); | |||
| if (item != workspaces_addr_.end()) { | |||
| return type_info + wrap(item->second); | |||
| } | |||
| @@ -174,7 +170,6 @@ class MemoryAllocator { | |||
| std::map<Tensor *, std::string> origin_weights_addr_; | |||
| std::map<Tensor *, std::string> malloc_weights_addr_; | |||
| std::map<Tensor *, std::string> tensors_addr_; | |||
| std::map<void *, std::string> inputs_addr_; | |||
| std::string net_input_addr_; | |||
| std::string net_buffer_addr_; | |||
| std::string net_weight_addr_; | |||
| @@ -28,6 +28,7 @@ | |||
| #include "src/common/file_utils.h" | |||
| #include "src/common/utils.h" | |||
| #include "coder/coder_config.h" | |||
| #include "coder/generator/component/component.h" | |||
| namespace mindspore::lite::micro { | |||
| @@ -39,6 +40,7 @@ class CoderFlags : public virtual FlagParser { | |||
| AddFlag(&CoderFlags::code_module_name_, "moduleName", "Input code module name", ""); | |||
| AddFlag(&CoderFlags::target_, "target", "generated code target, x86| ARM32M| ARM32A| ARM64", "x86"); | |||
| AddFlag(&CoderFlags::code_mode_, "codeMode", "generated code mode, Inference | Train", "Inference"); | |||
| AddFlag(&CoderFlags::interface_, "interface", "the interface of generated code, CPP | C", "CPP"); | |||
| AddFlag(&CoderFlags::support_parallel_, "supportParallel", "whether support parallel launch, true | false", false); | |||
| AddFlag(&CoderFlags::debug_mode_, "debugMode", "dump the tensors data for debugging, true | false", false); | |||
| } | |||
| @@ -50,6 +52,7 @@ class CoderFlags : public virtual FlagParser { | |||
| std::string code_module_name_; | |||
| std::string code_path_; | |||
| std::string code_mode_; | |||
| std::string interface_; | |||
| bool debug_mode_{false}; | |||
| std::string target_; | |||
| }; | |||
| @@ -87,6 +90,7 @@ int Coder::Init(const CoderFlags &flags) const { | |||
| static const std::map<std::string, Target> kTargetMap = { | |||
| {"x86", kX86}, {"ARM32M", kARM32M}, {"ARM32A", kARM32A}, {"ARM64", kARM64}, {"All", kAllTargets}}; | |||
| static const std::map<std::string, CodeMode> kCodeModeMap = {{"Inference", Inference}, {"Train", Train}}; | |||
| static const std::map<std::string, Interface> kInterfaceMap = {{"CPP", Interface_CPP}, {"C", Interface_C}}; | |||
| Configurator *config = Configurator::GetInstance(); | |||
| @@ -106,7 +110,14 @@ int Coder::Init(const CoderFlags &flags) const { | |||
| }); | |||
| parsers.emplace_back([&flags, config]() -> bool { | |||
| if (flags.support_parallel_ == true && config->target() == kARM32M) { | |||
| auto item = kInterfaceMap.find(flags.interface_); | |||
| MS_CHECK_TRUE_RET_BOOL(item != kInterfaceMap.end(), "unsupported interface: " + flags.code_mode_); | |||
| config->set_interface(item->second); | |||
| return true; | |||
| }); | |||
| parsers.emplace_back([&flags, config]() -> bool { | |||
| if (flags.support_parallel_ && config->target() == kARM32M) { | |||
| MS_LOG(ERROR) << "arm32M cannot support parallel."; | |||
| return false; | |||
| } | |||
| @@ -162,6 +173,7 @@ int Coder::Init(const CoderFlags &flags) const { | |||
| } | |||
| return RET_ERROR; | |||
| } | |||
| config->set_module_name(kModelName); | |||
| auto print_parameter = [](auto name, auto value) { | |||
| MS_LOG(INFO) << std::setw(20) << std::left << name << "= " << value; | |||
| @@ -22,6 +22,7 @@ | |||
| namespace mindspore::lite::micro { | |||
| enum Target { kX86 = 0, kARM32M = 1, kARM32A = 2, kARM64 = 3, kAllTargets = 4, kTargetUnknown = 99 }; | |||
| enum CodeMode { Inference = 0, Train = 1, Code_Unknown = 99 }; | |||
| enum Interface { Interface_CPP = 0, Interface_C = 1, Interface_Unknown = 99 }; | |||
| inline const char *EnumNameTarget(Target target) { | |||
| switch (target) { | |||
| @@ -70,6 +71,9 @@ class Configurator { | |||
| void set_code_mode(CodeMode code_mode) { code_mode_ = code_mode; } | |||
| CodeMode code_mode() const { return code_mode_; } | |||
| void set_interface(Interface interface) { interface_ = interface; } | |||
| Interface interface() const { return interface_; } | |||
| void set_debug_mode(bool debug) { debug_mode_ = debug; } | |||
| bool debug_mode() const { return debug_mode_; } | |||
| @@ -84,6 +88,7 @@ class Configurator { | |||
| std::string code_path_; | |||
| Target target_{kTargetUnknown}; | |||
| CodeMode code_mode_{Code_Unknown}; | |||
| Interface interface_{Interface_CPP}; | |||
| bool support_parallel_{false}; | |||
| bool debug_mode_{false}; | |||
| }; | |||
| @@ -20,10 +20,9 @@ | |||
| namespace mindspore::lite::micro { | |||
| void CodeCMakeNetLibrary(std::ofstream &ofs, const std::string &module_name, const std::unique_ptr<CoderContext> &ctx, | |||
| Target target) { | |||
| void CodeCMakeNetLibrary(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx, const Configurator *config) { | |||
| ofs << "include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include/)\n"; | |||
| if (target == kARM32M) { | |||
| if (config->target() == kARM32M) { | |||
| ofs << "include_directories(${OP_HEADER_PATH}/CMSIS/NN/Include)\n" | |||
| << "include_directories(${OP_HEADER_PATH}/CMSIS/DSP/Include)\n" | |||
| << "include_directories(${OP_HEADER_PATH}/CMSIS/Core/Include)\n"; | |||
| @@ -32,12 +31,15 @@ void CodeCMakeNetLibrary(std::ofstream &ofs, const std::string &module_name, con | |||
| 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"; | |||
| ofs << " net_weight.c.o\n" | |||
| << " net.c.o\n"; | |||
| if (config->interface() == Interface_CPP) { | |||
| ofs << " session.cc.o\n" | |||
| << " tensor.cc.o\n"; | |||
| } | |||
| ofs << ")\n"; | |||
| std::set<std::string> kernel_cmake_asm_set_files = ctx->asm_files(); | |||
| if (!kernel_cmake_asm_set_files.empty() && (target == kARM32A || target == kARM64)) { | |||
| if (!kernel_cmake_asm_set_files.empty() && (config->target() == kARM32A || config->target() == kARM64)) { | |||
| ofs << "set(ASSEMBLY_SRC\n"; | |||
| for (const std::string &asm_file : kernel_cmake_asm_set_files) { | |||
| ofs << " " << asm_file << ".o\n"; | |||
| @@ -46,9 +48,11 @@ void CodeCMakeNetLibrary(std::ofstream &ofs, const std::string &module_name, con | |||
| << "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(net STATIC ${NET_SRC})\n"; | |||
| ofs << "file(GLOB NET_SRC\n" | |||
| " ${CMAKE_CURRENT_SOURCE_DIR}/*.cc\n" | |||
| " ${CMAKE_CURRENT_SOURCE_DIR}/*.c\n" | |||
| " )\n" | |||
| "add_library(net STATIC ${NET_SRC})\n"; | |||
| } | |||
| } // namespace mindspore::lite::micro | |||
| @@ -27,8 +27,7 @@ | |||
| #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); | |||
| void CodeCMakeNetLibrary(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx, const Configurator *config); | |||
| } // namespace mindspore::lite::micro | |||
| @@ -17,7 +17,9 @@ | |||
| #include "coder/generator/component/common_component.h" | |||
| #include <memory> | |||
| #include "coder/generator/component/const_blocks/license.h" | |||
| #include "coder/generator/component/component.h" | |||
| #include "coder/utils/type_cast.h" | |||
| #include "coder/utils/coder_utils.h" | |||
| #include "coder/log.h" | |||
| #include "include/errorcode.h" | |||
| #include "nnacl/op_base.h" | |||
| @@ -29,6 +31,59 @@ void CodeSourceFileInclude(std::ofstream &ofs, const std::string &weight_file, c | |||
| << "#include \"" << header << "\"\n\n"; | |||
| } | |||
| void CodeSessionCompileGraph(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx) { | |||
| std::vector<Tensor *> inputs = ctx->graph_inputs(); | |||
| std::vector<Tensor *> outputs = ctx->graph_outputs(); | |||
| size_t inputs_size = inputs.size(); | |||
| size_t outputs_size = outputs.size(); | |||
| ofs << kNameSpaceMindSpore << " {\n"; | |||
| ofs << kNameSpaceLite << " {\n"; | |||
| ofs << "int LiteSession::CompileGraph(lite::Model *model) {\n"; | |||
| ofs << " inputs_.resize(" << inputs_size << ");\n"; | |||
| for (size_t i = 0; i < inputs_size; ++i) { | |||
| Tensor *input = inputs[i]; | |||
| ofs << " inputs_[" << i << "] = new (std::nothrow) MTensor(\"" << input->tensor_name() << "\", " | |||
| << EnumNameDataType(input->data_type()) << ", " << ArrayToString(input->shape()) << ");\n"; | |||
| ofs << " MS_ERROR_IF_NULL(inputs_[" << i << "]);\n"; | |||
| } | |||
| ofs << " outputs_.resize(" << outputs_size << ");\n"; | |||
| for (size_t i = 0; i < outputs_size; ++i) { | |||
| Tensor *output = outputs[i]; | |||
| ofs << " outputs_[" << i << "] = new (std::nothrow) MTensor(\"" << output->tensor_name() << "\", " | |||
| << EnumNameDataType(output->data_type()) << ", " << ArrayToString(output->shape()) << ");\n"; | |||
| ofs << " MS_ERROR_IF_NULL(outputs_[" << i << "]);\n"; | |||
| } | |||
| ofs << " for (const auto &output: outputs_) {\n" | |||
| " output_tensor_map_[output->tensor_name()] = output;\n" | |||
| " }\n"; | |||
| ofs << " return RET_OK;\n"; | |||
| ofs << "}\n\n"; | |||
| } | |||
| void CodeCopyOutputsState(std::ofstream &ofs) { ofs << "int CopyOutputsData(void **outputs, int num);\n\n"; } | |||
| void CodeCopyOutputsImplement(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx) { | |||
| auto tensor_map = ctx->tensors_map(); | |||
| std::vector<Tensor *> outputs = ctx->graph_outputs(); | |||
| size_t outputs_size = outputs.size(); | |||
| ofs << "int CopyOutputsData(void **outputs, int num) {\n" | |||
| " if (outputs == NULL) {\n" | |||
| " return RET_ERROR;\n" | |||
| " }\n" | |||
| << " if (num != " << outputs_size << ") {\n" | |||
| << " return RET_ERROR;\n" | |||
| " }\n"; | |||
| for (size_t i = 0; i < outputs_size; ++i) { | |||
| Tensor *output = outputs[i]; | |||
| MS_CHECK_PTR_IF_NULL(output); | |||
| ofs << " memcpy(outputs[" << i << "], " << tensor_map[output] << ", " << output->Size() << ");\n"; | |||
| } | |||
| ofs << " outputs[0] = net_B;\n" | |||
| " return RET_OK;\n" | |||
| "}\n\n"; | |||
| } | |||
| void CodeInputAndOutputState(std::ofstream &ofs, const std::string &module_name) { | |||
| ofs << "/**\n" | |||
| << " * set input tensors\n" | |||
| @@ -61,7 +116,7 @@ void PrintMicroTensors(std::ofstream &ofs, std::vector<Tensor *> tensors, const | |||
| << " " << name << "[" << i << "].ndim = " << tensor->shape().size() << ";\n" | |||
| << " " << name << "[" << i << "].dim = dim" << i << ";\n" | |||
| << " " << name << "[" << i << "].type = " << EnumMicroTensorDataType(tensor->data_type()) << ";\n" | |||
| << " " << name << "[" << i << "].format = " << std::to_string(tensor->format()) << ";\n" | |||
| << " " << name << "[" << i << "].format = " << EnumMicroTensorFormat(tensor->format()) << ";\n" | |||
| << " " << name << "[" << i << "].data =" << item->second << ";\n"; | |||
| } | |||
| } | |||
| @@ -82,7 +137,7 @@ void CodeInputAndOutputImplement(std::ofstream &ofs, const std::string &module_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 << "\t" << ctx->input_name() << i << " = inputs[" << i << "];\n"; | |||
| } | |||
| ofs << " return RET_OK;\n}\n"; | |||
| @@ -129,14 +184,6 @@ void CodeGraphQuantArgsImplement(std::ofstream &ofs, const std::string &module_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" | |||
| @@ -161,12 +208,10 @@ void CodeInitResourceImplement(std::ofstream &ofs, const std::string &module_nam | |||
| << "}\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" | |||
| ofs << " " << ctx->buffer_name() << " = buffer;\n" | |||
| << " return RET_OK;\n" | |||
| "}\n"; | |||
| } | |||
| @@ -28,6 +28,11 @@ | |||
| namespace mindspore::lite::micro { | |||
| void CodeSourceFileInclude(std::ofstream &ofs, const std::string &weight_file, const std::string &header); | |||
| void CodeSessionCompileGraph(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx); | |||
| void CodeCopyOutputsState(std::ofstream &ofs); | |||
| void CodeCopyOutputsImplement(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx); | |||
| 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); | |||
| @@ -36,8 +41,6 @@ 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); | |||
| @@ -0,0 +1,43 @@ | |||
| /** | |||
| * 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/component.h" | |||
| namespace mindspore::lite::micro { | |||
| const char *kModelName = "net"; | |||
| const char *kSession = "session"; | |||
| const char *kByteType = "unsigned char *"; | |||
| const char *kConstByteType = "const unsigned char *"; | |||
| const char *kNameSpaceMindSpore = "namespace mindspore"; | |||
| const char *kNameSpaceLite = "namespace lite"; | |||
| const char *kExternCpp = R"RAW( | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| )RAW"; | |||
| const char *kEndExternCpp = R"RAW( | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| )RAW"; | |||
| } // namespace mindspore::lite::micro | |||
| @@ -0,0 +1,37 @@ | |||
| /** | |||
| * 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_COMPONENT_H_ | |||
| #define MINDSPORE_LITE_MICRO_CODER_GENERATOR_COMPONENT_H_ | |||
| namespace mindspore::lite::micro { | |||
| extern const char *kModelName; | |||
| extern const char *kSession; | |||
| extern const char *kByteType; | |||
| extern const char *kConstByteType; | |||
| extern const char *kNameSpaceMindSpore; | |||
| extern const char *kNameSpaceLite; | |||
| extern const char *kExternCpp; | |||
| extern const char *kEndExternCpp; | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_GENERATOR_COMPONENT_H_ | |||
| @@ -43,7 +43,7 @@ const char *benchmark_source = R"RAW( | |||
| #include "include/ms_tensor.h" | |||
| #include "include/errorcode.h" | |||
| #include "read_file.h" | |||
| #include "load_input.h" | |||
| using namespace mindspore; | |||
| @@ -86,12 +86,13 @@ int main(int argc, const char **argv) { | |||
| for (size_t i = 0; i < inputs_num; ++i) { | |||
| inputs_size[i] = inputs[i]->Size(); | |||
| } | |||
| int ret = ReadInputsFile(argv[1], inputs_binbuf, inputs_size, inputs_num); | |||
| int ret = ReadInputsFile(const_cast<char *>(argv[1]), inputs_binbuf, inputs_size, inputs_num); | |||
| if (ret != lite::RET_OK) { | |||
| return lite::RET_ERROR; | |||
| } | |||
| for (size_t i = 0; i < inputs_num; ++i) { | |||
| inputs[i]->set_data(inputs_binbuf[i]); | |||
| void *input_data = inputs[i]->MutableData(); | |||
| memcpy(input_data, inputs_binbuf[i], inputs_size[i]); | |||
| } | |||
| ret = session->RunGraph(); | |||
| @@ -100,7 +101,11 @@ int main(int argc, const char **argv) { | |||
| } | |||
| auto outputs = session->GetOutputs(); | |||
| std::cout << outputs.size() << std::endl; | |||
| std::cout << "output size: " << outputs.size() << std::endl; | |||
| for (const auto &item : outputs) { | |||
| auto output = item.second; | |||
| std::cout << "name: " << output->tensor_name() << ", size: " << output->Size() << std::endl; | |||
| } | |||
| std::cout << "run benchmark success" << std::endl; | |||
| delete session; | |||
| @@ -59,15 +59,19 @@ if(MICRO_BUILD_ARM32A) | |||
| add_definitions(-mfloat-abi=softfp -mfpu=neon) | |||
| endif() | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include) | |||
| set(CMAKE_C_FLAGS "${CMAKE_ENABLE_C99} ${CMAKE_C_FLAGS}") | |||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") | |||
| if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") | |||
| message("*******************${CMAKE_BUILD_TYPE}**********") | |||
| set(CMAKE_C_FLAGS "-DDebug -g -fPIC -fPIE -fvisibility=default ${CMAKE_C_FLAGS}") | |||
| message(STATUS "build benchmark with debug info") | |||
| set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDebug -g") | |||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDebug -g") | |||
| set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=default") | |||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default") | |||
| else() | |||
| set(CMAKE_C_FLAGS "-fPIC -fPIE -O3 -fstack-protector-strong -fomit-frame-pointer ${CMAKE_C_FLAGS}") | |||
| set(CMAKE_C_FLAGS_Release "${CMAKE_C_FLAGS_Release} -O3 -ffunction-sections -fdata-sections") | |||
| set(CMAKE_C_FLAGS "-fPIC -fPIE -D_FORTIFY_SOURCE=2 -O2 -Wall -Werror -fstack-protector-strong -Wno-attributes \ | |||
| -Wno-deprecated-declarations -Wno-missing-braces ${CMAKE_C_FLAGS}") | |||
| set(CMAKE_CXX_FLAGS "-fPIC -fPIE -D_FORTIFY_SOURCE=2 -O2 -Wall -Werror -fstack-protector-strong -Wno-attributes \ | |||
| -Wno-deprecated-declarations -Wno-missing-braces -Wno-overloaded-virtual ${CMAKE_CXX_FLAGS}") | |||
| endif() | |||
| link_directories(${MODEL_LIB_PATH}) | |||
| include(benchmark.cmake) | |||
| @@ -96,6 +100,7 @@ message("operator header path: ${OP_HEADER_PATH}") | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include) | |||
| include_directories(${OP_HEADER_PATH}) | |||
| include_directories(${HEADER_PATH}) | |||
| include(net.cmake) | |||
| @@ -118,12 +123,17 @@ if(MICRO_BUILD_ARM32A) | |||
| endif() | |||
| set(CMAKE_C_FLAGS "${CMAKE_ENABLE_C99} ${CMAKE_C_FLAGS}") | |||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") | |||
| if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") | |||
| set(CMAKE_C_FLAGS "-DDebug -g -fPIC -fPIE -fvisibility=default ${CMAKE_C_FLAGS}") | |||
| set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDebug -g") | |||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDebug -g") | |||
| set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=default") | |||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default") | |||
| else() | |||
| set(CMAKE_C_FLAGS "-fPIC -fPIE -O3 -Werror -fstack-protector-strong -fomit-frame-pointer ${CMAKE_C_FLAGS}") | |||
| set(CMAKE_C_FLAGS_Release "${CMAKE_C_FLAGS_Release} -O3 -ffunction-sections -Werror -fdata-sections") | |||
| string(REPLACE "-g" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") | |||
| set(CMAKE_C_FLAGS "-fPIC -fPIE -D_FORTIFY_SOURCE=2 -O2 -Wall -Werror -fstack-protector-strong -Wno-attributes \ | |||
| -Wno-deprecated-declarations -Wno-missing-braces ${CMAKE_C_FLAGS}") | |||
| set(CMAKE_CXX_FLAGS "-fPIC -fPIE -D_FORTIFY_SOURCE=2 -O2 -Wall -Werror -fstack-protector-strong -Wno-attributes \ | |||
| -Wno-deprecated-declarations -Wno-missing-braces -Wno-overloaded-virtual ${CMAKE_CXX_FLAGS}") | |||
| endif() | |||
| function(create_library) | |||
| @@ -37,12 +37,21 @@ const char *load_input_h = R"RAW( | |||
| #ifndef MICRO_EXAMPLE_LOAD_INPUT_LOAD_INPUT_H_ | |||
| #define MICRO_EXAMPLE_LOAD_INPUT_LOAD_INPUT_H_ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| void *ReadInputData(const char *real_input_path, int *size); | |||
| void SaveOutputData(char *final_name, unsigned char *output_data, unsigned int out_size); | |||
| int ReadInputsFile(char *path, void **buffers, const int *inputs_size, int inputs_num); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif // MICRO_EXAMPLE_LOAD_INPUT_LOAD_INPUT_H_ | |||
| )RAW"; | |||
| @@ -0,0 +1,225 @@ | |||
| /** | |||
| * 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/const_blocks/msession.h" | |||
| namespace mindspore::lite::micro { | |||
| const char *session_header = R"RAW( | |||
| /** | |||
| * 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_LIBRARY_SOURCE_SESSION_H_ | |||
| #define MINDSPORE_LITE_MICRO_LIBRARY_SOURCE_SESSION_H_ | |||
| #include "include/errorcode.h" | |||
| #include "include/lite_session.h" | |||
| #include "tensor.h" | |||
| namespace mindspore { | |||
| namespace lite { | |||
| #define MS_ERROR_IF_NULL(ptr) \ | |||
| do { \ | |||
| if ((ptr) == nullptr) { \ | |||
| return mindspore::lite::RET_ERROR; \ | |||
| } \ | |||
| } while (0) | |||
| class LiteSession : public session::LiteSession { | |||
| public: | |||
| LiteSession() = default; | |||
| ~LiteSession() override; | |||
| void BindThread(bool if_bind) override {} | |||
| int CompileGraph(lite::Model *model) override; | |||
| std::vector<tensor::MSTensor *> GetInputs() const override; | |||
| mindspore::tensor::MSTensor *GetInputsByTensorName(const std::string &tensor_name) const override { return nullptr; } | |||
| int RunGraph(const KernelCallBack &before = nullptr, const KernelCallBack &after = nullptr) override; | |||
| std::vector<tensor::MSTensor *> GetOutputsByNodeName(const std::string &node_name) const override; | |||
| std::unordered_map<std::string, mindspore::tensor::MSTensor *> GetOutputs() const override; | |||
| std::vector<std::string> GetOutputTensorNames() const override; | |||
| mindspore::tensor::MSTensor *GetOutputByTensorName(const std::string &tensor_name) const override; | |||
| int Resize(const std::vector<tensor::MSTensor *> &inputs, const std::vector<std::vector<int>> &dims) override; | |||
| int InitRuntimeBuffer(); | |||
| private: | |||
| int SetInputsData(const std::vector<MTensor *> &inputs) const; | |||
| std::vector<MTensor *> inputs_; | |||
| std::vector<MTensor *> outputs_; | |||
| std::unordered_map<std::string, mindspore::tensor::MSTensor *> output_tensor_map_; | |||
| std::unordered_map<std::string, std::vector<mindspore::tensor::MSTensor *>> output_node_map_; | |||
| void *runtime_buffer_; | |||
| }; | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| #endif // MINDSPORE_LITE_MICRO_LIBRARY_SOURCE_SESSION_H_ | |||
| )RAW"; | |||
| const char *session_source = R"RAW( | |||
| int LiteSession::RunGraph(const KernelCallBack &before, const KernelCallBack &after) { | |||
| const void *inputs_data[inputs_.size()]; | |||
| for (size_t i = 0; i < inputs_.size(); ++i) { | |||
| inputs_data[i] = inputs_[i]->MutableData(); | |||
| } | |||
| net_SetInputs(inputs_data, inputs_.size()); | |||
| net_Inference(); | |||
| void *outputs_data[outputs_.size()]; | |||
| for (size_t i = 0; i < outputs_.size(); ++i) { | |||
| outputs_data[i] = outputs_[i]->MutableData(); | |||
| } | |||
| CopyOutputsData(outputs_data, outputs_.size()); | |||
| return RET_OK; | |||
| } | |||
| LiteSession::~LiteSession() { | |||
| net_FreeResource(); | |||
| if (runtime_buffer_ != nullptr) { | |||
| free(runtime_buffer_); | |||
| runtime_buffer_ = nullptr; | |||
| } | |||
| for (auto &input : inputs_) { | |||
| if (input == nullptr) { | |||
| continue; | |||
| } | |||
| delete input; | |||
| input = nullptr; | |||
| } | |||
| for (auto &item : output_tensor_map_) { | |||
| auto output = item.second; | |||
| if (output == nullptr) { | |||
| continue; | |||
| } | |||
| delete output; | |||
| output = nullptr; | |||
| } | |||
| } | |||
| int LiteSession::InitRuntimeBuffer() { | |||
| int buffer_size = net_GetBufferSize(); | |||
| runtime_buffer_ = malloc(buffer_size); | |||
| if (runtime_buffer_ == nullptr) { | |||
| return RET_ERROR; | |||
| } | |||
| int ret = net_SetBuffer(runtime_buffer_); | |||
| if (ret != RET_OK) { | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| std::vector<tensor::MSTensor *> LiteSession::GetInputs() const { | |||
| std::vector<tensor::MSTensor *> inputs; | |||
| inputs.insert(inputs.begin(), inputs_.begin(), inputs_.end()); | |||
| return inputs; | |||
| } | |||
| std::vector<tensor::MSTensor *> LiteSession::GetOutputsByNodeName(const std::string &node_name) const { | |||
| auto iter = output_node_map_.find(node_name); | |||
| if (iter == output_node_map_.end()) { | |||
| std::vector<tensor::MSTensor *> empty; | |||
| return empty; | |||
| } | |||
| return iter->second; | |||
| } | |||
| std::unordered_map<std::string, mindspore::tensor::MSTensor *> LiteSession::GetOutputs() const { | |||
| return output_tensor_map_; | |||
| } | |||
| std::vector<std::string> LiteSession::GetOutputTensorNames() const { | |||
| std::vector<std::string> output_names; | |||
| for (const auto &item : output_node_map_) { | |||
| for (const auto &output : item.second) { | |||
| output_names.emplace_back(output->tensor_name()); | |||
| } | |||
| } | |||
| return output_names; | |||
| } | |||
| mindspore::tensor::MSTensor *LiteSession::GetOutputByTensorName(const std::string &tensor_name) const { | |||
| auto item = output_tensor_map_.find(tensor_name); | |||
| if (item == output_tensor_map_.end()) { | |||
| return nullptr; | |||
| } | |||
| return item->second; | |||
| } | |||
| int LiteSession::Resize(const std::vector<tensor::MSTensor *> &inputs, const std::vector<std::vector<int>> &dims) { | |||
| return RET_OK; | |||
| } | |||
| } // namespace lite | |||
| session::LiteSession *session::LiteSession::CreateSession(const lite::Context *context) { | |||
| auto *session = new (std::nothrow) lite::LiteSession(); | |||
| if (session == nullptr) { | |||
| return nullptr; | |||
| } | |||
| session->InitRuntimeBuffer(); | |||
| return session; | |||
| } | |||
| session::LiteSession *session::LiteSession::CreateSession(const char *net_buf, size_t size, | |||
| const lite::Context *context) { | |||
| session::LiteSession *session = CreateSession(context); | |||
| if (session == nullptr) { | |||
| return nullptr; | |||
| } | |||
| int ret = session->CompileGraph(nullptr); | |||
| if (ret != lite::RET_OK) { | |||
| return nullptr; | |||
| } | |||
| net_Init(const_cast<char *>(net_buf), size); | |||
| return session; | |||
| } | |||
| } // namespace mindspore | |||
| )RAW"; | |||
| } // namespace mindspore::lite::micro | |||
| @@ -0,0 +1,28 @@ | |||
| /** | |||
| * 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_GENERATOR_CONST_BLOCK_SESSION_H_ | |||
| #define MINDSPORE_LITE_MICRO_GENERATOR_CONST_BLOCK_SESSION_H_ | |||
| namespace mindspore::lite::micro { | |||
| extern const char *session_header; | |||
| extern const char *session_source; | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MINDSPORE_LITE_MICRO_GENERATOR_CONST_BLOCK_SESSION_H_ | |||
| @@ -19,6 +19,7 @@ | |||
| namespace mindspore::lite::micro { | |||
| const char *tensor_header = R"RAW( | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * | |||
| @@ -60,16 +61,16 @@ struct QuantArg { | |||
| class MTensor : public mindspore::tensor::MSTensor { | |||
| public: | |||
| MTensor() = default; | |||
| MTensor(std::string name, enum TypeId type, std::vector<int32_t> shape, void *data) | |||
| : tensor_name_(std::move(name)), data_type_(type), shape_(std::move(shape)), data_(data) {} | |||
| ~MTensor() override = default; | |||
| MTensor(std::string name, enum TypeId type, std::vector<int32_t> shape) | |||
| : tensor_name_(std::move(name)), data_type_(type), shape_(std::move(shape)) {} | |||
| ~MTensor() override; | |||
| TypeId data_type() const override { return data_type_; } | |||
| std::vector<int> shape() const override { return shape_; } | |||
| int DimensionSize(size_t index) const override; | |||
| int ElementsNum() const override; | |||
| size_t Size() const override; | |||
| void *MutableData() override { return data_; }; | |||
| void *MutableData() override; | |||
| std::string tensor_name() const override { return tensor_name_; } | |||
| void set_tensor_name(const std::string name) override { tensor_name_ = name; } | |||
| void set_data(void *data) override { data_ = data; } | |||
| @@ -87,9 +88,11 @@ class MTensor : public mindspore::tensor::MSTensor { | |||
| #endif // MINDSPORE_LITE_MICRO_LIBRARY_SOURCE_TENSOR_H_ | |||
| )RAW"; | |||
| const char *tensor_source = R"RAW( | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * | |||
| @@ -144,6 +147,13 @@ size_t DataTypeSize(const TypeId type) { | |||
| } | |||
| } | |||
| MTensor::~MTensor() { | |||
| if (data_ != nullptr) { | |||
| free(data_); | |||
| data_ = nullptr; | |||
| } | |||
| } | |||
| int MTensor::DimensionSize(const size_t index) const { | |||
| int dim_size = -1; | |||
| if (index < shape_.size()) { | |||
| @@ -164,6 +174,13 @@ size_t MTensor::Size() const { | |||
| size_t element_size = DataTypeSize(data_type_); | |||
| return element_size * ElementsNum(); | |||
| } | |||
| void *MTensor::MutableData() { | |||
| if (data_ == nullptr) { | |||
| data_ = malloc(this->Size()); | |||
| } | |||
| return data_; | |||
| } | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| @@ -84,6 +84,14 @@ void CodeModelParamsForNet(std::ofstream &hofs, std::ofstream &cofs, const std:: | |||
| cofs << "\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 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" | |||
| @@ -34,6 +34,8 @@ void CodeModelParamsData(std::ofstream &ofs, const std::map<std::string, Tensor | |||
| 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 CodeInitWeightState(std::ofstream &ofs, const std::string &module_name); | |||
| void CodeWeightInitFunc(std::ofstream &ofs, const std::string &module_name, const std::unique_ptr<CoderContext> &ctx); | |||
| } // namespace mindspore::lite::micro | |||
| @@ -15,16 +15,19 @@ | |||
| */ | |||
| #include "coder/generator/generator.h" | |||
| #include <sys/stat.h> | |||
| #include <map> | |||
| #include <set> | |||
| #include <fstream> | |||
| #include "coder/generator/component/cmake_component.h" | |||
| #include "coder/generator/component/weight_component.h" | |||
| #include "coder/generator/component/common_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/thread_pool.h" | |||
| #include "coder/generator/component/const_blocks/msession.h" | |||
| #include "coder/generator/component/const_blocks/mtensor.h" | |||
| #include "coder/generator/component/const_blocks/benchmark.h" | |||
| #include "coder/generator/component/const_blocks/license.h" | |||
| #include "coder/log.h" | |||
| @@ -48,8 +51,11 @@ Generator::Generator(std::unique_ptr<CoderContext> ctx) { | |||
| this->net_inc_hfile_ = module_name + ".h"; | |||
| this->net_src_cfile_ = module_name + ".c"; | |||
| this->net_weight_hfile_ = module_name + "_weight.h"; | |||
| this->net_main_cfile_ = module_name + "_benchmark.c"; | |||
| if (config_->interface() == Interface_CPP) { | |||
| this->net_main_cfile_ = "benchmark.cc"; | |||
| } else { | |||
| this->net_main_cfile_ = "benchmark.c"; | |||
| } | |||
| this->net_src_file_path_ = config_->code_path() + "/src/"; | |||
| this->net_inc_file_path_ = config_->code_path() + "/include/"; | |||
| this->net_main_file_path_ = config_->code_path() + "/benchmark/"; | |||
| @@ -80,9 +86,14 @@ int Generator::CodeBenchmarkCMakeFile() { | |||
| MS_CHECK_TRUE(!ofs.bad(), "filed to open file"); | |||
| MS_LOG(INFO) << "write " << test_cmake_file; | |||
| ofs << "include_directories(${CMAKE_CURRENT_SOURCE_DIR})\n"; | |||
| ofs << "include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include/)\n"; | |||
| if (config_->interface() == Interface_CPP) { | |||
| ofs << "include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/)\n"; | |||
| ofs << "include_directories(${HEADER_PATH})\n"; | |||
| } else { | |||
| ofs << "include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include/)\n"; | |||
| } | |||
| ofs << "set(SRC_FILES\n"; | |||
| ofs << "\t\t" << config_->module_name() + "_benchmark.c\n"; | |||
| ofs << "\t\t" << net_main_cfile_ << "\n"; | |||
| ofs << "\t\tload_input.c\n"; | |||
| ofs << "\t\tdebug_utils.c\n"; | |||
| ofs << ")\n"; | |||
| @@ -95,24 +106,32 @@ int Generator::CodeSourceCMakeFile() { | |||
| 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()); | |||
| CodeCMakeNetLibrary(ofs, ctx_, config_); | |||
| ofs.close(); | |||
| return RET_OK; | |||
| } | |||
| int Generator::CodeStaticContent() { | |||
| std::vector<std::pair<std::string, std::string>> static_blocks = { | |||
| {net_inc_file_path_ + "microtensor.h", micro_tensor_h}, | |||
| std::vector<std::pair<std::string, std::string>> const_blocks = { | |||
| {net_src_file_path_ + "CMakeLists.txt", src_cmake_lists_txt}, | |||
| {net_main_file_path_ + "debug_utils.h", debug_utils_h}, | |||
| {net_main_file_path_ + "debug_utils.c", debug_utils_c}, | |||
| {net_main_file_path_ + "load_input.h", load_input_h}, | |||
| {net_main_file_path_ + "load_input.c", load_input_c}, | |||
| {net_main_file_path_ + "CMakeLists.txt", bench_cmake_lists_txt}}; | |||
| if (config_->interface() == Interface_CPP) { | |||
| const_blocks.emplace_back(net_src_file_path_ + "microtensor.h", micro_tensor_h); | |||
| const_blocks.emplace_back(net_src_file_path_ + "session.h", session_header); | |||
| const_blocks.emplace_back(net_src_file_path_ + "tensor.h", tensor_header); | |||
| const_blocks.emplace_back(net_src_file_path_ + "tensor.cc", tensor_source); | |||
| const_blocks.emplace_back(net_main_file_path_ + "benchmark.cc", benchmark_source); | |||
| } else { | |||
| const_blocks.emplace_back(net_inc_file_path_ + "microtensor.h", micro_tensor_h); | |||
| } | |||
| if (config_->support_parallel()) { | |||
| static_blocks.emplace_back(net_inc_file_path_ + "thread_pool.h", thread_pool_h); | |||
| const_blocks.emplace_back(net_inc_file_path_ + "thread_pool.h", thread_pool_h); | |||
| } | |||
| for (const auto &static_block : static_blocks) { | |||
| for (const auto &static_block : const_blocks) { | |||
| std::string file_name = static_block.first; | |||
| std::string content = static_block.second; | |||
| MS_CHECK_RET_CODE(WriteContentToFile(file_name, content), "write file failed"); | |||
| @@ -120,6 +139,19 @@ int Generator::CodeStaticContent() { | |||
| return RET_OK; | |||
| } | |||
| int Generator::CodeSessionImplement() { | |||
| std::string cfile = net_src_file_path_ + "session.cc"; | |||
| std::ofstream ofs(cfile); | |||
| MS_CHECK_TRUE(!ofs.bad(), "filed to open file"); | |||
| MS_LOG(INFO) << "write " << cfile; | |||
| ofs << g_hwLicense; | |||
| ofs << "#include \"session.h\"\n"; | |||
| ofs << "#include \"net.h\"\n\n"; | |||
| CodeSessionCompileGraph(ofs, ctx_); | |||
| ofs << session_source; | |||
| return RET_OK; | |||
| } | |||
| int Generator::CodeWeightFile() { | |||
| // weight header file | |||
| std::string hfile = net_src_file_path_ + net_weight_hfile_; | |||
| @@ -156,9 +188,13 @@ int Generator::GenerateCode() { | |||
| MS_CHECK_RET_CODE(CodeNetCFile(), "code net c file failed."); | |||
| MS_CHECK_RET_CODE(CodeWeightFile(), "code weight 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."); | |||
| if (config_->interface() == Interface_CPP) { | |||
| MS_CHECK_RET_CODE(CodeSessionImplement(), "code session file failed."); | |||
| } else { | |||
| MS_CHECK_RET_CODE(CodeBenchmarkFile(), "code benchmark file failed."); | |||
| } | |||
| return RET_OK; | |||
| } | |||
| } // namespace mindspore::lite::micro | |||
| @@ -34,6 +34,7 @@ | |||
| #include "coder/utils/type_cast.h" | |||
| namespace mindspore::lite::micro { | |||
| class Generator { | |||
| public: | |||
| explicit Generator(std::unique_ptr<CoderContext> ctx); | |||
| @@ -66,6 +67,7 @@ class Generator { | |||
| int CodeBenchmarkCMakeFile(); | |||
| int CodeSourceCMakeFile(); | |||
| int CodeStaticContent(); | |||
| int CodeSessionImplement(); | |||
| std::string cmake_file_name_{"net.cmake"}; | |||
| // the user's generated file's permission | |||
| @@ -20,11 +20,18 @@ | |||
| #include "coder/generator/component/common_component.h" | |||
| #include "coder/generator/component/parallel_component.h" | |||
| #include "coder/generator/component/benchmark_component.h" | |||
| #include "coder/generator/component/weight_component.h" | |||
| #include "coder/generator/component/const_blocks/license.h" | |||
| #include "coder/generator/component/component.h" | |||
| namespace mindspore::lite::micro { | |||
| int InferenceGenerator::CodeNetHFile() { | |||
| std::string net_include_file = net_inc_file_path_ + net_inc_hfile_; | |||
| std::string net_include_file; | |||
| if (config_->interface() == Interface_CPP) { | |||
| net_include_file = net_src_file_path_ + net_inc_hfile_; | |||
| } else { | |||
| net_include_file = net_inc_file_path_ + net_inc_hfile_; | |||
| } | |||
| std::ofstream ofs(net_include_file); | |||
| MS_CHECK_TRUE(!ofs.bad(), "filed to open file"); | |||
| MS_LOG(INFO) << "write " << net_include_file; | |||
| @@ -33,7 +40,11 @@ int InferenceGenerator::CodeNetHFile() { | |||
| ofs << "#include \"thread_pool.h\"\n"; | |||
| } | |||
| ofs << "#include \"microtensor.h\"\n\n"; | |||
| ofs << kExternCpp; | |||
| CodeInputAndOutputState(ofs, config_->module_name()); | |||
| if (config_->interface() == Interface_CPP) { | |||
| CodeCopyOutputsState(ofs); | |||
| } | |||
| if (is_get_quant_args_) { | |||
| CodeGraphQuantArgsState(ofs, config_->module_name()); | |||
| } | |||
| @@ -45,6 +56,7 @@ int InferenceGenerator::CodeNetHFile() { | |||
| } | |||
| CodeManageResourceState(ofs, config_->module_name()); | |||
| CodeInferenceState(ofs, config_->module_name()); | |||
| ofs << kEndExternCpp; | |||
| return RET_OK; | |||
| } | |||
| @@ -58,6 +70,9 @@ int InferenceGenerator::CodeNetCFile() { | |||
| CodeSetGlobalThreadPoolImplement(ofs, config_->module_name()); | |||
| } | |||
| CodeInputAndOutputImplement(ofs, config_->module_name(), ctx_); | |||
| if (config_->interface() == Interface_CPP) { | |||
| CodeCopyOutputsImplement(ofs, ctx_); | |||
| } | |||
| CodeInitResourceImplement(ofs, config_->module_name(), ctx_); | |||
| CodeFreeResourceImplement(ofs, config_->module_name(), ctx_); | |||
| if (is_get_quant_args_) { | |||
| @@ -19,6 +19,7 @@ | |||
| #include <string> | |||
| #include "coder/generator/component/common_component.h" | |||
| #include "coder/generator/component/benchmark_component.h" | |||
| #include "coder/generator/component/weight_component.h" | |||
| #include "coder/generator/component/train_component.h" | |||
| #include "coder/generator/component/const_blocks/license.h" | |||
| @@ -87,6 +87,9 @@ int CoderGraph::ConvertTensors() { | |||
| "memcpy_s copy data failed!", delete dstTensor); | |||
| dstTensor->set_data(dst_data); | |||
| } | |||
| if (origin_tensor->name() != nullptr) { | |||
| dstTensor->set_tensor_name(origin_tensor->name()->str()); | |||
| } | |||
| auto quant_params = origin_tensor->quantParams(); | |||
| if (quant_params != nullptr) { | |||
| for (int j = 0; j < static_cast<int>(quant_params->size()); j++) { | |||
| @@ -75,13 +75,6 @@ void PrintTensorData(const lite::Tensor *tensor, std::ofstream &ofs) { | |||
| } | |||
| } | |||
| template <typename T> | |||
| std::string ArrayToString(const std::vector<T> &array) { | |||
| std::string result = "{"; | |||
| std::for_each(array.begin(), array.end(), [&result](const T &t) { result += std::to_string(t) + ", "; }); | |||
| return result + "}"; | |||
| } | |||
| std::string TensorsToString(const std::vector<Tensor *> &tensors, const std::string &is_input) { | |||
| MemoryAllocator *allocator = MemoryAllocator::GetInstance(); | |||
| std::string info; | |||
| @@ -35,6 +35,13 @@ std::vector<std::string> AddDumpDataInfo(const std::vector<std::string> &blocks, | |||
| void PrintTensorData(const lite::Tensor *tensor, std::ofstream &ofs); | |||
| template <typename T> | |||
| std::string ArrayToString(std::vector<T> array) { | |||
| std::string result; | |||
| std::for_each(array.begin(), array.end(), [&result](const T &t) { result += std::to_string(t) + ", "; }); | |||
| return "{" + result + "}"; | |||
| } | |||
| } // namespace mindspore::lite::micro | |||
| #endif // MINDSPORE_LITE_MICRO_CODER_UTILS_CODER_UTILS_H_ | |||