-
Couldn't load subscription status.
- Fork 25.7k
[pytree] Remove LeafSpec construction cost in tree_flatten #112392
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
Conversation
On my machine, `pytree.LeafSpec()` takes ~600ns but since every leaf spec is the same, we can just use a global constant. [ghstack-poisoned]
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/112392
Note: Links to docs will display an error until the docs builds have been completed. ✅ No FailuresAs of commit e44f847 with merge base 29844ad ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
On my machine, `pytree.LeafSpec()` takes ~600ns but since every leaf spec is the same, we can just use a global constant. ghstack-source-id: 05cff54 Pull Request resolved: pytorch#112392
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.
Fine, but I reckon that we shouldn't invest that much time in optimising this implementation, as we are working towards moving to optree. See the stack #112110 and more generally the work of the author of those PRs
|
@XuehaiPan I see that some parts of the codebase already use |
|
In the short to medium term, both the python and C++ pytree (optree) will be relevant. Open question for the longer term (we likely will need to keep around the python pytree implementation so that Dynamo can trace through it) |
|
@pytorchbot merge |
Merge failedReason: This PR needs a If not, please add the To add a label, you can comment to pytorchbot, for example For more information, see Details for Dev Infra teamRaised by workflow job |
|
@pytorchbot merge |
Merge startedYour change will be merged once all checks pass (ETA 0-4 Hours). Learn more about merging in the wiki. Questions? Feedback? Please reach out to the PyTorch DevX Team |
#112393) We commonly do some variation of `tree_leaves((args, kwargs))`. This adds a new function `arg_tree_leaves(*args, **kwargs)` which takes advantage of the known structure of `args` and `kwargs` to skip their `flatten_fn`. I see ~1 us improvement per call for args + kwargs, or a 0.5 us improvement when passing just one of `args` or `kwargs`. For shallow structures, this can be proportionally quite significant. For example, the empty_strided call I've been using as a benchmark: ``` args = ((100, 100), (100, 1)) kwargs = dict(device="cuda") ``` Sees a 30% speedup from this. Pull Request resolved: #112393 Approved by: https://github.com/lezcano ghstack dependencies: #112391, #112392
Pull Request resolved: #112394 Approved by: https://github.com/lezcano ghstack dependencies: #112391, #112392, #112393
…12392) On my machine, `pytree.LeafSpec()` takes ~600ns but since every leaf spec is the same, we can just use a global constant. Pull Request resolved: pytorch#112392 Approved by: https://github.com/lezcano ghstack dependencies: pytorch#112391
pytorch#112393) We commonly do some variation of `tree_leaves((args, kwargs))`. This adds a new function `arg_tree_leaves(*args, **kwargs)` which takes advantage of the known structure of `args` and `kwargs` to skip their `flatten_fn`. I see ~1 us improvement per call for args + kwargs, or a 0.5 us improvement when passing just one of `args` or `kwargs`. For shallow structures, this can be proportionally quite significant. For example, the empty_strided call I've been using as a benchmark: ``` args = ((100, 100), (100, 1)) kwargs = dict(device="cuda") ``` Sees a 30% speedup from this. Pull Request resolved: pytorch#112393 Approved by: https://github.com/lezcano ghstack dependencies: pytorch#112391, pytorch#112392
Pull Request resolved: pytorch#112394 Approved by: https://github.com/lezcano ghstack dependencies: pytorch#112391, pytorch#112392, pytorch#112393
Wherever we discard the output of `tree_map` it's better to call `tree_map_` which doesn't unflatten the mapped results and so is a lot cheaper. Pull Request resolved: pytorch#112417 Approved by: https://github.com/lezcano ghstack dependencies: pytorch#112391, pytorch#112392, pytorch#112393, pytorch#112394
…12392) On my machine, `pytree.LeafSpec()` takes ~600ns but since every leaf spec is the same, we can just use a global constant. Pull Request resolved: pytorch#112392 Approved by: https://github.com/lezcano ghstack dependencies: pytorch#112391
pytorch#112393) We commonly do some variation of `tree_leaves((args, kwargs))`. This adds a new function `arg_tree_leaves(*args, **kwargs)` which takes advantage of the known structure of `args` and `kwargs` to skip their `flatten_fn`. I see ~1 us improvement per call for args + kwargs, or a 0.5 us improvement when passing just one of `args` or `kwargs`. For shallow structures, this can be proportionally quite significant. For example, the empty_strided call I've been using as a benchmark: ``` args = ((100, 100), (100, 1)) kwargs = dict(device="cuda") ``` Sees a 30% speedup from this. Pull Request resolved: pytorch#112393 Approved by: https://github.com/lezcano ghstack dependencies: pytorch#112391, pytorch#112392
Pull Request resolved: pytorch#112394 Approved by: https://github.com/lezcano ghstack dependencies: pytorch#112391, pytorch#112392, pytorch#112393
Wherever we discard the output of `tree_map` it's better to call `tree_map_` which doesn't unflatten the mapped results and so is a lot cheaper. Pull Request resolved: pytorch#112417 Approved by: https://github.com/lezcano ghstack dependencies: pytorch#112391, pytorch#112392, pytorch#112393, pytorch#112394
Stack from ghstack (oldest at bottom):
pytree.tree_map_everywhere #112417pytree.arg_tree_leaveseverywhere #112394On my machine,
pytree.LeafSpec()takes ~600ns but since every leaf spec is thesame, we can just use a global constant.
cc @zou3519 @XuehaiPan @jon-chuang