From 18a54baecbb75d7be2e80a4fc3e24218a321186c Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Tue, 2 Feb 2021 16:42:43 -0800 Subject: [PATCH 01/19] Create C-runtime-style metadata module for llvm builds. --- python/tvm/driver/build_module.py | 21 ++-- python/tvm/micro/compiler.py | 7 +- src/target/llvm/codegen_cpu.cc | 85 +++++++------- src/target/llvm/codegen_cpu.h | 6 + src/target/llvm/llvm_module.cc | 53 +++++++++ src/target/llvm/llvm_module.h | 39 +++++++ src/target/metadata_module.cc | 108 ++++++++++++++++++ src/target/metadata_module.h | 46 ++++++++ src/target/source/codegen_source_base.h | 5 +- src/target/source/source_module.cc | 84 ++------------ src/target/source/source_module.h | 46 ++++++++ tests/python/unittest/test_crt.py | 30 ++++- tests/python/unittest/test_link_params.py | 7 +- .../unittest/test_target_codegen_llvm.py | 28 +---- 14 files changed, 406 insertions(+), 159 deletions(-) create mode 100644 src/target/llvm/llvm_module.h create mode 100644 src/target/metadata_module.cc create mode 100644 src/target/metadata_module.h create mode 100644 src/target/source/source_module.h diff --git a/python/tvm/driver/build_module.py b/python/tvm/driver/build_module.py index 7ad48e19a1db..948b3cb10d3d 100644 --- a/python/tvm/driver/build_module.py +++ b/python/tvm/driver/build_module.py @@ -427,13 +427,16 @@ def build(inputs, args=None, target=None, target_host=None, name="default_functi if not isinstance(target_host, Target): target_host = Target(target_host) - if ( - "system-lib" in target_host.attrs - and target_host.attrs["system-lib"].value == 1 - and target_host.kind.name == "c" - ): - create_csource_metadata_module = tvm._ffi.get_global_func( - "runtime.CreateCSourceMetadataModule" - ) - return create_csource_metadata_module([rt_mod_host], target_host) + if "system-lib" in target_host.attrs and target_host.attrs["system-lib"].value == 1: + if target_host.kind.name == "c": + create_csource_crt_metadata_module = tvm._ffi.get_global_func( + "runtime.CreateCSourceCrtMetadataModule" + ) + return create_csource_crt_metadata_module([rt_mod_host], target_host) + elif target_host.kind.name == "llvm": + create_llvm_crt_metadata_module = tvm._ffi.get_global_func( + "runtime.CreateLLVMCrtMetadataModule" + ) + return create_llvm_crt_metadata_module([rt_mod_host], target_host) + return rt_mod_host diff --git a/python/tvm/micro/compiler.py b/python/tvm/micro/compiler.py index f59ac8dbc4a0..f5fb74854334 100644 --- a/python/tvm/micro/compiler.py +++ b/python/tvm/micro/compiler.py @@ -82,6 +82,10 @@ def _target_from_sources(cls, sources): target_strs = set() for obj in sources: + print("read", obj) + if os.path.splitext(obj)[1] not in (".cc", ".c"): + continue + with open(obj) as obj_f: for line in obj_f: m = cls.TVM_TARGET_RE.match(line) @@ -247,7 +251,8 @@ def library(self, output, sources, options=None): ) prefix = self._autodetect_toolchain_prefix(target) - outputs = [] + outputs = [s for s in sources if os.path.splitext(s)[1] == ".o"] + sources = [s for s in sources if s not in outputs] for src in sources: src_base, src_ext = os.path.splitext(os.path.basename(src)) diff --git a/src/target/llvm/codegen_cpu.cc b/src/target/llvm/codegen_cpu.cc index e2a8553199f0..b37cd73ece04 100644 --- a/src/target/llvm/codegen_cpu.cc +++ b/src/target/llvm/codegen_cpu.cc @@ -123,12 +123,6 @@ void CodeGenCPU::AddFunction(const PrimFunc& f) { << "CodeGenLLVM: Expect PrimFunc to have the global_symbol attribute"; export_system_symbols_.emplace_back( std::make_pair(global_symbol.value().operator std::string(), function_)); - } else if (target_c_runtime_) { - auto global_symbol = f->GetAttr(tvm::attr::kGlobalSymbol); - ICHECK(global_symbol.defined()) - << "CodeGenLLVM: Expect PrimFunc to have the global_symbol attribute"; - registry_functions_.emplace_back( - std::make_pair(global_symbol.value().operator std::string(), function_)); } AddDebugInformation(function_); } @@ -791,47 +785,50 @@ llvm::Value* CodeGenCPU::RuntimeTVMParallelBarrier() { return GetContextPtr(gv_tvm_parallel_barrier_); } -void CodeGenCPU::AddStartupFunction() { - if (registry_functions_.size() != 0) { - ICHECK(is_system_lib_) << "Loading of --system-lib modules is yet to be defined for C runtime"; - Array symbols; - std::vector funcs; - for (auto sym : registry_functions_) { - symbols.push_back(sym.first); - funcs.emplace_back(llvm::ConstantExpr::getBitCast( - sym.second, ftype_tvm_backend_packed_c_func_->getPointerTo())); - } - llvm::DataLayout layout(module_.get()); - llvm::ArrayType* t_tvm_crt_func_ptrs = - llvm::ArrayType::get(ftype_tvm_backend_packed_c_func_->getPointerTo(), funcs.size()); - llvm::GlobalVariable* func_registry_ptrs = new llvm::GlobalVariable( - *module_, t_tvm_crt_func_ptrs, true, llvm::GlobalValue::InternalLinkage, - llvm::ConstantArray::get(t_tvm_crt_func_ptrs, funcs), "_tvm_func_registry_ptrs"); - uint64_t align = layout.getTypeAllocSize(ftype_tvm_backend_packed_c_func_->getPointerTo()); +void CodeGenCPU::DefineFunctionRegistry(Array func_names) { + ICHECK(is_system_lib_) << "Loading of --system-lib modules is yet to be defined for C runtime"; + Array symbols; + std::vector funcs; + for (auto sym : func_names) { + symbols.push_back(sym); + llvm::GlobalVariable* sym_func = new llvm::GlobalVariable( + *module_, ftype_tvm_backend_packed_c_func_, true, llvm::GlobalValue::ExternalLinkage, + nullptr, sym.operator std::string()); + funcs.emplace_back(sym_func); + } + llvm::DataLayout layout(module_.get()); + llvm::ArrayType* t_tvm_crt_func_ptrs = + llvm::ArrayType::get(ftype_tvm_backend_packed_c_func_->getPointerTo(), funcs.size()); + llvm::GlobalVariable* func_registry_ptrs = new llvm::GlobalVariable( + *module_, t_tvm_crt_func_ptrs, true, llvm::GlobalValue::InternalLinkage, + llvm::ConstantArray::get(t_tvm_crt_func_ptrs, funcs), "_tvm_func_registry_ptrs"); + uint64_t align = layout.getTypeAllocSize(ftype_tvm_backend_packed_c_func_->getPointerTo()); #if TVM_LLVM_VERSION >= 100 - func_registry_ptrs->setAlignment(llvm::Align(align)); + func_registry_ptrs->setAlignment(llvm::Align(align)); #else - func_registry_ptrs->setAlignment(align); + func_registry_ptrs->setAlignment(align); #endif - llvm::GlobalVariable* func_registry = new llvm::GlobalVariable( - *module_, t_tvm_crt_func_registry_, true, llvm::GlobalVariable::InternalLinkage, - llvm::ConstantStruct::get( - t_tvm_crt_func_registry_, - {GetConstString(::tvm::target::GenerateFuncRegistryNames(symbols)), - func_registry_ptrs}), - "_tvm_crt_func_registry"); - llvm::GlobalVariable* module = new llvm::GlobalVariable( - *module_, t_tvm_crt_module_, true, llvm::GlobalValue::InternalLinkage, - llvm::ConstantStruct::get(t_tvm_crt_module_, {func_registry}), "_tvm_crt_module"); - - // Now build TVMSystemLibEntryPoint. - llvm::FunctionType* ftype = llvm::FunctionType::get(t_void_p_, {}, false); - function_ = llvm::Function::Create(ftype, llvm::Function::ExternalLinkage, - "TVMSystemLibEntryPoint", module_.get()); - llvm::BasicBlock* entry_point_entry = llvm::BasicBlock::Create(*ctx_, "entry", function_); - builder_->SetInsertPoint(entry_point_entry); - builder_->CreateRet(builder_->CreateBitCast(module, t_void_p_)); - } else { + llvm::GlobalVariable* func_registry = new llvm::GlobalVariable( + *module_, t_tvm_crt_func_registry_, true, llvm::GlobalVariable::InternalLinkage, + llvm::ConstantStruct::get( + t_tvm_crt_func_registry_, + {GetConstString(::tvm::target::GenerateFuncRegistryNames(symbols)), func_registry_ptrs}), + "_tvm_crt_func_registry"); + llvm::GlobalVariable* module = new llvm::GlobalVariable( + *module_, t_tvm_crt_module_, true, llvm::GlobalValue::InternalLinkage, + llvm::ConstantStruct::get(t_tvm_crt_module_, {func_registry}), "_tvm_crt_module"); + + // Now build TVMSystemLibEntryPoint. + llvm::FunctionType* ftype = llvm::FunctionType::get(t_void_p_, {}, false); + function_ = llvm::Function::Create(ftype, llvm::Function::ExternalLinkage, + "TVMSystemLibEntryPoint", module_.get()); + llvm::BasicBlock* entry_point_entry = llvm::BasicBlock::Create(*ctx_, "entry", function_); + builder_->SetInsertPoint(entry_point_entry); + builder_->CreateRet(builder_->CreateBitCast(module, t_void_p_)); +} + +void CodeGenCPU::AddStartupFunction() { + if (!target_c_runtime_) { llvm::FunctionType* ftype = llvm::FunctionType::get(t_void_, {}, false); function_ = llvm::Function::Create(ftype, llvm::Function::InternalLinkage, "__tvm_module_startup", module_.get()); diff --git a/src/target/llvm/codegen_cpu.h b/src/target/llvm/codegen_cpu.h index fc46dc53ce15..d08bd639e131 100644 --- a/src/target/llvm/codegen_cpu.h +++ b/src/target/llvm/codegen_cpu.h @@ -50,6 +50,12 @@ class CodeGenCPU : public CodeGenLLVM { llvm::Value* CreateCallExtern(Type ret_type, String global_symbol, const Array& args, bool skip_first_arg) override; + /*! + * \brief A CPU-specific function to create the FuncRegistry. + * \param func_names List of functions to be included, in order. + */ + void DefineFunctionRegistry(Array func_names); + protected: void AddStartupFunction() final; // meta data diff --git a/src/target/llvm/llvm_module.cc b/src/target/llvm/llvm_module.cc index 43d20971404e..24fb3dc95819 100644 --- a/src/target/llvm/llvm_module.cc +++ b/src/target/llvm/llvm_module.cc @@ -34,6 +34,7 @@ #include "../../runtime/library_module.h" #include "../func_registry_generator.h" #include "codegen_blob.h" +#include "codegen_cpu.h" #include "codegen_llvm.h" #include "llvm_common.h" @@ -445,6 +446,58 @@ TVM_REGISTER_GLOBAL("codegen.codegen_blob") return runtime::Module(n); }); +runtime::Module CreateLLVMCrtMetadataModule(const Array& modules, Target target) { + Array func_names; + for (runtime::Module mod : modules) { + auto pf_funcs = mod.GetFunction("get_func_names"); + if (pf_funcs != nullptr) { + Array func_names_ = pf_funcs(); + for (const auto& fname : func_names_) { + func_names.push_back(fname); + } + } + } + + InitializeLLVM(); + auto tm = GetLLVMTargetMachine(target); + bool system_lib = target->GetAttr("system-lib").value_or(Bool(false)); + bool target_c_runtime = (target->GetAttr("runtime").value_or("") == kTvmRuntimeCrt); + ICHECK(system_lib && target_c_runtime) + << "For LLVM C-runtime metadata module, must include --system-lib and --runtime=c; " + << "got target: " << target->str(); + auto ctx = std::make_shared(); + std::unique_ptr cg{new CodeGenCPU()}; + cg->Init("TVMMetadataMod", tm.get(), ctx.get(), system_lib, system_lib, target_c_runtime); + + cg->DefineFunctionRegistry(func_names); + auto mod = cg->Finish(); + mod->addModuleFlag(llvm::Module::Warning, "tvm_target", + llvm::MDString::get(*ctx, LLVMTargetToString(target))); + mod->addModuleFlag(llvm::Module::Override, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); + + if (tm->getTargetTriple().isOSDarwin()) { + mod->addModuleFlag(llvm::Module::Override, "Dwarf Version", 2); + } + + std::string verify_errors_storage; + llvm::raw_string_ostream verify_errors(verify_errors_storage); + LOG_IF(FATAL, llvm::verifyModule(*mod, &verify_errors)) + << "LLVM module verification failed with the following errors: \n" + << verify_errors.str(); + + auto n = make_object(); + n->Init(std::move(mod), ctx); + for (auto m : modules) { + n->Import(m); + } + return runtime::Module(n); +} + +TVM_REGISTER_GLOBAL("runtime.CreateLLVMCrtMetadataModule") + .set_body_typed([](const Array& modules, Target target) { + return CreateLLVMCrtMetadataModule(modules, target); + }); + } // namespace codegen } // namespace tvm #endif // TVM_LLVM_VERSION diff --git a/src/target/llvm/llvm_module.h b/src/target/llvm/llvm_module.h new file mode 100644 index 000000000000..0cdb33a7d6ec --- /dev/null +++ b/src/target/llvm/llvm_module.h @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/*! + * \file llvm_module.h + * \brief Declares top-level shared functions related to the LLVM codegen. + */ + +#include +#include +#include + +#ifdef TVM_LLVM_VERSION + +namespace tvm { +namespace codegen { + +runtime::Module CreateLLVMCrtMetadataModule(const Array& modules, Target target); + +} // namespace codegen +} // namespace tvm + +#endif // TVM_LLVM_VERSION diff --git a/src/target/metadata_module.cc b/src/target/metadata_module.cc new file mode 100644 index 000000000000..ff56f641baaf --- /dev/null +++ b/src/target/metadata_module.cc @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/*! + * \file metadata_module.cc + * \brief Defines functions that build MetadataModules for C++ and C runtimes. + */ + +#include "metadata_module.h" + +#include "../runtime/meta_data.h" +#include "llvm/llvm_module.h" +#include "source/source_module.h" + +namespace tvm { +namespace codegen { + +/*! + * \brief Create a metadata module wrapper. The helper is used by different + * codegens, such as graph runtime codegen and the vm compiler. + * + * \param params The metadata for initialization of all modules. + * \param target_module the internal module that is compiled by tvm. + * \param ext_modules The external modules that needs to be imported inside the metadata + * module(s). + * \param target The target that all the modules are compiled for + * \return The created metadata module that manages initialization of metadata. + */ +runtime::Module CreateMetadataModule( + const std::unordered_map& params, + tvm::runtime::Module target_module, const Array& ext_modules, Target target) { + Array csource_modules; + Array binary_modules; + + auto DSOExportable = [](tvm::runtime::Module& mod) { + return !std::strcmp(mod->type_key(), "llvm") || !std::strcmp(mod->type_key(), "c"); + }; + + // Wrap all submodules in the initialization wrapper. + std::unordered_map> sym_metadata; + for (tvm::runtime::Module mod : ext_modules) { + auto pf_sym = mod.GetFunction("get_symbol"); + auto pf_var = mod.GetFunction("get_const_vars"); + std::vector arrays; + if (pf_sym != nullptr && pf_var != nullptr) { + String symbol = pf_sym(); + Array variables = pf_var(); + for (size_t i = 0; i < variables.size(); i++) { + arrays.push_back(variables[i].operator std::string()); + } + ICHECK_EQ(sym_metadata.count(symbol), 0U) << "Found duplicated symbol: " << symbol; + sym_metadata[symbol] = arrays; + } + // We only need loading of serialized constant data + // if there are constants present and required by the + // runtime module to be initialized by the binary + // metadata module. If not rest of the modules are + // wrapped in c-source metadata module. + + // TODO(@manupa-arm) : we should be able to use csource_metadata + // if the variables are empty when all the runtime modules implement get_func_names + if (arrays.empty() && DSOExportable(mod) && target->kind->name == "c") { + csource_modules.push_back(mod); + } else { + binary_modules.push_back(mod); + } + } + + if (target.defined() && + target->GetAttr("runtime").value_or(String("")) == kTvmRuntimeCrt) { + if (target->kind->name == "c") { + csource_modules.push_back(target_module); + target_module = CreateCSourceCrtMetadataModule(csource_modules, target); + } else if (target->kind->name == "llvm") { + binary_modules.push_back(target_module); + target_module = CreateLLVMCrtMetadataModule(binary_modules, target); + } + } else { + if (!binary_modules.empty()) { + runtime::Module binary_meta_mod = runtime::MetadataModuleCreate(params, sym_metadata); + binary_meta_mod.Import(target_module); + for (const auto& it : binary_modules) { + binary_meta_mod.Import(it); + } + return binary_meta_mod; + } + } + return target_module; +} + +} // namespace codegen +} // namespace tvm diff --git a/src/target/metadata_module.h b/src/target/metadata_module.h new file mode 100644 index 000000000000..986ab92cea86 --- /dev/null +++ b/src/target/metadata_module.h @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/*! + * \file metadata_module.h + * \brief Declares functions that build MetadataModules for C++ and C runtimes. + */ + +#ifndef TVM_TARGET_METADATA_MODULE_H_ +#define TVM_TARGET_METADATA_MODULE_H_ + +#include +#include +#include +#include + +#include +#include + +namespace tvm { +namespace codegen { + +runtime::Module CreateMetadataModule( + const std::unordered_map& params, + tvm::runtime::Module target_module, const Array& ext_modules, Target target); + +} // namespace codegen +} // namespace tvm + +#endif diff --git a/src/target/source/codegen_source_base.h b/src/target/source/codegen_source_base.h index ed838f825812..3baa44eb639f 100644 --- a/src/target/source/codegen_source_base.h +++ b/src/target/source/codegen_source_base.h @@ -170,12 +170,13 @@ runtime::Module DeviceSourceModuleCreate( std::string type_key, std::function fget_source = nullptr); /*! - * \brief Wrap the submodules that are to be wrapped in a c-source metadata module. + * \brief Wrap the submodules that are to be wrapped in a c-source metadata module for C runtime. * \param modules The modules to be wrapped. * \param target the target the modules are compiled for. * \return The wrapped module. */ -runtime::Module CreateCSourceMetadataModule(const Array& modules, Target target); +runtime::Module CreateCSourceCrtMetadataModule(const Array& modules, + Target target); } // namespace codegen } // namespace tvm diff --git a/src/target/source/source_module.cc b/src/target/source/source_module.cc index 4b4770a79816..87e58199aab3 100644 --- a/src/target/source/source_module.cc +++ b/src/target/source/source_module.cc @@ -21,12 +21,13 @@ * \file source_module.cc * \brief Source code module, only for viewing */ +#include "source_module.h" + #include #include #include #include "../../runtime/file_utils.h" -#include "../../runtime/meta_data.h" #include "../../support/str_escape.h" #include "../func_registry_generator.h" #include "codegen_source_base.h" @@ -43,73 +44,6 @@ using runtime::GetFileFormat; using runtime::GetMetaFilePath; using runtime::SaveBinaryToFile; -/*! - * \brief Create a metadata module wrapper. The helper is used by different - * codegens, such as graph runtime codegen and the vm compiler. - * - * \param params The metadata for initialization of all modules. - * \param target_module the internal module that is compiled by tvm. - * \param ext_modules The external modules that needs to be imported inside the metadata - * module(s). - * \param target The target that all the modules are compiled for - * \return The created metadata module that manages initialization of metadata. - */ -runtime::Module CreateMetadataModule( - const std::unordered_map& params, - tvm::runtime::Module target_module, const Array& ext_modules, Target target) { - Array csource_modules; - Array binary_modules; - - auto DSOExportable = [](tvm::runtime::Module& mod) { - return !std::strcmp(mod->type_key(), "llvm") || !std::strcmp(mod->type_key(), "c"); - }; - - // Wrap all submodules in the initialization wrapper. - std::unordered_map> sym_metadata; - for (tvm::runtime::Module mod : ext_modules) { - auto pf_sym = mod.GetFunction("get_symbol"); - auto pf_var = mod.GetFunction("get_const_vars"); - std::vector arrays; - if (pf_sym != nullptr && pf_var != nullptr) { - String symbol = pf_sym(); - Array variables = pf_var(); - for (size_t i = 0; i < variables.size(); i++) { - arrays.push_back(variables[i].operator std::string()); - } - ICHECK_EQ(sym_metadata.count(symbol), 0U) << "Found duplicated symbol: " << symbol; - sym_metadata[symbol] = arrays; - } - // We only need loading of serialized constant data - // if there are constants present and required by the - // runtime module to be initialized by the binary - // metadata module. If not rest of the modules are - // wrapped in c-source metadata module. - - // TODO(@manupa-arm) : we should be able to use csource_metadata - // if the variables are empty when all the runtime modules implement get_func_names - if (arrays.empty() && DSOExportable(mod) && target->kind->name == "c") { - csource_modules.push_back(mod); - } else { - binary_modules.push_back(mod); - } - } - - if (target.defined() && target->kind->name == "c") { - csource_modules.push_back(target_module); - target_module = CreateCSourceMetadataModule(csource_modules, target); - } - - if (!binary_modules.empty()) { - runtime::Module binary_meta_mod = runtime::MetadataModuleCreate(params, sym_metadata); - binary_meta_mod.Import(target_module); - for (const auto& it : binary_modules) { - binary_meta_mod.Import(it); - } - return binary_meta_mod; - } - return target_module; -} - // Simulator function class SourceModuleNode : public runtime::ModuleNode { public: @@ -189,9 +123,10 @@ runtime::Module CSourceModuleCreate(const String& code, const String& fmt, return runtime::Module(n); } -class CSourceMetadataModuleNode : public runtime::ModuleNode { +class CSourceCrtMetadataModuleNode : public runtime::ModuleNode { public: - CSourceMetadataModuleNode(const Array& func_names, const std::string& fmt, Target target) + CSourceCrtMetadataModuleNode(const Array& func_names, const std::string& fmt, + Target target) : fmt_(fmt), func_names_(func_names), target_(target) { CreateSource(); } @@ -261,7 +196,8 @@ class CSourceMetadataModuleNode : public runtime::ModuleNode { } }; -runtime::Module CreateCSourceMetadataModule(const Array& modules, Target target) { +runtime::Module CreateCSourceCrtMetadataModule(const Array& modules, + Target target) { Array func_names; for (runtime::Module mod : modules) { auto pf_funcs = mod.GetFunction("get_func_names"); @@ -272,7 +208,7 @@ runtime::Module CreateCSourceMetadataModule(const Array& module } } } - auto n = make_object(func_names, "cc", target); + auto n = make_object(func_names, "cc", target); auto csrc_metadata_module = runtime::Module(n); for (const auto& mod : modules) { csrc_metadata_module.Import(mod); @@ -341,9 +277,9 @@ TVM_REGISTER_GLOBAL("runtime.CSourceModuleCreate") return CSourceModuleCreate(code, fmt, func_names, const_vars); }); -TVM_REGISTER_GLOBAL("runtime.CreateCSourceMetadataModule") +TVM_REGISTER_GLOBAL("runtime.CreateCSourceCrtMetadataModule") .set_body_typed([](const Array& modules, Target target) { - return CreateCSourceMetadataModule(modules, target); + return CreateCSourceCrtMetadataModule(modules, target); }); } // namespace codegen diff --git a/src/target/source/source_module.h b/src/target/source/source_module.h new file mode 100644 index 000000000000..45858b9f4ef2 --- /dev/null +++ b/src/target/source/source_module.h @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/*! + * \file source_module.h + * \brief Source code module + */ + +#ifndef TVM_TARGET_SOURCE_SOURCE_MODULE_H_ +#define TVM_TARGET_SOURCE_SOURCE_MODULE_H_ + +#include +#include +#include + +namespace tvm { +namespace codegen { + +/*! + * \brief Create C-runtime targeted metadata module for "c" backend. + * \param modules Array of modules included in the compilation output. + * \param target TVM target. + */ +runtime::Module CreateCSourceCrtMetadataModule(const Array& modules, + tvm::Target target); + +} // namespace codegen +} // namespace tvm + +#endif // TVM_TARGET_SOURCE_SOURCE_MODULE_H_ diff --git a/tests/python/unittest/test_crt.py b/tests/python/unittest/test_crt.py index 659d1908096b..9120facd213c 100644 --- a/tests/python/unittest/test_crt.py +++ b/tests/python/unittest/test_crt.py @@ -28,7 +28,6 @@ import pytest import tvm -import tvm.testing import tvm.relay import tvm.testing @@ -106,6 +105,20 @@ def test_compile_runtime(): assert (C_data.asnumpy() == np.array([6, 7])).all() +@tvm.testing.requires_micro +def test_compile_runtime_llvm(): + """Test targeting the on-device runtime with the llvm backend.""" + global TARGET + old_target = TARGET + try: + TARGET = tvm.target.Target("llvm " + str(TARGET)[2:]) + + test_compile_runtime() + + finally: + TARGET = old_target + + @tvm.testing.requires_micro def test_reset(): """Test when the remote end resets during a session.""" @@ -127,7 +140,7 @@ def test_graph_runtime(): """Test use of the graph runtime with microTVM.""" import tvm.micro - workspace = tvm.micro.Workspace() + workspace = tvm.micro.Workspace(debug=True) relay_mod = tvm.parser.fromtext( """ #[version = "0.0.5"] @@ -160,6 +173,19 @@ def test_std_math_functions(): """Verify that standard math functions can be used.""" import tvm.micro + workspace = tvm.micro.Workspace() + + with _make_add_sess(workspace) as sess: + A_data = tvm.nd.array(np.array([2, 3], dtype="int8"), ctx=sess.context) + assert (A_data.asnumpy() == np.array([2, 3])).all() + B_data = tvm.nd.array(np.array([4], dtype="int8"), ctx=sess.context) + assert (B_data.asnumpy() == np.array([4])).all() + C_data = tvm.nd.array(np.array([0, 0], dtype="int8"), ctx=sess.context) + assert (C_data.asnumpy() == np.array([0, 0])).all() + + system_lib = sess.get_system_lib() + system_lib.get_function("add")(A_data, B_data, C_data) + workspace = tvm.micro.Workspace() A = tvm.te.placeholder((2,), dtype="float32", name="A") B = tvm.te.compute(A.shape, lambda i: tvm.te.exp(A[i]), name="B") diff --git a/tests/python/unittest/test_link_params.py b/tests/python/unittest/test_link_params.py index 52d7a27838d7..f3d24111de65 100644 --- a/tests/python/unittest/test_link_params.py +++ b/tests/python/unittest/test_link_params.py @@ -188,9 +188,10 @@ def test_llvm_link_params(): target = "llvm --runtime=c --system-lib --link-params" with tvm.transform.PassContext(opt_level=3): lib = tvm.relay.build(mod, target, params=param_init) + print("mod", lib.lib.get_source()) assert set(lib.params.keys()) == {"p0", "p1"} # NOTE: op folded + assert lib.lib.get_function("TVMSystemLibEntryPoint") != None - print("graph", lib.graph_json) graph = json.loads(lib.graph_json) for p in lib.params: _verify_linked_param(dtype, lib, lib.lib, graph, p) or found_one @@ -266,8 +267,8 @@ def test_c_link_params(): lib = tvm.relay.build(mod, target, params=param_init) assert set(lib.params.keys()) == {"p0", "p1"} # NOTE: op folded - src = lib.lib.imported_modules[0].get_source() - lib.lib.save("test.c", "cc") + src = lib.lib.get_source() + lib.lib.save("test.c", "c") c_dtype = _get_c_datatype(dtype) src_lines = src.split("\n") param = lib.params["p0"].asnumpy().reshape(np.prod(KERNEL_SHAPE)) diff --git a/tests/python/unittest/test_target_codegen_llvm.py b/tests/python/unittest/test_target_codegen_llvm.py index 67c1f6bff429..ec7c5aea333f 100644 --- a/tests/python/unittest/test_target_codegen_llvm.py +++ b/tests/python/unittest/test_target_codegen_llvm.py @@ -17,6 +17,8 @@ import collections import ctypes import json +import sys + import tvm import tvm.testing from tvm import te @@ -26,6 +28,7 @@ import ctypes import math import re +import pytest @tvm.testing.requires_llvm @@ -816,27 +819,4 @@ def do_atomic_add(A): if __name__ == "__main__": - test_multiple_func() - test_llvm_large_uintimm() - test_llvm_import() - test_alignment() - test_rank_zero() - test_rank_zero_bound_checkers() - test_llvm_bool() - test_llvm_persist_parallel() - test_llvm_condition() - test_llvm_vadd_pipeline() - test_llvm_add_pipeline() - test_llvm_intrin() - test_llvm_overloaded_intrin() - test_llvm_flip_pipeline() - test_llvm_madd_pipeline() - test_llvm_temp_space() - test_llvm_lookup_intrin() - test_llvm_div() - test_llvm_fp_math() - test_dwarf_debug_information() - test_llvm_shuffle() - test_llvm_bf16() - test_llvm_crt_static_lib() - test_llvm_gpu_lower_atomic() + sys.exit(pytest.main([__file__] + sys.argv[1:])) From f4d4d778dc78a2f3220e30ecb21105ff3f8e8b51 Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Fri, 5 Feb 2021 14:07:56 -0800 Subject: [PATCH 02/19] maybe address manupa's comment --- src/target/metadata_module.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/target/metadata_module.cc b/src/target/metadata_module.cc index ff56f641baaf..1ed5e38c0b0a 100644 --- a/src/target/metadata_module.cc +++ b/src/target/metadata_module.cc @@ -75,7 +75,8 @@ runtime::Module CreateMetadataModule( // TODO(@manupa-arm) : we should be able to use csource_metadata // if the variables are empty when all the runtime modules implement get_func_names - if (arrays.empty() && DSOExportable(mod) && target->kind->name == "c") { + if (arrays.empty() && DSOExportable(mod) && + (target->kind->name == "c" || target->kind->name == "llvm")) { csource_modules.push_back(mod); } else { binary_modules.push_back(mod); @@ -88,8 +89,8 @@ runtime::Module CreateMetadataModule( csource_modules.push_back(target_module); target_module = CreateCSourceCrtMetadataModule(csource_modules, target); } else if (target->kind->name == "llvm") { - binary_modules.push_back(target_module); - target_module = CreateLLVMCrtMetadataModule(binary_modules, target); + csource_modules.push_back(target_module); + target_module = CreateLLVMCrtMetadataModule(csource_modules, target); } } else { if (!binary_modules.empty()) { From 48b005d08b017e63973d55bc857d2b6b666f5ec0 Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Fri, 5 Feb 2021 14:09:36 -0800 Subject: [PATCH 03/19] lint --- src/target/llvm/llvm_module.h | 5 +++++ src/target/metadata_module.cc | 2 ++ src/target/metadata_module.h | 2 +- src/target/source/source_module.cc | 4 ++++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/target/llvm/llvm_module.h b/src/target/llvm/llvm_module.h index 0cdb33a7d6ec..3eab00c643e5 100644 --- a/src/target/llvm/llvm_module.h +++ b/src/target/llvm/llvm_module.h @@ -22,6 +22,9 @@ * \brief Declares top-level shared functions related to the LLVM codegen. */ +#ifndef TVM_TARGET_LLVM_LLVM_MODULE_H_ +#define TVM_TARGET_LLVM_LLVM_MODULE_H_ + #include #include #include @@ -37,3 +40,5 @@ runtime::Module CreateLLVMCrtMetadataModule(const Array& module } // namespace tvm #endif // TVM_LLVM_VERSION + +#endif // TVM_TARGET_LLVM_LLVM_MODULE_H_ diff --git a/src/target/metadata_module.cc b/src/target/metadata_module.cc index 1ed5e38c0b0a..ee5720f6b607 100644 --- a/src/target/metadata_module.cc +++ b/src/target/metadata_module.cc @@ -24,6 +24,8 @@ #include "metadata_module.h" +#include + #include "../runtime/meta_data.h" #include "llvm/llvm_module.h" #include "source/source_module.h" diff --git a/src/target/metadata_module.h b/src/target/metadata_module.h index 986ab92cea86..83cb29dd5a46 100644 --- a/src/target/metadata_module.h +++ b/src/target/metadata_module.h @@ -43,4 +43,4 @@ runtime::Module CreateMetadataModule( } // namespace codegen } // namespace tvm -#endif +#endif // TVM_TARGET_METADATA_MODULE_H_ diff --git a/src/target/source/source_module.cc b/src/target/source/source_module.cc index 87e58199aab3..a83b8f9f5e46 100644 --- a/src/target/source/source_module.cc +++ b/src/target/source/source_module.cc @@ -23,6 +23,10 @@ */ #include "source_module.h" +#include +#include +#include + #include #include #include From eae7a69c45fd4a8e4b4330060c3ec41ebaa24aed Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Fri, 5 Feb 2021 18:04:11 -0800 Subject: [PATCH 04/19] actually address manupa comments --- src/target/metadata_module.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/target/metadata_module.cc b/src/target/metadata_module.cc index ee5720f6b607..f794438d5b8d 100644 --- a/src/target/metadata_module.cc +++ b/src/target/metadata_module.cc @@ -47,6 +47,8 @@ namespace codegen { runtime::Module CreateMetadataModule( const std::unordered_map& params, tvm::runtime::Module target_module, const Array& ext_modules, Target target) { + // Here we split modules into two groups: + // 1. Array csource_modules; Array binary_modules; @@ -87,6 +89,24 @@ runtime::Module CreateMetadataModule( if (target.defined() && target->GetAttr("runtime").value_or(String("")) == kTvmRuntimeCrt) { + if (!binary_modules.empty()) { + string non_exportable_modules; + for (int i = 0; i < binary_modules.size(); i++) { + if (i > 0) { + non_exportable_modules += ", "; + } + auto pf_sym = mod.GetFunction("get_symbol"); + if (pf_sym != nullptr) { + non_exportable_modules += pf_sym().operator std::string(); + } else { + non_exportable_modules.push_back(std::string{"(module type_key="} + m->type_); + } + } + CHECK(false) + << "These " << binary_modules.size() << " modules are not exportable to C-runtime: " + << non_exportable_modules; + } + if (target->kind->name == "c") { csource_modules.push_back(target_module); target_module = CreateCSourceCrtMetadataModule(csource_modules, target); From 87c7ca580f0f973348d84d2e5d8a3e97ad38bbfe Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Fri, 5 Feb 2021 18:19:39 -0800 Subject: [PATCH 05/19] comment and rename --- src/target/metadata_module.cc | 38 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/target/metadata_module.cc b/src/target/metadata_module.cc index f794438d5b8d..da80a9d6d1d2 100644 --- a/src/target/metadata_module.cc +++ b/src/target/metadata_module.cc @@ -48,9 +48,11 @@ runtime::Module CreateMetadataModule( const std::unordered_map& params, tvm::runtime::Module target_module, const Array& ext_modules, Target target) { // Here we split modules into two groups: - // 1. - Array csource_modules; - Array binary_modules; + // 1. Those modules which can be exported to C-runtime. These are DSO-exportable + // (i.e. llvm or c) modules which return nothing from get_const_vars(). + // 2. Other modules. + Array crt_exportable_modules; + Array non_crt_exportable_modules; auto DSOExportable = [](tvm::runtime::Module& mod) { return !std::strcmp(mod->type_key(), "llvm") || !std::strcmp(mod->type_key(), "c"); @@ -81,44 +83,46 @@ runtime::Module CreateMetadataModule( // if the variables are empty when all the runtime modules implement get_func_names if (arrays.empty() && DSOExportable(mod) && (target->kind->name == "c" || target->kind->name == "llvm")) { - csource_modules.push_back(mod); + crt_exportable_modules.push_back(mod); } else { - binary_modules.push_back(mod); + non_crt_exportable_modules.push_back(mod); } } if (target.defined() && target->GetAttr("runtime").value_or(String("")) == kTvmRuntimeCrt) { - if (!binary_modules.empty()) { - string non_exportable_modules; - for (int i = 0; i < binary_modules.size(); i++) { + if (!non_crt_exportable_modules.empty()) { + std::string non_exportable_modules; + for (int i = 0; i < non_crt_exportable_modules.size(); i++) { if (i > 0) { non_exportable_modules += ", "; } + auto mod = non_crt_exportable_modules[i]; auto pf_sym = mod.GetFunction("get_symbol"); if (pf_sym != nullptr) { non_exportable_modules += pf_sym().operator std::string(); } else { - non_exportable_modules.push_back(std::string{"(module type_key="} + m->type_); + non_exportable_modules += + std::string{"(module type_key="} + mod->type_key() + std::string{")"}; } } CHECK(false) - << "These " << binary_modules.size() << " modules are not exportable to C-runtime: " - << non_exportable_modules; + << "These " << non_crt_exportable_modules.size() + << " modules are not exportable to C-runtime: " << non_exportable_modules; } if (target->kind->name == "c") { - csource_modules.push_back(target_module); - target_module = CreateCSourceCrtMetadataModule(csource_modules, target); + crt_exportable_modules.push_back(target_module); + target_module = CreateCSourceCrtMetadataModule(crt_exportable_modules, target); } else if (target->kind->name == "llvm") { - csource_modules.push_back(target_module); - target_module = CreateLLVMCrtMetadataModule(csource_modules, target); + crt_exportable_modules.push_back(target_module); + target_module = CreateLLVMCrtMetadataModule(crt_exportable_modules, target); } } else { - if (!binary_modules.empty()) { + if (!non_crt_exportable_modules.empty()) { runtime::Module binary_meta_mod = runtime::MetadataModuleCreate(params, sym_metadata); binary_meta_mod.Import(target_module); - for (const auto& it : binary_modules) { + for (const auto& it : non_crt_exportable_modules) { binary_meta_mod.Import(it); } return binary_meta_mod; From aa89625f98b6773dd468b777690f2849a292753e Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Fri, 5 Feb 2021 18:19:53 -0800 Subject: [PATCH 06/19] git-clang-format --- src/target/metadata_module.cc | 7 +++---- src/target/source/source_module.cc | 8 ++++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/target/metadata_module.cc b/src/target/metadata_module.cc index da80a9d6d1d2..c14aab0c3255 100644 --- a/src/target/metadata_module.cc +++ b/src/target/metadata_module.cc @@ -103,12 +103,11 @@ runtime::Module CreateMetadataModule( non_exportable_modules += pf_sym().operator std::string(); } else { non_exportable_modules += - std::string{"(module type_key="} + mod->type_key() + std::string{")"}; + std::string{"(module type_key="} + mod->type_key() + std::string{")"}; } } - CHECK(false) - << "These " << non_crt_exportable_modules.size() - << " modules are not exportable to C-runtime: " << non_exportable_modules; + CHECK(false) << "These " << non_crt_exportable_modules.size() + << " modules are not exportable to C-runtime: " << non_exportable_modules; } if (target->kind->name == "c") { diff --git a/src/target/source/source_module.cc b/src/target/source/source_module.cc index a83b8f9f5e46..a7732719a699 100644 --- a/src/target/source/source_module.cc +++ b/src/target/source/source_module.cc @@ -23,14 +23,14 @@ */ #include "source_module.h" -#include -#include -#include - #include #include #include +#include +#include +#include + #include "../../runtime/file_utils.h" #include "../../support/str_escape.h" #include "../func_registry_generator.h" From fd651da731e89dc7a9067f2c128cde96650fca2d Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Mon, 8 Feb 2021 14:50:54 -0800 Subject: [PATCH 07/19] pylint --- python/tvm/driver/build_module.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/tvm/driver/build_module.py b/python/tvm/driver/build_module.py index 948b3cb10d3d..e7a3ed50c848 100644 --- a/python/tvm/driver/build_module.py +++ b/python/tvm/driver/build_module.py @@ -433,7 +433,8 @@ def build(inputs, args=None, target=None, target_host=None, name="default_functi "runtime.CreateCSourceCrtMetadataModule" ) return create_csource_crt_metadata_module([rt_mod_host], target_host) - elif target_host.kind.name == "llvm": + + if target_host.kind.name == "llvm": create_llvm_crt_metadata_module = tvm._ffi.get_global_func( "runtime.CreateLLVMCrtMetadataModule" ) From 567407a4f8d777ca719f6a7dc75d5ec8817dc9cc Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Mon, 8 Feb 2021 15:20:23 -0800 Subject: [PATCH 08/19] cpp warning --- src/target/metadata_module.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/metadata_module.cc b/src/target/metadata_module.cc index c14aab0c3255..1eeaaba95dc1 100644 --- a/src/target/metadata_module.cc +++ b/src/target/metadata_module.cc @@ -93,7 +93,7 @@ runtime::Module CreateMetadataModule( target->GetAttr("runtime").value_or(String("")) == kTvmRuntimeCrt) { if (!non_crt_exportable_modules.empty()) { std::string non_exportable_modules; - for (int i = 0; i < non_crt_exportable_modules.size(); i++) { + for (unsigned int i = 0; i < non_crt_exportable_modules.size(); i++) { if (i > 0) { non_exportable_modules += ", "; } From 5f8b4a2c58ebca888a1b335565390b634210cd74 Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Tue, 9 Feb 2021 17:49:19 -0800 Subject: [PATCH 09/19] try to fix apps/bundle_deploy --- apps/bundle_deploy/Makefile | 19 +++++++++++++------ apps/bundle_deploy/build_model.py | 5 +++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/apps/bundle_deploy/Makefile b/apps/bundle_deploy/Makefile index 8a5f1cf95571..38d9d3456d55 100644 --- a/apps/bundle_deploy/Makefile +++ b/apps/bundle_deploy/Makefile @@ -62,6 +62,9 @@ $(endif) CRT_SRCS = $(shell find $(CRT_ROOT)) +MODEL_OBJ = $(build_dir)/model_c/devc.o $(build_dir)/model_c/lib0.o $(build_dir)/model_c/lib1.o +TEST_MODEL_OBJ = $(build_dir)/test_model_c/devc.o $(build_dir)/test_model_c/lib0.o $(build_dir)/test_model_c/lib1.o + demo_dynamic: $(build_dir)/demo_dynamic $(build_dir)/bundle.so $(build_dir)/bundle_c.so $(build_dir)/bundle.so $(build_dir)/graph_cpp.json $(build_dir)/graph_c.json $(build_dir)/params_cpp.bin $(build_dir)/params_c.bin $(build_dir)/cat.bin $(QUIET)TVM_NUM_THREADS=1 $(build_dir)/demo_dynamic $(build_dir)/bundle.so $(build_dir)/graph_cpp.json $(build_dir)/params_cpp.bin $(build_dir)/cat.bin $(QUIET)TVM_NUM_THREADS=1 $(build_dir)/demo_dynamic $(build_dir)/bundle_c.so $(build_dir)/graph_c.json $(build_dir)/params_c.bin $(build_dir)/cat.bin @@ -93,11 +96,11 @@ $(build_dir)/test_dynamic: test.cc ${build_dir}/test_graph_c.json ${build_dir}/t $(QUIET)mkdir -p $(@D) $(QUIET)g++ $(PKG_CXXFLAGS) -o $@ test.cc $(BACKTRACE_OBJS) $(BACKTRACE_LDFLAGS) -$(build_dir)/demo_static: demo_static.c ${build_dir}/bundle_static.o ${build_dir}/model_c.o ${build_dir}/crt/libmemory.a ${build_dir}/crt/libgraph_runtime.a ${build_dir}/crt/libcommon.a ${build_dir}/graph_c.json.c ${build_dir}/params_c.bin.c $(BACKTRACE_OBJS) +$(build_dir)/demo_static: demo_static.c ${build_dir}/bundle_static.o $(MODEL_OBJ) ${build_dir}/crt/libmemory.a ${build_dir}/crt/libgraph_runtime.a ${build_dir}/crt/libcommon.a ${build_dir}/graph_c.json.c ${build_dir}/params_c.bin.c $(BACKTRACE_OBJS) $(QUIET)mkdir -p $(@D) $(QUIET)gcc $(PKG_CFLAGS) -o $@ $^ $(PKG_LDFLAGS) $(BACKTRACE_LDFLAGS) $(BACKTRACE_CFLAGS) -$(build_dir)/test_static: test_static.c ${build_dir}/bundle_static.o ${build_dir}/test_model_c.o ${build_dir}/crt/libmemory.a ${build_dir}/crt/libgraph_runtime.a ${build_dir}/crt/libcommon.a $(BACKTRACE_OBJS) +$(build_dir)/test_static: test_static.c ${build_dir}/bundle_static.o $(TEST_MODEL_OBJ) ${build_dir}/crt/libmemory.a ${build_dir}/crt/libgraph_runtime.a ${build_dir}/crt/libcommon.a $(BACKTRACE_OBJS) $(QUIET)mkdir -p $(@D) $(QUIET)gcc $(PKG_CFLAGS) -o $@ $^ $(BACKTRACE_LDFLAGS) @@ -119,11 +122,15 @@ $(build_dir)/params_c.bin.c: $(build_dir)/params_c.bin $(build_dir)/params_cpp.bin.c: $(build_dir)/params_cpp.bin $(QUIET)xxd -i $^ > $@ -$(build_dir)/model_c.o $(build_dir)/graph_c.json $(build_dir)/model_cpp.o $(build_dir)/graph_cpp.json $(build_dir)/params.bin $(build_dir)/cat.bin: build_model.py +$(MODEL_OBJ) $(build_dir)/graph_c.json $(build_dir)/model_cpp.o $(build_dir)/graph_cpp.json $(build_dir)/params.bin $(build_dir)/cat.bin: build_model.py $(QUIET)python3 $< -o $(build_dir) + $(QUIET)mkdir -p build/model_c + $(QUIET)tar -C build/model_c -xvf build/model_c.tar -$(build_dir)/test_model_c.o $(build_dir)/test_graph_c.json $(build_dir)/test_params_c.bin $(build_dir)/test_data_c.bin $(build_dir)/test_output_c.bin $(build_dir)/test_model_cpp.o $(build_dir)/test_graph_cpp.json $(build_dir)/test_params_cpp.bin $(build_dir)/test_data_cpp.bin $(build_dir)/test_output_cpp.bin: build_model.py +$(TEST_MODEL_OBJ) $(build_dir)/test_graph_c.json $(build_dir)/test_params_c.bin $(build_dir)/test_data_c.bin $(build_dir)/test_output_c.bin $(build_dir)/test_model_cpp.o $(build_dir)/test_graph_cpp.json $(build_dir)/test_params_cpp.bin $(build_dir)/test_data_cpp.bin $(build_dir)/test_output_cpp.bin: build_model.py $(QUIET)python3 $< -o $(build_dir) --test + $(QUIET)mkdir -p build/test_model_c + $(QUIET)tar -C build/test_model_c -xvf build/test_model_c.tar # Build our bundle against the serialized bundle.c API, the runtime.cc API, and # the serialized graph.json and params.bin @@ -131,7 +138,7 @@ $(build_dir)/bundle.so: bundle.cc runtime.cc $(build_dir)/model_cpp.o $(QUIET)mkdir -p $(@D) $(QUIET)g++ -shared $(PKG_CXXFLAGS) -fvisibility=hidden -o $@ $^ $(PKG_LDFLAGS) -$(build_dir)/bundle_c.so: bundle.c $(build_dir)/model_c.o ${build_dir}/crt/libmemory.a ${build_dir}/crt/libgraph_runtime.a ${build_dir}/crt/libcommon.a $(BACKTRACE_OBJS) +$(build_dir)/bundle_c.so: bundle.c $(MODEL_OBJ) ${build_dir}/crt/libmemory.a ${build_dir}/crt/libgraph_runtime.a ${build_dir}/crt/libcommon.a $(BACKTRACE_OBJS) $(QUIET)mkdir -p $(@D) $(QUIET)gcc -shared $(PKG_CFLAGS) -fvisibility=hidden -o $@ $^ $(PKG_LDFLAGS) $(BACKTRACE_LDFLAGS) $(BACKTRACE_CFLAGS) @@ -139,7 +146,7 @@ $(build_dir)/test_bundle.so: bundle.cc runtime.cc $(build_dir)/test_model_cpp.o $(QUIET)mkdir -p $(@D) $(QUIET)g++ -shared $(PKG_CXXFLAGS) -fvisibility=hidden -o $@ $^ $(PKG_LDFLAGS) -$(build_dir)/test_bundle_c.so: bundle.c $(build_dir)/test_model_c.o ${build_dir}/crt/libmemory.a ${build_dir}/crt/libgraph_runtime.a ${build_dir}/crt/libcommon.a $(BACKTRACE_OBJS) +$(build_dir)/test_bundle_c.so: bundle.c $(TEST_MODEL_OBJ) ${build_dir}/crt/libmemory.a ${build_dir}/crt/libgraph_runtime.a ${build_dir}/crt/libcommon.a $(BACKTRACE_OBJS) $(QUIET)mkdir -p $(@D) $(QUIET)gcc -shared $(PKG_CFLAGS) -fvisibility=hidden -o $@ $^ $(PKG_LDFLAGS) $(BACKTRACE_LDFLAGS) $(BACKTRACE_CFLAGS) diff --git a/apps/bundle_deploy/build_model.py b/apps/bundle_deploy/build_model.py index a2513c8a46d0..24ee6036fb9c 100644 --- a/apps/bundle_deploy/build_model.py +++ b/apps/bundle_deploy/build_model.py @@ -51,7 +51,8 @@ def build_module(opts): build_dir = os.path.abspath(opts.out_dir) if not os.path.isdir(build_dir): os.makedirs(build_dir) - lib.save(os.path.join(build_dir, file_format_str.format(name="model", ext="o"))) + ext = 'tar' if runtime_name == 'c' else 'o' + lib.export_library(os.path.join(build_dir, file_format_str.format(name="model", ext=ext))) with open( os.path.join(build_dir, file_format_str.format(name="graph", ext="json")), "w" ) as f_graph_json: @@ -84,7 +85,7 @@ def build_test_module(opts): build_dir = os.path.abspath(opts.out_dir) if not os.path.isdir(build_dir): os.makedirs(build_dir) - lib.save(os.path.join(build_dir, file_format_str.format(name="test_model", ext="o"))) + lib.export_library(os.path.join(build_dir, file_format_str.format(name="test_model", ext="tar"))) with open( os.path.join(build_dir, file_format_str.format(name="test_graph", ext="json")), "w" ) as f_graph_json: From 2b53a106ee036aec58dd9741e1b67edd4f42a1eb Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Tue, 9 Feb 2021 21:57:17 -0800 Subject: [PATCH 10/19] black format --- apps/bundle_deploy/build_model.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/bundle_deploy/build_model.py b/apps/bundle_deploy/build_model.py index 24ee6036fb9c..bd178b7f8d0e 100644 --- a/apps/bundle_deploy/build_model.py +++ b/apps/bundle_deploy/build_model.py @@ -51,7 +51,7 @@ def build_module(opts): build_dir = os.path.abspath(opts.out_dir) if not os.path.isdir(build_dir): os.makedirs(build_dir) - ext = 'tar' if runtime_name == 'c' else 'o' + ext = "tar" if runtime_name == "c" else "o" lib.export_library(os.path.join(build_dir, file_format_str.format(name="model", ext=ext))) with open( os.path.join(build_dir, file_format_str.format(name="graph", ext="json")), "w" @@ -85,7 +85,9 @@ def build_test_module(opts): build_dir = os.path.abspath(opts.out_dir) if not os.path.isdir(build_dir): os.makedirs(build_dir) - lib.export_library(os.path.join(build_dir, file_format_str.format(name="test_model", ext="tar"))) + lib.export_library( + os.path.join(build_dir, file_format_str.format(name="test_model", ext="tar")) + ) with open( os.path.join(build_dir, file_format_str.format(name="test_graph", ext="json")), "w" ) as f_graph_json: From 67fc137dbff6420f3658e1d0bd6b257b62f0b18b Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Wed, 10 Feb 2021 10:09:29 -0800 Subject: [PATCH 11/19] build correct file --- apps/bundle_deploy/build_model.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/bundle_deploy/build_model.py b/apps/bundle_deploy/build_model.py index bd178b7f8d0e..51f7b8279ff0 100644 --- a/apps/bundle_deploy/build_model.py +++ b/apps/bundle_deploy/build_model.py @@ -85,8 +85,9 @@ def build_test_module(opts): build_dir = os.path.abspath(opts.out_dir) if not os.path.isdir(build_dir): os.makedirs(build_dir) + ext = "tar" if runtime_name == "c" else "o" lib.export_library( - os.path.join(build_dir, file_format_str.format(name="test_model", ext="tar")) + os.path.join(build_dir, file_format_str.format(name="test_model", ext=ext)) ) with open( os.path.join(build_dir, file_format_str.format(name="test_graph", ext="json")), "w" From d026b074c3d14cd54bdc48b8ce90975601a51cd7 Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Fri, 12 Feb 2021 14:16:25 -0800 Subject: [PATCH 12/19] Use save() for C++-runtime targeted artifacts. --- apps/bundle_deploy/build_model.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/apps/bundle_deploy/build_model.py b/apps/bundle_deploy/build_model.py index 51f7b8279ff0..0991ac9ad94b 100644 --- a/apps/bundle_deploy/build_model.py +++ b/apps/bundle_deploy/build_model.py @@ -23,6 +23,7 @@ from tvm import te import logging import json +from tvm.contrib import cc as _cc RUNTIMES = { "c": "{name}_c.{ext}", @@ -52,7 +53,16 @@ def build_module(opts): if not os.path.isdir(build_dir): os.makedirs(build_dir) ext = "tar" if runtime_name == "c" else "o" - lib.export_library(os.path.join(build_dir, file_format_str.format(name="model", ext=ext))) + lib_file_name = os.path.join(build_dir, file_format_str.format(name="model", ext=ext)) + if runtime_name == "c": + lib.export_library(lib_file_name) + else: + # NOTE: at present, export_libarary will always create _another_ shared object, and you + # can't stably combine two shared objects together (in this case, init_array is not + # populated correctly when you do that). So for now, must continue to use save() with the + # C++ library. + # TODO(areusch): Obliterate runtime.cc and replace with libtvm_runtime.so. + lib.save(lib_file_name) with open( os.path.join(build_dir, file_format_str.format(name="graph", ext="json")), "w" ) as f_graph_json: @@ -86,9 +96,16 @@ def build_test_module(opts): if not os.path.isdir(build_dir): os.makedirs(build_dir) ext = "tar" if runtime_name == "c" else "o" - lib.export_library( - os.path.join(build_dir, file_format_str.format(name="test_model", ext=ext)) - ) + lib_file_name = os.path.join(build_dir, file_format_str.format(name="test_model", ext=ext)) + if runtime_name == "c": + lib.export_library(lib_file_name) + else: + # NOTE: at present, export_libarary will always create _another_ shared object, and you + # can't stably combine two shared objects together (in this case, init_array is not + # populated correctly when you do that). So for now, must continue to use save() with the + # C++ library. + # TODO(areusch): Obliterate runtime.cc and replace with libtvm_runtime.so. + lib.save(lib_file_name) with open( os.path.join(build_dir, file_format_str.format(name="test_graph", ext="json")), "w" ) as f_graph_json: From 461cb2634fafb4301af9ea34fd56a7ff73578c7a Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Tue, 16 Feb 2021 14:50:07 -0800 Subject: [PATCH 13/19] fix build_module LLVM metadata module conditions --- python/tvm/driver/build_module.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/tvm/driver/build_module.py b/python/tvm/driver/build_module.py index e7a3ed50c848..dd58231877d5 100644 --- a/python/tvm/driver/build_module.py +++ b/python/tvm/driver/build_module.py @@ -427,7 +427,8 @@ def build(inputs, args=None, target=None, target_host=None, name="default_functi if not isinstance(target_host, Target): target_host = Target(target_host) - if "system-lib" in target_host.attrs and target_host.attrs["system-lib"].value == 1: + if (target_host.attrs.get("runtime", tvm.runtime.String("c++")) == "c" and + target_host.attrs.get("system-lib", 0).value == 1): if target_host.kind.name == "c": create_csource_crt_metadata_module = tvm._ffi.get_global_func( "runtime.CreateCSourceCrtMetadataModule" From 470851ab8ce4ca804f76b472613278c6767fac63 Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Tue, 16 Feb 2021 15:35:34 -0800 Subject: [PATCH 14/19] fix test comment --- tests/python/unittest/test_crt.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/python/unittest/test_crt.py b/tests/python/unittest/test_crt.py index f6d9c87a5e83..dd329005c66f 100644 --- a/tests/python/unittest/test_crt.py +++ b/tests/python/unittest/test_crt.py @@ -108,7 +108,10 @@ def test_compile_runtime_llvm(): global TARGET old_target = TARGET try: - TARGET = tvm.target.Target("llvm " + str(TARGET)[2:]) + # NOTE: test_compile_runtime uses the "c" backend--re run it using the llvm backend. + target_str = str(TARGET) + assert target_str.startswith("c ") + TARGET = tvm.target.Target("llvm " + str(TARGET)[len("c "):]) test_compile_runtime() From 7a3be65937b06009d1fca561a0a0d611e005cb58 Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Tue, 16 Feb 2021 15:36:22 -0800 Subject: [PATCH 15/19] black format --- python/tvm/driver/build_module.py | 6 ++++-- tests/python/unittest/test_crt.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/python/tvm/driver/build_module.py b/python/tvm/driver/build_module.py index dd58231877d5..5eaecb422163 100644 --- a/python/tvm/driver/build_module.py +++ b/python/tvm/driver/build_module.py @@ -427,8 +427,10 @@ def build(inputs, args=None, target=None, target_host=None, name="default_functi if not isinstance(target_host, Target): target_host = Target(target_host) - if (target_host.attrs.get("runtime", tvm.runtime.String("c++")) == "c" and - target_host.attrs.get("system-lib", 0).value == 1): + if ( + target_host.attrs.get("runtime", tvm.runtime.String("c++")) == "c" + and target_host.attrs.get("system-lib", 0).value == 1 + ): if target_host.kind.name == "c": create_csource_crt_metadata_module = tvm._ffi.get_global_func( "runtime.CreateCSourceCrtMetadataModule" diff --git a/tests/python/unittest/test_crt.py b/tests/python/unittest/test_crt.py index dd329005c66f..4b744b8ee10a 100644 --- a/tests/python/unittest/test_crt.py +++ b/tests/python/unittest/test_crt.py @@ -111,7 +111,7 @@ def test_compile_runtime_llvm(): # NOTE: test_compile_runtime uses the "c" backend--re run it using the llvm backend. target_str = str(TARGET) assert target_str.startswith("c ") - TARGET = tvm.target.Target("llvm " + str(TARGET)[len("c "):]) + TARGET = tvm.target.Target("llvm " + str(TARGET)[len("c ") :]) test_compile_runtime() From 7ef66ef41bc0f8cb49531e31d4264a4caa1268bc Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Wed, 17 Feb 2021 09:28:43 -0800 Subject: [PATCH 16/19] further restrict CRT MetadataModule creation --- src/target/metadata_module.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/target/metadata_module.cc b/src/target/metadata_module.cc index 1eeaaba95dc1..e2575c34d8f2 100644 --- a/src/target/metadata_module.cc +++ b/src/target/metadata_module.cc @@ -58,6 +58,9 @@ runtime::Module CreateMetadataModule( return !std::strcmp(mod->type_key(), "llvm") || !std::strcmp(mod->type_key(), "c"); }; + bool is_targeting_crt = + target.defined() && target->GetAttr("runtime").value_or(String("")) == kTvmRuntimeCrt; + // Wrap all submodules in the initialization wrapper. std::unordered_map> sym_metadata; for (tvm::runtime::Module mod : ext_modules) { @@ -81,7 +84,7 @@ runtime::Module CreateMetadataModule( // TODO(@manupa-arm) : we should be able to use csource_metadata // if the variables are empty when all the runtime modules implement get_func_names - if (arrays.empty() && DSOExportable(mod) && + if (arrays.empty() && is_targeting_crt && DSOExportable(mod) && (target->kind->name == "c" || target->kind->name == "llvm")) { crt_exportable_modules.push_back(mod); } else { @@ -89,8 +92,7 @@ runtime::Module CreateMetadataModule( } } - if (target.defined() && - target->GetAttr("runtime").value_or(String("")) == kTvmRuntimeCrt) { + if (is_targeting_crt) { if (!non_crt_exportable_modules.empty()) { std::string non_exportable_modules; for (unsigned int i = 0; i < non_crt_exportable_modules.size(); i++) { From aed8ebca65a31757fb17e66a1365340d722f29c5 Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Wed, 17 Feb 2021 16:48:44 -0800 Subject: [PATCH 17/19] Fix test_link_params --- tests/python/unittest/test_link_params.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/python/unittest/test_link_params.py b/tests/python/unittest/test_link_params.py index a59453686a2f..24149e8b8265 100644 --- a/tests/python/unittest/test_link_params.py +++ b/tests/python/unittest/test_link_params.py @@ -21,6 +21,7 @@ import re import struct import sys +import tempfile import numpy as np import pytest @@ -188,23 +189,29 @@ def test_llvm_link_params(): target = "llvm --runtime=c --system-lib --link-params" with tvm.transform.PassContext(opt_level=3): lib = tvm.relay.build(mod, target, params=param_init) - print("mod", lib.lib.get_source()) + + # NOTE: Need to export_library() and load_library() to link all the Module(llvm, ...) + # against one another. + temp_dir = tempfile.mkdtemp() + export_file = os.path.join(temp_dir, 'lib.so') + lib.lib.export_library(export_file) + mod = tvm.runtime.load_module(export_file) assert set(lib.params.keys()) == {"p0", "p1"} # NOTE: op folded - assert lib.lib.get_function("TVMSystemLibEntryPoint") != None + assert mod.get_function("TVMSystemLibEntryPoint") != None graph = json.loads(lib.graph_json) for p in lib.params: - _verify_linked_param(dtype, lib, lib.lib, graph, p) or found_one + _verify_linked_param(dtype, lib, mod, graph, p) or found_one # Wrap in function to explicitly deallocate the runtime. - def _run_linked(lib): - graph_json, mod, _ = lib + def _run_linked(lib, mod): + graph_json, _, _ = lib graph_rt = tvm.contrib.graph_runtime.create(graph_json, mod, tvm.cpu(0)) graph_rt.set_input("rand_input", rand_input) # NOTE: params not required. graph_rt.run() return graph_rt.get_output(0) - linked_output = _run_linked(lib) + linked_output = _run_linked(lib, mod) with tvm.transform.PassContext(opt_level=3): lib = tvm.relay.build(mod, "llvm --system-lib", params=param_init) From 6c508f2729f503745657cebda95a98023c5d117f Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Thu, 18 Feb 2021 08:15:40 -0800 Subject: [PATCH 18/19] black format and address zhiics comments --- python/tvm/micro/compiler.py | 1 - tests/python/unittest/test_link_params.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/python/tvm/micro/compiler.py b/python/tvm/micro/compiler.py index a315bf14abf6..5bc5aba8a1be 100644 --- a/python/tvm/micro/compiler.py +++ b/python/tvm/micro/compiler.py @@ -81,7 +81,6 @@ def _target_from_sources(cls, sources): target_strs = set() for obj in sources: - print("read", obj) if os.path.splitext(obj)[1] not in (".cc", ".c"): continue diff --git a/tests/python/unittest/test_link_params.py b/tests/python/unittest/test_link_params.py index 24149e8b8265..0615d965beb9 100644 --- a/tests/python/unittest/test_link_params.py +++ b/tests/python/unittest/test_link_params.py @@ -193,7 +193,7 @@ def test_llvm_link_params(): # NOTE: Need to export_library() and load_library() to link all the Module(llvm, ...) # against one another. temp_dir = tempfile.mkdtemp() - export_file = os.path.join(temp_dir, 'lib.so') + export_file = os.path.join(temp_dir, "lib.so") lib.lib.export_library(export_file) mod = tvm.runtime.load_module(export_file) assert set(lib.params.keys()) == {"p0", "p1"} # NOTE: op folded From ce38ed10e873df511288e43db55caf08d3f57cca Mon Sep 17 00:00:00 2001 From: Andrew Reusch Date: Thu, 18 Feb 2021 08:54:30 -0800 Subject: [PATCH 19/19] fix test_link_params, i think? --- tests/python/unittest/test_link_params.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/python/unittest/test_link_params.py b/tests/python/unittest/test_link_params.py index 0615d965beb9..ffe859927ad7 100644 --- a/tests/python/unittest/test_link_params.py +++ b/tests/python/unittest/test_link_params.py @@ -183,12 +183,12 @@ def _add_decl(name, dtype): @tvm.testing.requires_llvm def test_llvm_link_params(): for dtype in LINKABLE_DTYPES: - mod, param_init = _make_mod_and_params(dtype) + ir_mod, param_init = _make_mod_and_params(dtype) rand_input = _make_random_tensor(dtype, INPUT_SHAPE) - main_func = mod["main"] + main_func = ir_mod["main"] target = "llvm --runtime=c --system-lib --link-params" with tvm.transform.PassContext(opt_level=3): - lib = tvm.relay.build(mod, target, params=param_init) + lib = tvm.relay.build(ir_mod, target, params=param_init) # NOTE: Need to export_library() and load_library() to link all the Module(llvm, ...) # against one another. @@ -214,7 +214,7 @@ def _run_linked(lib, mod): linked_output = _run_linked(lib, mod) with tvm.transform.PassContext(opt_level=3): - lib = tvm.relay.build(mod, "llvm --system-lib", params=param_init) + lib = tvm.relay.build(ir_mod, "llvm --system-lib", params=param_init) def _run_unlinked(lib): graph_json, mod, lowered_params = lib