-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[runtime] AOTExecutor implementation and c target code-generator #10283
Conversation
816c9ca
to
512e3f4
Compare
20fa726
to
9c02629
Compare
f187f9f
to
5f4d538
Compare
928ac6f
to
ccc6c9c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks ok to me. Please change the make_unique
statements though, but it can go into a subsequent PR.
|
||
const int num_args = args_.size(); | ||
::std::unique_ptr<TVMValue> call_values{new TVMValue[num_args]}; | ||
::std::unique_ptr<int> call_type_codes{new int[num_args]}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two lines should be
auto call_values = std::make_unique<TVMValue[]>(num_args);
auto call_type_codes = std::make_unique<int[]>(num_args);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, thanks
return_ttypes_.reserve(ttypes.size()); | ||
for (auto ttype : ttypes) { | ||
return_ttypes_.push_back(ttype); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this is equivalent to return_ttypes_ = FlattenTupleType(e->checked_type());
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @areusch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found some left-over log while running test_conv2d
src/target/source/source_module.cc
Outdated
auto metadata = Downcast<runtime::metadata::MetadataBase>(*value); | ||
const runtime::metadata::MetadataArrayNode* arr = | ||
value->as<runtime::metadata::MetadataArrayNode>(); | ||
std::cout << "Is array? " << arr << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/target/source/source_module.cc
Outdated
void Visit(const char* key, ObjectRef* value) final { | ||
const runtime::metadata::MetadataArrayNode* arr = | ||
value->as<runtime::metadata::MetadataArrayNode>(); | ||
std::cout << "Is array? " << arr << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/target/source/source_module.cc
Outdated
for (unsigned int i = 0; i < array->array.size(); ++i) { // ObjectRef o : *(array->array)) { | ||
ObjectRef o = array->array[i]; | ||
std::cout << "visiting array element " << i << ": " << o->type_index() << " (" | ||
<< o.operator->() << ")" << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/target/source/source_module.cc
Outdated
for (unsigned int i = 0; i < arr->array.size(); i++) { | ||
ObjectRef o = arr->array[i]; | ||
std::cout << "queue-visiting array element " << i << ": " << o->type_index() << " (" | ||
<< o.operator->() << ")" << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/target/source/source_module.cc
Outdated
auto struct_name = std::get<0>(item); | ||
auto obj = std::get<1>(item); | ||
auto arr = obj.as<runtime::metadata::MetadataArrayNode>(); | ||
std::cout << "codegen: " << struct_name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
pools.push_back( | ||
runtime::metadata::TensorInfo(make_object<target::metadata::InMemoryTensorInfoNode>( | ||
var->name_hint, | ||
std::vector<int64_t>{metadata->pool_inputs.value()[var]->allocated_size}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check that metadata->pool_inputs
is non-null (it's Optional<Map<tir::Var, tir::usmp::AllocatedPoolInfo>>
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is done earlier in the function, but it was in the wrong spot and i've reorganized the checks.
lib: tvm.runtime.Module = tvm.runtime.load_module("compiled_lib.so") | ||
# Call the library factory function for default and create | ||
# a new runtime.Module, wrap with graph module. | ||
gmod = graph_executor.GraphModule(lib["default"](dev)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need update?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, thanks!
- GraphExecutor, in python/tvm/contrib/graph_executor.py | ||
- VM Executor, in python/tvm/runtime/vm.py | ||
|
||
TODO(areusch): Consolidate these into this module. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized that, we have two notions of executor
. One is the runtime one above, the other is
tvm/python/tvm/relay/build_module.py
Line 647 in 55849e6
def create_executor(kind="debug", mod=None, device=None, target="llvm", params=None): |
which is used a lot in the test cases.
Do we intend to support create_executor(kind="aot", ...)
, given that we can now run things via the cpp runtime?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah that is a good point. added support here.
include/tvm/runtime/metadata.h
Outdated
@@ -75,6 +75,13 @@ struct TVMMetadata { | |||
const struct TVMTensorInfo* outputs; | |||
/*! \brief Number of elements in `outputs` array. */ | |||
int64_t num_outputs; | |||
/*! \brief Memory Pools needed by the AOT run_model function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are not using run_model
anymore, are you? In your previous branch indeed I'm seeing tvmgen_default_run_model
generated, but after rebase it is replaced with tvmgen_default___tvm_main__
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is right!.
We had run (entry_point), run_model and tvm_main.
The entry_point is supposed to call run_model, however, run_model is identical to tvm_main -- therefore, it was removed due to no need of maintaining two symbols for relay and tir versions of main.
So I think it needs to be tvm_main now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to just "AOT main" since the function should probably eventually be renamed based on mod_name
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat! Looking good.
Few nits and questions (for my understanding).
import numpy as np | ||
|
||
|
||
class AotModule(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(stylistic) : AotModule --> AOTModule or AoTModule ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i kind of find it easier to read the acronyms if we use CapWords, this also follows https://www.python.org/dev/peps/pep-0008/#class-names which is linked from numpydoc
@@ -317,6 +327,16 @@ class AOTExecutorCodegen : public MixedModeVisitor { | |||
} | |||
} | |||
|
|||
void PushArgs(const Expr& expr, std::vector<tir::Var> sids, Array<PrimExpr>* args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit : any reason mixed pass-by-value, pass-by-(const)-references usage and pointers here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, sorry kinda rough. changed to pass-by-const-ref and pointer per c++ style guide.
|
||
// Validate choice of use_unpacked_api_ and use_call_cpacked_ | ||
if (runtime_config->name == kTvmRuntimeCrt) { | ||
CHECK(interface_api == "packed" || static_cast<bool>(use_unpacked_api_) == true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are both of these CHECKs tested ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the CRT CHECK is thoroughly tested by existing code (ran into a lot of those tests in making CI happy). added tests for the C++ one.
|
||
/*! | ||
* \file aot_executor_factory.cc | ||
* \brief Graph executor factory implementations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
namespace tvm { | ||
namespace runtime { | ||
|
||
AotExecutorFactory::AotExecutorFactory( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for my knowledge, I never understood why these are called "factories". What maybe the reason ? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's because they are container objects which hold the constructor arguments to an executor. They also handle serializing those arguments during export_library
and reconstructing them during load_module
. they follow the factory pattern (e.g. a no-arg or less-args functor that constructs a given datatype), so that's why the name.
with pytest.raises(tvm.TVMError, match="Packed interface required for packed operators"): | ||
with pytest.raises( | ||
tvm.TVMError, | ||
match=re.escape( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the above comment, I'd expect two of these tests here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think the check fails when both of these conditions are false, so we just need one to assert we get the error message. the remaining single-true cases are tested in various other tests, so i think we should be ok. but lmk if you have a more specific concern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More minor comments, finished the whole thing.
At some point we should review our meta data situation... There are so many classes / files and they look quite messy.
<< ") or unpacked-api == true (got: " << use_unpacked_api_ | ||
<< ") when targeting c runtime"; | ||
} else if (runtime_config->name == kTvmRuntimeCpp) { | ||
CHECK(static_cast<bool>(use_unpacked_api_) == false && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use ICHECK
, also at L918
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
* processor. | ||
* \param devs The device of the host and devices where graph nodes will be | ||
* executed on. | ||
* \param lookup_linked_param_func If given, a PackedFunc invoked to lookup linked parameters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lookup_linked_param_func
not given in the param list
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
* \brief Initialize the AOT executor with metadata, runtime::Module, and device. | ||
* \param module The module containing the compiled functions for the host | ||
* processor. | ||
* \param devs The device of the host and devices where graph nodes will be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no "graph".
And why only the first element of devs
is ever used in aot_executor.cc
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reworded the comment, added ICHECK, and tested.
src/runtime/metadata.cc
Outdated
// " | ||
// << "(when passed from runtime)"; | ||
metadata_ = metadata; | ||
// code_ = code; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
CHECK_EQ(ret_type_code, kTVMOpaqueHandle) | ||
<< "Expected kOpaqueHandle returned; got " << ret_type_code; | ||
CHECK(ret_value.v_handle != nullptr) << "get_c_metadata returned nullptr"; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ICHECK
or ICHECK_EQ
in this function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
* module. | ||
* \param target_module The main TIR-lowered internal runtime module | ||
* \param modules All the external modules that needs to be imported inside the metadata module(s). | ||
* \param target The target that all the modules are compiled for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
metadata
not documented
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/target/source/source_module.cc
Outdated
address_.push_back(i_str.str()); | ||
Visit(nullptr, &metadata); | ||
address_.pop_back(); | ||
// ReflectionVTable::Global()->VisitAttrs(metadata.operator->(), this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/target/source/source_module.cc
Outdated
|
||
auto mod = MetadataModuleCreate(metadata); | ||
std::vector<String> func_names{"get_c_metadata"}; | ||
// definer.GetOutput() + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/target/source/source_module.cc
Outdated
lookup_func << "};" << std::endl; | ||
|
||
auto mod = MetadataModuleCreate(metadata); | ||
std::vector<String> func_names{"get_c_metadata"}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than hard code get_c_metadata
everywhere, we should introduce a new symbol at
tvm/include/tvm/runtime/module.h
Line 219 in d8f639a
namespace symbol { |
tvm_module_main
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
{sid_array, 0, tir::builtin::kArrDeviceType, kDLCPU}))); | ||
new_stmts.push_back(tir::Evaluate( | ||
tvm::tir::Call(DataType::Handle(), tvm::tir::builtin::tvm_struct_set(), | ||
{sid_array, 0, tir::builtin::kArrDeviceId, 0}))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are these changes for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these changes fixed the flaky stack bug where device allocations were using bad threadlocalstorage for workspace. the fix was to explicitly initialize the device_id and device_type fields of the created DLTensor. there are other fields we need to initialize as well, but which we don't use in the c-codgen generated code, at least not extensively.
src/runtime/metadata.cc
Outdated
return PackedFunc([this, sptr_to_self](TVMArgs args, TVMRetValue* rv) { | ||
if (!metadata_.defined()) { | ||
TVMFunctionHandle f_handle; | ||
int32_t ret_code = TVMBackendGetFuncFromEnv(this, "get_c_metadata", &f_handle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@manupa-arm @kparzysz-quic @masahi thanks for the review! addressed your comments, ptal when you have time.
include/tvm/runtime/metadata.h
Outdated
@@ -75,6 +75,13 @@ struct TVMMetadata { | |||
const struct TVMTensorInfo* outputs; | |||
/*! \brief Number of elements in `outputs` array. */ | |||
int64_t num_outputs; | |||
/*! \brief Memory Pools needed by the AOT run_model function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to just "AOT main" since the function should probably eventually be renamed based on mod_name
.
- GraphExecutor, in python/tvm/contrib/graph_executor.py | ||
- VM Executor, in python/tvm/runtime/vm.py | ||
|
||
TODO(areusch): Consolidate these into this module. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah that is a good point. added support here.
import numpy as np | ||
|
||
|
||
class AotModule(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i kind of find it easier to read the acronyms if we use CapWords, this also follows https://www.python.org/dev/peps/pep-0008/#class-names which is linked from numpydoc
lib: tvm.runtime.Module = tvm.runtime.load_module("compiled_lib.so") | ||
# Call the library factory function for default and create | ||
# a new runtime.Module, wrap with graph module. | ||
gmod = graph_executor.GraphModule(lib["default"](dev)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, thanks!
@@ -317,6 +327,16 @@ class AOTExecutorCodegen : public MixedModeVisitor { | |||
} | |||
} | |||
|
|||
void PushArgs(const Expr& expr, std::vector<tir::Var> sids, Array<PrimExpr>* args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, sorry kinda rough. changed to pass-by-const-ref and pointer per c++ style guide.
* module. | ||
* \param target_module The main TIR-lowered internal runtime module | ||
* \param modules All the external modules that needs to be imported inside the metadata module(s). | ||
* \param target The target that all the modules are compiled for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/target/source/source_module.cc
Outdated
address_.push_back(i_str.str()); | ||
Visit(nullptr, &metadata); | ||
address_.pop_back(); | ||
// ReflectionVTable::Global()->VisitAttrs(metadata.operator->(), this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/target/source/source_module.cc
Outdated
lookup_func << "};" << std::endl; | ||
|
||
auto mod = MetadataModuleCreate(metadata); | ||
std::vector<String> func_names{"get_c_metadata"}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/target/source/source_module.cc
Outdated
|
||
auto mod = MetadataModuleCreate(metadata); | ||
std::vector<String> func_names{"get_c_metadata"}; | ||
// definer.GetOutput() + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
{sid_array, 0, tir::builtin::kArrDeviceType, kDLCPU}))); | ||
new_stmts.push_back(tir::Evaluate( | ||
tvm::tir::Call(DataType::Handle(), tvm::tir::builtin::tvm_struct_set(), | ||
{sid_array, 0, tir::builtin::kArrDeviceId, 0}))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these changes fixed the flaky stack bug where device allocations were using bad threadlocalstorage for workspace. the fix was to explicitly initialize the device_id and device_type fields of the created DLTensor. there are other fields we need to initialize as well, but which we don't use in the c-codgen generated code, at least not extensively.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM modulo some unaddressed comments. But they can go into the next LLVM PR.
@manupa-arm @kparzysz-quic please take a look when you have a minute, CI is green now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - thanks @areusch for landing AoT executor !
Thank you @areusch @masahi @kparzysz-quic @manupa-arm for the reviews! The PR has been merged. |
…che#10283) * Add memory pools to Metadata classes. * Move ShapeToJSON to utils. * Track returned TensorType from AOTExecutorCodegen. * Support calling Relay functions with Tuple. * Expand supported TIR calling conventions to work with C++ runtime. * Rename MetadataModule to ConstLoaderModule. * Add runtime AOT executor module. * Add AOT code-generation. * Add a runtime Module to mux between .text Metadata and live Metadata. * Move launch_param to namespace * Add test of c++ AOT. * Fix incongruity between kTvmRuntimeCrt constant * Expand ExecutorCodegenMetadata to include AOT runtime metadata. * commit cpp test * Make Metadata compile under C. * Ignore ephemeral metadata_module export_model_library_format. * This module does not need to be exported, since it is merely a C++ wrapper around get_c_metadata, and get_metadata is not used in C. * address manupa, kparszsyc, masahi comments. * further address comments * clang and python format * Fix broken test * Address lingering comments from masahi, kparszyzc
…che#10283) * Add memory pools to Metadata classes. * Move ShapeToJSON to utils. * Track returned TensorType from AOTExecutorCodegen. * Support calling Relay functions with Tuple. * Expand supported TIR calling conventions to work with C++ runtime. * Rename MetadataModule to ConstLoaderModule. * Add runtime AOT executor module. * Add AOT code-generation. * Add a runtime Module to mux between .text Metadata and live Metadata. * Move launch_param to namespace * Add test of c++ AOT. * Fix incongruity between kTvmRuntimeCrt constant * Expand ExecutorCodegenMetadata to include AOT runtime metadata. * commit cpp test * Make Metadata compile under C. * Ignore ephemeral metadata_module export_model_library_format. * This module does not need to be exported, since it is merely a C++ wrapper around get_c_metadata, and get_metadata is not used in C. * address manupa, kparszsyc, masahi comments. * further address comments * clang and python format * Fix broken test * Address lingering comments from masahi, kparszyzc
This PR adds the AOTExecutor implementation and the metadata code-generator for use with the
c
target. This PR allows users to run models which use only the CPU via the AOTExecutor using the C++ runtime.cc @Mousius @manupa-arm @kparzysz-quic @masahi @mehrdadh