-
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
[CRT] Create C-runtime-style metadata module for llvm builds #7398
Conversation
dad84a0
to
18a54ba
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.
Just a heads up that you might want to know.
src/target/metadata_module.cc
Outdated
csource_modules.push_back(target_module); | ||
target_module = CreateCSourceCrtMetadataModule(csource_modules, target); | ||
} else if (target->kind->name == "llvm") { | ||
binary_modules.push_back(target_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 think target_module should not be a binary module that gets imported inside non-DSOExportable metadata module.
I think csource_modules --> dso_modules and binary_modules --> non_dso_modules would be better. Moreover, non-DSOExportable metadata module should not be created if non of the modules need constant loading.
TL;DR
This one is little complex to explain. Let me use some definitions first (and feel free to change the names as you see fit).
[Defn.1] binary module : a runtime.Module that is not DSOExportable (not of type "c" or "llvm").
[Defn.2][NCL (needs constant loading) module : a module that requires constant loading in the init process.
As of today these two things are not strictly orthogonal. (i.e. DSOExportabe module could use constant loading -- though the only one is the example byoc c codegen).
So technically any module that implements get_func_names could be imported under the DSOExportable metadata module (llvm -- the one this PR introduces or c -- the one I introduced before). However, currently the only ones that get imported inside DSOExportable metadata module are modules that are !("binary" or "NCL"). So I had a hard time finding the name and end-up calling them binary modules.
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.
As of today these two things are not strictly orthogonal. (i.e. DSOExportabe module could use constant loading -- though the only one is the example byoc c codegen).
Do you mean "(I.e. binary module could use constant loading..." here?
okay I think my point of confusion here (and I think it's related to lack of experience with BYOC) is: what makes metadata module non-DSO-exportable?
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.
runtime::MetadataModuleCreate() --> is non-DSO-exportable it gets packed into to devc.{o/c} and I think we should only need this if we have modules that require constant loading. This one is of type "metadata". Im talking about the one that is created in line 96.
I mean DSOExportable modules could still use constant loading -- though I think its not very useful since we have linked params now. Only remaining place is the example c byoc codegen that uses the constant loading process as a demo to all BYOC codegens -- I think.
Thus, if none of the modules does not require constant loading -- that is indicated by arrays.empty() -- we dont need to create the non-DSOExportable metadata module.
See the diagram here : https://discuss.tvm.apache.org/t/csourcemetadata-module-a-csourcemodule-to-hold-function-registry-for-utvm/8554.
Does that make sense ?
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.
okay so let me summarize my understanding:
- at the end of the day, we want to produce a single module that imports all the others
- This function gets the Module that implements target_host (
target_module
) plus a list of all the BYOC modules (ext_modules
). - when building for the C++ runtime, we have runtime::MetadataModule for this root module. We assume each Module in
ext_modules
contains exactly one Relay function whose name isget_symbol()
and which may use ConstantNodes whose values must be initialized fromget_const_vars()
.get_func_names()
is unused becausedlsym
is used to resolve functions in the C++ runtime. - when building for the C runtime, we use either the CSourceMetadataModule from Created CSourceMetaData module for model metadata #7002 or LLVMCrtMetadataModule from this PR. These are both DSO-exportable. The CSourceMetadataModule queries function names from and imports all DSO-exportable modules which don't define any const_vars. Let's call these "CRT-exportable modules" since we don't have a good name for them.
- Then, any modules which are: a) non-DSO-exportable, b) not codegen'd by c or llvm backend, OR c) not defining any const_vars are imported into the resulting metadata module.
Presumably then the LLVM module should work the same way as the C-source one, the only change needed being that target->kind->name == "llvm" should also admit DSO-exportable functions to csource_modules.
Then, I'd propose the following name changes:
- csource_modules -> crt_exportable_modules
- binary_modules -> non_crt_exportable_modules
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.
Yes, this seems right :)
Let me just tighten the point 5
"5.) Then, any modules which are: a) non-DSO-exportable OR b) (not defining any const_vars OR result of get_const_vars() is empty() ) are imported into the resulting (here resulting means at least one of the two conditions is met) metadata module."
Summary is 5b is covered 5a and metadata module of type "metadata" should only be created if one of the above condition is met.
Moreover, c runtime does not support ProcessModuleBlob(Im talking about : src/runtime/library_module.cc) anyway -- does it ? -- that could be used as a blanket assertion to check whether all modules are !5a and !5b if the target says c 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 seems right. I think we've come to similar conclusions. I think there are a couple of larger issues to be resolved here:
- When targeting the C runtime, an entirely different strategy than MetadataModule is needed to export Modules which don't run on the target_host CPU. This isn't well-defined yet. Model Library Format RFC also touches on this, but doesn't resolve it.
- Related to resolving this conundrum: the model of the C++ runtime is that some library running on target_host parses binary configuration data in MetadataModule and then configures any runtime libraries or accelerators. This is generally used to implement BYOC. C runtime does not want to require any startup procedure that involves parsing binary blobs using RAM--instead, this must happen at code-generation time. This means that we need to do a better job here of organizing Module according to the DLContext which will be executing those modules.
Here we've mostly fixed problem 1. In future PR and RFC, we can work to address problem 2. Let me know if that makes sense to you!
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.
@areusch , few clarfications :
-
The MetadataModule of type "metadata" is a another module that get loaded using ProcessModuleBlob in c++ runtime. Therefore, I would not agree to "MetadataModule is needed to export Modules ". For e.g., currently ARM Ethos-N that uses ProcessModuleBlob does not require MetadataModule of type "metadata" as it does not need any constants to be loaded into it in the init process. Having said that, what I agree with you is that ProcessModuleBlob should not be the way to do things in C runtime -- more specifically in uTVM environments. So you can think of MetadataModule of type "metadata" as a peer to all runtime modules that gets "packed" to use ProcessModuleBlob in the runtime.
-
Similarly, I would not agree "target_host parses binary configuration data in MetadataModule and then configures any runtime libraries or accelerators", because MetadataModule of type "metadata" only have the constants and other binaries go inside devc.c/o independently of MetadataModule of type "metadata".
I agree that " C runtime does not want to require any startup procedure that involves parsing binary blobs using RAM--instead, this must happen at code-generation time.".
"This means that we need to do a better job here of organizing Module according to the DLContext which will be executing those modules." -- This I agree. First thing is we need to move away from the assumption that BYOC flows always generate non-DSO-exportable runtime.Modules that is not currently true for our ongoing ARM Ethos-U work. We will be producing a DSOExportable runtime.Module. One side note to this, we might want to integrate the BYOC (possiblly not call it BYOC :) ) in the compilation pathway as it offers IRModule --> runtime.Module conversion generally and TVM's internal module compilation is "a" way of producing it. I have made a similiar comment here : #7428
So towards that goal, I think we need a mechanism to identify the DLContext without relying on their type being "c" or "llvm" as they could possiblly be coming from a BYOC flow. There should be a primary key in the runtime.Module to say its DLContext, IMHO.
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.
Therefore, I would not agree to "MetadataModule is needed to export Modules ". For e.g., currently ARM Ethos-N that uses ProcessModuleBlob does not require MetadataModule of type "metadata" as it does not need any constants to be loaded into it in the init process.
sure, but it depends on ProcessModuleBlob calling runtime.module.loadbinary_ethos-n
, right? This is the part I think of most concern going forward--for µTVM, and I think we could say more broadly for CRT (no reason to support two flows in one runtime) we want to make it possible to do as much of this logic at compile time to produce a firmware binary that requires minimal startup procedures.
So you can think of MetadataModule of type "metadata" as a peer to all runtime modules that gets "packed" to use ProcessModuleBlob in the runtime.
this makes sense to me, but I'd further qualify it to "all non-DSO-exportable runtime modules," at least for now.
Similarly, I would not agree "target_host parses binary configuration data in MetadataModule and then configures any runtime libraries or accelerators", because MetadataModule of type "metadata" only have the constants and other binaries go inside devc.c/o independently of MetadataModule of type "metadata".
You're right--I was getting this confused with codegen_blob
since the FuncRegistry logic doesn't have an explicit home in C++ land.
So towards that goal, I think we need a mechanism to identify the DLContext without relying on their type being "c" or "llvm" as they could possiblly be coming from a BYOC flow. There should be a primary key in the runtime.Module to say its DLContext, IMHO.
I agree with a few clarifications. Perhaps better to discuss on the forum. The main points are: all BYOC are ext_dev
, and perhaps some SoC may have a set of identical accelerators, some configured with one program and some with another. We probably should just consider how to support that case now rather than have to refactor that later--I think the difference is minor and amounts to coming up with another name for runtime::Module
which indicates a) which device_type
or BYOC accelerator the module is to run on and b) if multiple such things exist, a sort of "program name" for the particular accelerator program being generated.
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.
Thanks for hard work!
Broadly LGTM, just a one clarification about a test.
tests/python/unittest/test_crt.py
Outdated
global TARGET | ||
old_target = TARGET | ||
try: | ||
TARGET = tvm.target.Target("llvm " + str(TARGET)[2:]) |
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.
Not very clear to me what is going on here ?
I would imagine we would want to test both llvm and c targets, right ?
May I ask why is the need for try-finally 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.
clarified a bit--i'm being lazy and reusing test_compile_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.
The changes for metadata module and csource module look good to me, please fix the ci
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
@zhiics merge? |
Thank you @areusch @zhiics @manupa-arm the PR has been merged. |
…7398) * Create C-runtime-style metadata module for llvm builds. * maybe address manupa's comment * lint * actually address manupa comments * comment and rename * git-clang-format * pylint * cpp warning * try to fix apps/bundle_deploy * black format * build correct file * Use save() for C++-runtime targeted artifacts. * fix build_module LLVM metadata module conditions * fix test comment * black format * further restrict CRT MetadataModule creation * Fix test_link_params * black format and address zhiics comments * fix test_link_params, i think?
…7398) * Create C-runtime-style metadata module for llvm builds. * maybe address manupa's comment * lint * actually address manupa comments * comment and rename * git-clang-format * pylint * cpp warning * try to fix apps/bundle_deploy * black format * build correct file * Use save() for C++-runtime targeted artifacts. * fix build_module LLVM metadata module conditions * fix test comment * black format * further restrict CRT MetadataModule creation * Fix test_link_params * black format and address zhiics comments * fix test_link_params, i think?
FYI, this appears to break TVM builds with USE_LLVM=OFF. Will try to come up with a fix |
This PR is a follow-on to #7002 and continues its work to support BYOC functions with the
llvm
TVM target with the C runtime. Though the BYOC flow is supported with the TVM C++ runtime, this support depends heavily ondlsym
and shared library support, neither of which are required to use the TVM C runtime.This PR can roughly be thought of in these parts:
runtime.CreateLLVMCrtMetadataModule
PackedFunc to theruntime.CreateCSourceCrtMetadataModule
. Also addcrt
here to distinguish between these metadata modules (which are intended to be compiled) and runtime::MetadataModule (which is intended to be directly loaded into the TVM compiler c++ runtime)tvm.micro.build_static_runtime
to accept object files from the LLVM backend. This temporarily solution allows us to buildllvm
-targeted code using microTVM.