It seems to me relay.build() and tvm.build() are processed through completely different paths in TVM source repo. It is appreciated anyone can help correct me or confirm. Thanks in advance.
Relay.build() call in python is quickly passed on into C++ side, mainly processed within src/relay/backend/build_module.cc.
/*!
* \brief Compile a Relay IR module to runtime module.
*
* \param relay_module The Relay IR module.
* \param params The parameters.
*/
void BuildRelay(
IRModule relay_module,
const std::unordered_map<std::string, tvm::runtime::NDArray>& params) {
// Relay IRModule -> IRModule optimizations.
relay_module = Optimize(relay_module, targets_, params); // <== **Various graph-level optimizations**.
// Get the updated function.
auto func = Downcast<Function>(relay_module->Lookup("main"));
// Generate code for the updated function.
graph_codegen_ = std::unique_ptr<GraphCodegen>(new GraphCodegen());
graph_codegen_->Init(nullptr, targets_);
graph_codegen_->Codegen(func);
ret_.graph_json = graph_codegen_->GetJSON();
ret_.params = graph_codegen_->GetParams();
auto lowered_funcs = graph_codegen_->GetLoweredFunc();
if (lowered_funcs.size() == 0) {
LOG(WARNING) << "no lowered funcs exist in the compiled module";
} else {
ret_.mod = tvm::build( <= **Calls into tvm.build()???**
lowered_funcs,**
target_host_,**
BuildConfig::Current());**
}
...
}
In contrast, the tvm.build(…) python call is mainly processed via python code python/tvm/driver/build_module.py
...
fhost_all = []
device_modules = []
for tar, flist in target_flist.items():
fhost, mdev = _build_for_device(flist, tar, target_host)
# Save the current lowered functions of the host and the device module.
fhost_all += fhost
device_modules.append(mdev)
# Generate a unified host module.
mhost = codegen.build_module(fhost_all, str(target_host))
# Import all modules.
for mdev in device_modules:
if mdev:
mhost.import_module(mdev)
return mhost