[Unity] Ensure one VM register for each relax binding#15855
[Unity] Ensure one VM register for each relax binding#15855Lunderberg merged 5 commits intoapache:unityfrom
Conversation
|
This PR is based on top of #15854, and should not have any conflicts with it. However, as this PR implements a more general fix, it has a greater chance of causing failures in other test cases. The more general fix is preferred for long-term maintenance, but the more specific fix takes precedence to solve the immediate bug. Therefore, this PR is marked as a draft until either #15854 lands, or this PR passes CI and can therefore supersede #15854. |
2a77ca1 to
a9f3bce
Compare
a9f3bce to
b5897b6
Compare
|
Rebased onto current |
|
Would be great to create a UT for this behavior in the https://github.com/apache/tvm/blob/unity/tests/python/relax/test_vm_codegen_only.py def test(x: Object, callback):
alias_v = x
kill(x)
callback(alias_v)
We also need to update support for compiled mode |
|
Thank you, @tqchen, and I really like that unit test to validate the desired behavior in the VM, and not just how that behavior impacts a use case. I've updated the PR to include the unit test, parametrized to run on both |
|
One unrelated question, though. In your pseudocode, you have the signature |
|
ah i see, one way to get around is define the callback as a global test function and call that with call_packed. e.g. https://github.com/apache/tvm/blob/unity/tests/python/relax/test_vm_codegen_only.py#L140C1-L141C1 https://github.com/apache/tvm/blob/unity/python/tvm/relax/testing/vm.py |
Prior to this commit, if a relax variable were assigned to itself, through either `VarBinding` or `MatchCast` nodes, the two relax variables would share the same register in the VM. As a result, any upstream transform that deletes an object with `R.memory.kill_tensor` or `R.memory.kill_storage` must be aware of this VM behavior, and to only output one such instruction for each set of aliased registers. This commit updates the VM to produce one register for each aliased relax variable. The trivial bindings can be removed applying `relax.transform.CanonicalizeBindings`, instead of being implicitly de-duplicated at the codegen level. This PR is a follow-up to apache#15854, with a better long-term solution, but which may have knock-on effects that must also be resolved. In addition, this adds a usage example for the bug reported in apache#15852, to avoid re-occurrence of similar issues.
That's what I ended up doing, with a global definition which can be looked up at runtime. I'd been hoping that there would be a way to avoid dependencies on global state, out of a general principle. (And, if relax functions could accept a Rebased onto head to re-run CI. Previous failures were present in unity head, and have been resolved. (See this comment for details.) |
5b2ece6 to
e1d889c
Compare
|
|
||
| cached = tvm.get_global_func(func_name, allow_missing=True) | ||
|
|
||
| @tvm.register_func(func_name, override=True) |
There was a problem hiding this comment.
move this registeration to relax.testing namespace
There was a problem hiding this comment.
Sounds good, and updated!
Prior to this commit, if a relax variable were assigned to itself, through either
VarBindingorMatchCastnodes, the two relaxvariables would share the same register in the VM. As a result, any upstream transform that deletes an object with
R.memory.kill_tensororR.memory.kill_storagemust be aware of this VM behavior, and to only output one such instruction for each set of aliased registers.This commit updates the VM to produce one register for each aliased relax variable. The trivial bindings can be removed applying
relax.transform.CanonicalizeBindings, instead of being implicitly de-duplicated at the codegen level.This PR is a follow-up to #15854 with a better long-term solution, but which may have knock-on effects that must also be resolved. In addition, this adds a usage example for the bug reported in #15852, to avoid re-occurrence of similar issues.