This is an automated email from the ASF dual-hosted git repository.
csullivan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new bafa3e9c22 [Hexagon] Add AoT capability to Hexagon launcher (#11214)
bafa3e9c22 is described below
commit bafa3e9c2247eabea1aaa3864dbde1334415d8b8
Author: Krzysztof Parzyszek <[email protected]>
AuthorDate: Wed May 4 18:09:00 2022 -0500
[Hexagon] Add AoT capability to Hexagon launcher (#11214)
* [Hexagon] Add AoT capability to Hexagon launcher
---
apps/hexagon_launcher/README.md | 19 ++++++++++++++++
apps/hexagon_launcher/launcher_core.cc | 37 +++++++++++++++++++++++++++++--
apps/hexagon_launcher/launcher_core.h | 4 ++--
apps/hexagon_launcher/launcher_hexagon.cc | 27 +++++++++++++++++-----
apps/hexagon_launcher/launcher_main.cc | 9 ++++++--
5 files changed, 84 insertions(+), 12 deletions(-)
diff --git a/apps/hexagon_launcher/README.md b/apps/hexagon_launcher/README.md
index 5fc27cb253..210759a80c 100644
--- a/apps/hexagon_launcher/README.md
+++ b/apps/hexagon_launcher/README.md
@@ -170,6 +170,25 @@ A sample output JSON from running the Inception V3 model
may look like
}
```
+When using AoT, the `target` needs to be `llvm`:
+```
+aot_target = "llvm -keys=hexagon -link-params=0
-mattr=+hvxv69,+hvx-length128b,+hvx-qfloat,-hvx-ieee-fp -mcpu=hexagonv69
-mtriple=hexagon"
+aot_host_target = aot_target
+```
+
+Build the relay module specifying AoT as executor and CPP as runtime, and save
it via `export_library`:
+```
+lowered = tvm.relay.build(
+ relay_mod,
+ params=params,
+ target=tvm.target.Target(aot_target, host=aot_host_target),
+ runtime=Runtime("cpp"),
+ executor=Executor("aot", {"unpacked-api": False, "interface-api":
"packed"}),
+)
+
+lowered.export_library("model-aot.so", tvm.contrib.hexagon.link_shared)
+```
+
# Disclaimer
The launcher does not perform any correctness verification. In order to verify
diff --git a/apps/hexagon_launcher/launcher_core.cc
b/apps/hexagon_launcher/launcher_core.cc
index 842406d950..a3993451c2 100644
--- a/apps/hexagon_launcher/launcher_core.cc
+++ b/apps/hexagon_launcher/launcher_core.cc
@@ -26,6 +26,8 @@
#include <fstream>
#include <ios>
#include <iterator>
+#include <ostream>
+#include <sstream>
#include <string>
#include <vector>
@@ -130,9 +132,9 @@ bool write_output_config(const std::string& file_name,
OutputConfig* output_conf
}
Model::Model(tvm::runtime::Module executor, tvm::runtime::Module module,
std::string json)
- : graph_executor(executor), graph_module(module), graph_json(json) {
+ : model_executor(executor), graph_module(module), graph_json(json) {
// Lookup "run" ahead of time to reduce overhead in the model execution.
- run = get_module_func(graph_executor, "run");
+ run = get_module_func(model_executor, "run");
}
const tvm::runtime::PackedFunc get_runtime_func(const std::string& name) {
@@ -157,11 +159,23 @@ tvm::runtime::Module load_module(const std::string&
file_name) {
get_runtime_func("runtime.module.loadfile_hexagon");
tvm::runtime::TVMRetValue rv = loader(file_name);
if (rv.type_code() == kTVMModuleHandle) {
+ ICHECK_EQ(rv.type_code(), kTVMModuleHandle)
+ << __func__ << ": loaded " << file_name << ", but did not get module
handle";
return rv.operator tvm::runtime::Module();
}
return tvm::runtime::Module();
}
+std::ostream& operator<<(std::ostream& os, const tvm::Array<tvm::String>&
strings) {
+ os << '[';
+ for (int i = 0, e = strings.size(); i != e; ++i) {
+ if (i != 0) os << ',';
+ os << static_cast<std::string>(strings[i]);
+ }
+ os << ']';
+ return os;
+}
+
tvm::runtime::Module create_graph_executor(const std::string& graph_json,
tvm::runtime::Module graph_module,
tvm::Device device) {
std::string launcher_name = "tvm.graph_executor.create";
@@ -170,6 +184,25 @@ tvm::runtime::Module create_graph_executor(const
std::string& graph_json,
uint64_t device_type = device.device_type;
uint64_t device_id = device.device_id;
+ if (graph_json.empty()) {
+ LOG(ERROR) << __func__ << ": graph executor requires graph JSON";
+ return tvm::runtime::Module();
+ }
tvm::runtime::TVMRetValue rv = create_executor(graph_json, graph_module,
device_type, device_id);
return rv.operator tvm::runtime::Module();
}
+
+tvm::runtime::Module create_aot_executor(tvm::runtime::Module factory_module,
tvm::Device device) {
+ tvm::runtime::PackedFunc list_modules = get_module_func(factory_module,
"list_module_names");
+ tvm::Array<tvm::String> module_names = list_modules();
+ if (module_names.size() != 1) {
+ LOG(WARNING) << __func__ << ": expecting single module, got: " <<
module_names << ", using "
+ << module_names[0];
+ }
+ tvm::runtime::PackedFunc f = get_module_func(factory_module,
module_names[0]);
+ if (f.get() == nullptr) {
+ LOG(ERROR) << __func__ << ": failed to obtain function " <<
module_names[0];
+ return tvm::runtime::Module();
+ }
+ return f(device);
+}
diff --git a/apps/hexagon_launcher/launcher_core.h
b/apps/hexagon_launcher/launcher_core.h
index 91384133ab..a32bf937af 100644
--- a/apps/hexagon_launcher/launcher_core.h
+++ b/apps/hexagon_launcher/launcher_core.h
@@ -83,12 +83,11 @@ struct OutputConfig {
struct Model {
Model(tvm::runtime::Module executor, tvm::runtime::Module module,
std::string json);
- tvm::runtime::Module graph_executor;
+ tvm::runtime::Module model_executor;
tvm::runtime::Module graph_module;
std::string graph_json;
static tvm::Device device() { return
tvm::Device{static_cast<DLDeviceType>(kDLHexagon), 0}; }
-
static tvm::Device external() { return
tvm::Device{static_cast<DLDeviceType>(kDLCPU), 0}; }
tvm::runtime::PackedFunc run;
@@ -125,6 +124,7 @@ const tvm::runtime::PackedFunc get_runtime_func(const
std::string& name);
const tvm::runtime::PackedFunc get_module_func(tvm::runtime::Module module,
const std::string& name);
+tvm::runtime::Module create_aot_executor(tvm::runtime::Module factory_module,
tvm::Device device);
tvm::runtime::Module create_graph_executor(const std::string& graph_json,
tvm::runtime::Module graph_module,
tvm::Device device);
diff --git a/apps/hexagon_launcher/launcher_hexagon.cc
b/apps/hexagon_launcher/launcher_hexagon.cc
index 4159391b26..d4fbf4bf5d 100644
--- a/apps/hexagon_launcher/launcher_hexagon.cc
+++ b/apps/hexagon_launcher/launcher_hexagon.cc
@@ -64,7 +64,22 @@ AEEResult __QAIC_HEADER(launcher_rpc_load)(remote_handle64
handle, const char* m
}
tvm::runtime::Module module = load_module(module_path);
- tvm::runtime::Module executor = create_graph_executor(graph_json, module,
Model::device());
+ std::string module_type = module->type_key();
+ tvm::runtime::Module executor;
+ if (module_type == "AotExecutorFactory") {
+ executor = create_aot_executor(module, Model::external());
+ } else if (module_type == "library") {
+ // We're not expecting "GraphExecutorFactory" here.
+ executor = create_graph_executor(graph_json, module, Model::device());
+ } else {
+ LOG(ERROR) << __func__ << ": unexpected module type: " << module_type;
+ // Fall through.
+ }
+
+ if (executor.get() == nullptr) {
+ LOG(ERROR) << __func__ << ": failed to create executor for module" <<
module_path;
+ return AEE_EUNABLETOLOAD;
+ }
TheModel = std::make_unique<Model>(executor, module, graph_json);
return AEE_SUCCESS;
@@ -84,7 +99,7 @@ AEEResult
__QAIC_HEADER(launcher_rpc_get_num_inputs)(remote_handle64 handle, int
}
tvm::runtime::PackedFunc get_num_inputs =
- get_module_func(TheModel->graph_executor, "get_num_inputs");
+ get_module_func(TheModel->model_executor, "get_num_inputs");
*num_inputs = get_num_inputs();
return AEE_SUCCESS;
}
@@ -119,7 +134,7 @@ AEEResult
__QAIC_HEADER(launcher_rpc_set_input)(remote_handle64 handle, int inpu
auto input = tvm::runtime::NDArray::FromDLPack(&managed);
- tvm::runtime::PackedFunc set_input =
get_module_func(TheModel->graph_executor, "set_input");
+ tvm::runtime::PackedFunc set_input =
get_module_func(TheModel->model_executor, "set_input");
set_input(input_idx, input);
return AEE_SUCCESS;
@@ -132,7 +147,7 @@ AEEResult
__QAIC_HEADER(launcher_rpc_get_num_outputs)(remote_handle64 handle, in
}
tvm::runtime::PackedFunc get_num_outputs =
- get_module_func(TheModel->graph_executor, "get_num_outputs");
+ get_module_func(TheModel->model_executor, "get_num_outputs");
*num_outputs = get_num_outputs();
return AEE_SUCCESS;
}
@@ -152,7 +167,7 @@ AEEResult
__QAIC_HEADER(launcher_rpc_get_output)(remote_handle64 handle, int out
return AEE_EBADPARM;
}
- tvm::runtime::PackedFunc get_output =
get_module_func(TheModel->graph_executor, "get_output");
+ tvm::runtime::PackedFunc get_output =
get_module_func(TheModel->model_executor, "get_output");
tvm::runtime::NDArray output = get_output(output_idx);
std::vector<int64_t> shape_vec{output->shape, output->shape + output->ndim};
@@ -163,7 +178,7 @@ AEEResult
__QAIC_HEADER(launcher_rpc_get_output)(remote_handle64 handle, int out
delete static_cast<tvm::runtime::NDArray::Container*>(container);
});
- tvm::runtime::NDArray host_output(GetObjectPtr<tvm::Object>(container));
+ tvm::runtime::NDArray
host_output(tvm::runtime::GetObjectPtr<tvm::runtime::Object>(container));
if (meta_size != 0) {
auto* meta = reinterpret_cast<tensor_meta*>(output_meta);
diff --git a/apps/hexagon_launcher/launcher_main.cc
b/apps/hexagon_launcher/launcher_main.cc
index ac21a7be16..163d582db4 100644
--- a/apps/hexagon_launcher/launcher_main.cc
+++ b/apps/hexagon_launcher/launcher_main.cc
@@ -76,8 +76,13 @@ int main(int argc, char* argv[]) {
}
ExecutionSession& session = *session_ptr;
- std::cout << "loading model files: " << config.model_json << ", " <<
config.model_library << '\n';
- std::string json = load_text_file(config.model_json);
+ std::cout << "loading model files: ";
+ if (!config.model_json.empty()) {
+ std::cout << config.model_json << ", ";
+ }
+ std::cout << config.model_library << '\n';
+
+ std::string json = !config.model_json.empty() ?
load_text_file(config.model_json) : "";
if (!session.load_model(config.model_library, json.c_str())) {
return 1;
}