-
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
Return empty CSourceModule when no lowered_funcs exists in Relay mod #4847
Conversation
3bcb8aa
to
d6301d6
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.
Thanks for contributing this - I've hit this issue myself in the case where the entire graph is off-loaded to external codegen. I wonder whether there's a case for making tvm::build return a 'dummy' module in the case of no lowered_funcs being provided? That way we could avoid having to put the workaround here.
src/relay/backend/build_module.cc
Outdated
Stmt body = EvaluateNode::make(0); | ||
Array<ObjectRef> api_args; | ||
auto dummy_func = MakeAPI(body, "__dummy__", api_args, 0, false); | ||
lowered_funcs.Set("llvm", Array<LoweredFunc>({dummy_func})); |
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 defaulting the LLVM the correct behaviour here (eg. will this fall over if we build without LLVM support)?
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 should set target_host_
. Even we have LLVM support, it is not correct too, imagine our target host is ARM.
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.
Thank you guys for your kind comments. We don't need to set target in the latest commit.
src/relay/backend/build_module.cc
Outdated
lowered_funcs, | ||
target_host_, | ||
BuildConfig::Current()); | ||
LOG(WARNING) << "No lowered funcs exist in the compiled 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.
Do we need to retain this warning? With external codegen, having no lowered funcs can be a perfectly normal mode of operation.
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 @mbarrett97 , I've removed that log.
I agree that perhaps an empty module provides useful middle ground. The closest thing so far might be CSourceModule with an empty string https://github.com/apache/incubator-tvm/blob/master/src/target/source/source_module.cc#L190 |
CSourceModule with an empty string looks to me as well. @kumasento could you do that instead of creating a dummy llvm module? Thanks. |
Thank you guys for all your kind reviews! @mbarrett97 @FrozenGene @tqchen @zhiics I've updated this PR to fulfill the following revisions:
Now the generated module looks clean and tidy. No redundant dummy function generated and no extra design decisions should be made. Please let me know if there is anything else you feel should be done. Thanks! |
b3b15f2
to
1f13b9e
Compare
1f13b9e
to
adbe5a2
Compare
src/relay/backend/build_module.cc
Outdated
@@ -438,13 +439,14 @@ class RelayBuildModule : public runtime::ModuleNode { | |||
|
|||
auto lowered_funcs = graph_codegen_->GetLoweredFunc(); | |||
if (lowered_funcs.size() == 0) { | |||
LOG(WARNING) << "no lowered funcs exist in the compiled module"; | |||
ret_.mod = tvm::codegen::CSourceModuleCreate("", ""); |
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.
Sorry for the back and forth. Could you please add a comment here so that ppl would know what we are doing 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.
You can force push so that your previous CI could be terminated earlier.
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.
Sure thing, just added that
I don't think the empty CSourceModule method works. There's a check in source_module.cc that fails when you try and create one with an empty string. |
Hi @mbarrett97 thanks for your comment. Currently I haven't met such an issue while testing. Would you mind letting me know which assertion you were referring to? |
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.
Here's the assert:
https://github.com/apache/incubator-tvm/blob/a5661611472c8e92b20bbe4d074333b8183f2878/src/target/source/source_module.cc#L101
There's a problem that you hit before that though, you need to remove the check here:
https://github.com/apache/incubator-tvm/blob/a5661611472c8e92b20bbe4d074333b8183f2878/src/relay/backend/build_module.cc#L452
This is because the new module still has no lowered functions.
@mbarrett97 Thanks, I just noticed that the base of my PR is not the latest commit. I will update it soon. |
7a79f6b
to
ccded94
Compare
ping @FrozenGene please followup |
src/target/llvm/llvm_module.cc
Outdated
auto target = args[0].operator std::string(); | ||
auto module_name = args[1].operator std::string(); | ||
|
||
// create a default data layout |
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.
Sorry for later response. Minor comment: The logic here doesn't only create default data layout but also create default target triple. We should update the comment.
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 @FrozenGene I've updated the comments based on your comments :)
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 @kumasento @FrozenGene @mbaret @zhiics This PR is now merged |
This commit is causing segfaults when my entire relay program is offloaded to an external codegen. |
Hi Trevor,
Thanks for the info. Can you provide more information about the bug you've
got? Thanks.
…On Tue, 17 Mar 2020 at 17:29, Trevor Morris ***@***.***> wrote:
This commit is causing segfaults when my entire relay program is offloaded
to an external codegen.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#4847 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACC42R5SF23UYPEF6M5ABT3RH6XPNANCNFSM4KR43YZQ>
.
|
HI @kumasento the graph runtime is trying to get my external codegen functions from the empty LLVM module. Stack trace shows the segfault is coming from LLVMModuleNode, so I added a print statement after this line which showed that GetFunction() was called on the LLVM module with name= Stack trace:
|
Thanks @trevor-m @FrozenGene sorry for bothering you but does this ring a bell? I feel it is weird that |
Please see: https://github.com/apache/incubator-tvm/pull/4847/files#diff-8baddb83a9684e8373691bb48a946900R469-R474 When entire program is offloaded, I find previous logic will // Execute the whole module using external runtime.
ret_.mod = ext_mods[0]; However, current logic we will // Import all external runtime modules.
for (const auto& it : ext_mods)
ret_.mod.Import(it); Could you double check the logic is the same as previous? Thanks. |
Hi @FrozenGene Thanks for your explanation. I do have a question about this part, hope you won't mind:
Also @trevor-m would you mind sending me a minimal workable example? I would like to do the tracing myself as well. Thanks |
I think we should be |
I think changing it to a llvm module and import all submodules is okay. Now if you only have an external module. You will need to create a llvm module first and them import the external module to it. Stepping into llvm module to find the symbol is not wrong because we will always try to find the symbol from the host module first. If it is not found, we will then try to check each imported module. See the code here: A minimal example to reproduce this and track the root cause would be more helpful. |
You can reproduce this by running |
Hi @trevor-m Now I'm looking at the internal logic in LLVM to find out what the actual cause is. Please bear with me for 1-2 days. |
…pache#4847) * Use dummy func when no lowered_funcs exists in Relay mod * Dummy func -> CSourceModule with empty code str * Added comments describing the empty CSouceModule * Always import external modules w/o assertions * Use CSourceModule as a fallback for LLVMModule * Changed cond for target == llvm * Create an empty LLVM module w/o using dummy func * Avoid using IR str concat to create LLVM module * Improved comments for codegen.LLVMModuleCreate * Satisfy the linter for LLVMModuleCreate
…pache#4847) * Use dummy func when no lowered_funcs exists in Relay mod * Dummy func -> CSourceModule with empty code str * Added comments describing the empty CSouceModule * Always import external modules w/o assertions * Use CSourceModule as a fallback for LLVMModule * Changed cond for target == llvm * Create an empty LLVM module w/o using dummy func * Avoid using IR str concat to create LLVM module * Improved comments for codegen.LLVMModuleCreate * Satisfy the linter for LLVMModuleCreate
…pache#4847) * Use dummy func when no lowered_funcs exists in Relay mod * Dummy func -> CSourceModule with empty code str * Added comments describing the empty CSouceModule * Always import external modules w/o assertions * Use CSourceModule as a fallback for LLVMModule * Changed cond for target == llvm * Create an empty LLVM module w/o using dummy func * Avoid using IR str concat to create LLVM module * Improved comments for codegen.LLVMModuleCreate * Satisfy the linter for LLVMModuleCreate
This PR implements the dummy function idea as mentioned in #4748 - when the whole Relay module is optimized to empty, we can insert a dummy operator that allows TVM to still produce a library.