Skip to content
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

Fix and update type hints for make_functional.py #91579

Closed
wants to merge 4 commits into from

Conversation

XuehaiPan
Copy link
Collaborator

@XuehaiPan XuehaiPan commented Jan 2, 2023

Changes in details:

  • Fix and update some out-of-date type hints in _functorch/make_functional.py.

  • Explicitly use OrderedDict for order-sensitive mappings.

    In create_names_map(), _swap_state(), and FunctionalModuleWithBuffers.__init__(), the unordered dict was used. The key order should be preserved for dict.items() while it is required to zip with a tuple of params/buffers. Although since Python 3.6, the built-in dictionary is insertion ordered (PEP 468). Explicit is better than implicit.

cc @zou3519

@pytorch-bot
Copy link

pytorch-bot bot commented Jan 2, 2023

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/91579

Note: Links to docs will display an error until the docs builds have been completed.

✅ No Failures

As of commit bce866f:
💚 Looks good so far! There are no failures yet. 💚

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Jan 2, 2023

CLA Signed

The committers listed above are authorized under a signed CLA.

  • ✅ login: XuehaiPan / name: Xuehai Pan (524f59d)

@XuehaiPan XuehaiPan force-pushed the make-functional branch 2 times, most recently from 2afefe2 to 2329d7a Compare January 2, 2023 13:15
Copy link
Contributor

@zou3519 zou3519 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, @XuehaiPan. We should try to enable mypy checking for this file in PyTorch CI (to check the type hints and prevent regressions -- thanks for catching incorrect type annotations).

I don't buy using OrderedDict over dict here -- if you feel strongly about it, could we please leave it to a separate discussion?

Comment on lines 85 to 86
named_params = OrderedDict(named_params)
tied_named_params = OrderedDict(tied_named_params)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't buy the dict -> OrderedDict change:

  • Performance. OrderedDict has a different implementation than dict and there isn't a need to construct a new OrderedDict around a dict here.
  • As you mentioned, dict() is already ordered. As of Python 3.7, the language standard says that dict() is ordered. PyTorch does not support Python < 3.7, so there are no BC concerns.
  • consistency: I'd like to see buy in for "prefer OrderedDict to dict" in other parts of the PyTorch codebase.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't buy the dict -> OrderedDict change:

  • Performance. OrderedDict has a different implementation than dict and there isn't a need to construct a new OrderedDict around a dict here.
  • As you mentioned, dict() is already ordered. As of Python 3.7, the language standard says that dict() is ordered. PyTorch does not support Python < 3.7, so there are no BC concerns.

Let's pass on this since the language standard guarantees the insertion order for dict since Python 3.7. The builtin dict is faster for iteration.

In [1]: from collections import OrderedDict

In [2]: iterable = tuple((str(i), i) for i in range(100))

In [3]: %timeit dict(iterable)
2.37 µs ± 20.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

In [4]: %timeit OrderedDict(iterable)
8.42 µs ± 86.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

In [5]: d = dict(iterable)

In [6]: od = OrderedDict(iterable)

In [7]: %timeit list(d.items())
2.41 µs ± 83.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

In [8]: %timeit list(od.items())
4.05 µs ± 87.4 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
  • consistency: I'd like to see buy in for "prefer OrderedDict to dict" in other parts of the PyTorch codebase.

super().__setattr__('training', True)
super().__setattr__('_parameters', OrderedDict())
super().__setattr__('_buffers', OrderedDict())
super().__setattr__('_non_persistent_buffers_set', set())
super().__setattr__('_backward_pre_hooks', OrderedDict())
super().__setattr__('_backward_hooks', OrderedDict())
super().__setattr__('_is_full_backward_hook', None)
super().__setattr__('_forward_hooks', OrderedDict())
super().__setattr__('_forward_hooks_with_kwargs', OrderedDict())
super().__setattr__('_forward_pre_hooks', OrderedDict())
super().__setattr__('_forward_pre_hooks_with_kwargs', OrderedDict())
super().__setattr__('_state_dict_hooks', OrderedDict())
super().__setattr__('_state_dict_pre_hooks', OrderedDict())
super().__setattr__('_load_state_dict_pre_hooks', OrderedDict())
super().__setattr__('_load_state_dict_post_hooks', OrderedDict())
super().__setattr__('_modules', OrderedDict())

The attributes in nn.Module, such as _paramters, _buffers, _modules are stored as OrderedDict.

Note that, del and set attribute in _swap_state changes the order of items in _paramters and _buffers. (del + set is equivalent to move_to_end())

def _swap_state(mod: nn.Module, names_map: List[str], elems):
result = []
for (_, attr_names), elem in zip(names_map.items(), elems):
for i, attr_name in enumerate(attr_names):
if i == 0:
result.append(_get_nested_attr(mod, attr_name))
_del_nested_attr(mod, attr_name)
_set_nested_attr(mod, attr_name, elem)
return result

@XuehaiPan XuehaiPan force-pushed the make-functional branch 5 times, most recently from 9ea0f0e to dd122d2 Compare January 4, 2023 10:47
Copy link
Contributor

@zou3519 zou3519 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you!

@XuehaiPan
Copy link
Collaborator Author

@zou3519 Hi, any update for this PR? I opened a follow-up PR in #92218 which may share some relevant changes.

@kshitij12345
Copy link
Collaborator

Once approved by a PyTorch maintainer, you can trigger the merge yourself by commenting @pytorchbot merge.

More ref about the pytorchbot: https://github.com/pytorch/pytorch/wiki/Bot-commands

@XuehaiPan
Copy link
Collaborator Author

@pytorchbot merge

@pytorch-bot pytorch-bot bot added the ciflow/trunk Trigger trunk jobs on your pull request label Jan 18, 2023
@pytorchmergebot
Copy link
Collaborator

Merge started

Your 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

Advanced Debugging
Check the merge workflow status
here

@pytorchmergebot
Copy link
Collaborator

Merge failed

Reason: This PR is too stale; the last push date was more than 3 days ago. Please rebase and try again. You can rebase by leaving the following comment on this PR:
@pytorchbot rebase

Details for Dev Infra team Raised by workflow job

@XuehaiPan
Copy link
Collaborator Author

@pytorchbot rebase

@XuehaiPan
Copy link
Collaborator Author

@pytorchbot merge

@pytorchmergebot
Copy link
Collaborator

@pytorchbot successfully started a rebase job. Check the current status here

@pytorchmergebot
Copy link
Collaborator

Successfully rebased make-functional onto refs/remotes/origin/viable/strict, please pull locally before adding more changes (for example, via git checkout make-functional && git pull --rebase)

@pytorchmergebot
Copy link
Collaborator

Merge started

Your 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

Advanced Debugging
Check the merge workflow status
here

@pytorchmergebot
Copy link
Collaborator

The merge job was canceled. If you believe this is a mistake,then you can re trigger it through pytorch-bot.

@XuehaiPan
Copy link
Collaborator Author

@pytorchbot merge

@pytorchmergebot
Copy link
Collaborator

Merge started

Your 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

Advanced Debugging
Check the merge workflow status
here

@XuehaiPan XuehaiPan deleted the make-functional branch January 18, 2023 19:25
pytorchmergebot pushed a commit that referenced this pull request Feb 8, 2023
…#92536)

- Fixes #92295
- Resolves #86708
- Resolves #92153
- Closes #92401
- Closes #92218

- Requires #91579

Refactor NN stateless APIs by swapping module tensors.

Pull Request resolved: #92536
Approved by: https://github.com/jbschlosser
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ciflow/trunk Trigger trunk jobs on your pull request Merged open source
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants