functionalize(): make "additionally removing views" toggleable#678
functionalize(): make "additionally removing views" toggleable#678
Conversation
| } | ||
| ); | ||
| } | ||
| return tensor; |
There was a problem hiding this comment.
Apparently you need to compile with the -Werror=return-type flag, or else you get silent UB if you forget to return from a non-void function (aka this bug) :(
There was a problem hiding this comment.
:(, we used to have -Werror turned on for all errors but it turns out PyTorch doesn't and PyTorch would introduce warnings
… view_copy operators"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
…tors"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
| } | ||
|
|
||
| Tensor _unwrap_functional_tensor(const Tensor& self) { | ||
| auto* functional = dynamic_cast<FunctionalTensorWrapper*>(self.unsafeGetTensorImpl()); |
There was a problem hiding this comment.
sorry for missing this the first time around :)
… view_copy operators"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
…tors"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
… view_copy operators"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
…tors"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
… view_copy operators"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
…tors"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
zou3519
left a comment
There was a problem hiding this comment.
Code LGTM.
This needs a rebase and I want to bikeshed the API and defaults a little more (maybe there shouldn't be a default yet)
299da47 to
d505afc
Compare
… view_copy operators"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
…tors"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
… view_copy operators"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
…tors"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
|
Pushed some more changes. Updates: (1) API bikeshed. I liked your suggestion of (2) I ended up killing the CI will fail on this PR though until my stack lands from pytorch/pytorch#75913 |
… view_copy operators"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
…tors"
This PR splits the functionalization codegen into 2 pieces:
(1) Vanilla functionalization will now always turn view ops into "view_copy" ops.
(2) For functorch to "reapply views underneath the pass", I added a new dispatch key, "FunctionalizeAddBackViews". I codegen a kernel to that key for every view_copy operator that just calls back into the view op. All other ops get a fallthrough kernel.
Also - the codegen will now unconditionally register CompositeImplicitAutograd kernels directly to the functionalization keys, so we "always decompose" before hitting functionalization. Otherwise, we might break and accidentally send "view" calls to the backend, if we decompose an op into a view underneath the functionalization pass.
The important changes are in `gen.py` and `gen_functionalization_type.py` - most of the other changes are just plumbing `{view}_copy` everywhere. I also updated `test_functionalization.py`, and added expecttests for the "add back views" case.
One thing about the `AddBackViews` key - right now, I add it into the TLS include set. The other option would be to try to add it directly to the tensors, but that's kind of hard: putting it on the `FunctionalTensorWrapper` doesn't help, because the functionalization pass will unwrap when it calls back into the dispatcher, and run on the "inner tensor" (maybe we could modify the inner tensor's keyset and add the `AddBackViews` key when functionalization happens, instead?)
I also have an accompanying functorch change here: pytorch/functorch#678
Differential Revision: [D35419652](https://our.internmc.facebook.com/intern/diff/D35419652)
[ghstack-poisoned]
zou3519
left a comment
There was a problem hiding this comment.
LGTM, you probably want to change the PR body (it still mentions FunctionalizeAddBackViews). Also it would be good to wait until the CI turns green
d505afc to
2660ec9
Compare
2660ec9 to
fb4ea78
Compare
|
@bdhirsh btw, functorch CI runs off of the PyTorch nightly binary, so we have two options:
|
|
Lol you probably saw me blindly kicking off CI again hoping something would happen (although at least I'm ok with either, depending on how urgently @ZolotukhinM would like this change for mobile |
fb4ea78 to
4d72d1b
Compare
|
CI is red, but I think I'm seeing the same set of test failures on main: https://app.circleci.com/pipelines/github/pytorch/functorch/2432/workflows/4657bb2a-cba6-4ce4-b409-e72e5229e3c4/jobs/14516/tests |
|
@bdhirsh feel free to merge, the errors look pre-existing and we'll figure them out as we go along today |
…eable (pytorch/functorch#678) * functionalize() move AddBackViews logic to a separate key * make functionalize() toggleable when adding back views * fix unnecessary view reapply, add tests for out= * fix * change functionalize() API, also use the new internal TLS * rebase and fix tests
…eable (pytorch/functorch#678) * functionalize() move AddBackViews logic to a separate key * make functionalize() toggleable when adding back views * fix unnecessary view reapply, add tests for out= * fix * change functionalize() API, also use the new internal TLS * rebase and fix tests
This PR goes with the core-side change here: pytorch/pytorch#75302, which updates the functionalization pass to be able to turn view ops into view_copy ops. Mobile mentioned that they would like to be able to use the
functionalize()transform to trace models for running on mobile, and removing view ops (cc @ZolotukhinM)This PR updates
functionalize()to be toggleable:functionalize(remove='mutations')(the default) will remove mutations but preserve views.functionalize(remove='mutations_and_views')will remove mutations, and additionally convertviewoperators into their correspondingview_copyoperators.Some extra stuff in the PR: