Skip to content

Conversation

@Lunderberg
Copy link
Contributor

The KillAfterLastUse pass that was implemented in #15810 checked for trivial re-bindings in VarBinding nodes, but not in MatchCast nodes. As a result, CodeGenVM's de-duplication of registers resulted in the object being killed prematurely.

y = R.match_cast(x, R.Tensor(...)) # Trivial rebinding here.
                                   # CodeGenVM has these share a register.

R.memory.kill_tensor(x)  # Kill x after last usage.
                         # Register is set to None.

_ = R.ExternFunc("set_item")(y) # Use of the cleared register through y.

The `KillAfterLastUse` pass that was implemented in
apache#15810 checked for trivial
re-bindings in `VarBinding` nodes, but not in `MatchCast` nodes.  As a
result, `CodeGenVM`'s de-duplication of registers resulted in the
object being killed prematurely.

```python
y = R.match_cast(x, R.Tensor(...)) # Trivial rebinding here.
                                   # CodeGenVM has these share a register.

R.memory.kill_tensor(x)  # Kill x after last usage.
                         # Register is set to None.

_ = R.ExternFunc("set_item")(y) # Use of the cleared register through y.
```
@Lunderberg
Copy link
Contributor Author

@junrushao This change should resolve the MLC-LLM error you found in #15852. It works in my local setup, and it would be good to validate that it works on your side as well.

Lunderberg added a commit to Lunderberg/tvm that referenced this pull request Oct 2, 2023
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.
@junrushao junrushao merged commit 407e20d into apache:unity Oct 3, 2023
@masahi
Copy link
Member

masahi commented Oct 3, 2023

Just hit the issue of ValueError: Do not know how to handle type object, fixed by this PR. Thanks.

@Lunderberg Lunderberg deleted the unity_bugfix_check_for_trivial_match_cast branch October 3, 2023 13:56
Lunderberg added a commit to Lunderberg/tvm that referenced this pull request Oct 3, 2023
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.
Lunderberg added a commit to Lunderberg/tvm that referenced this pull request Oct 24, 2023
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.
Lunderberg added a commit to Lunderberg/tvm that referenced this pull request Oct 25, 2023
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.
Lunderberg added a commit that referenced this pull request Oct 31, 2023
* [Unity] Ensure one VM register for each relax binding

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 #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.

* Add unit test to validate that the alias is preserved

* Use the new GetBoundValue utility function

* Update VMTIRCodeGen to also avoid de-duplication of bindings

* Move the callback definition to tvm.relax.testing.vm namespace
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants