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] allow saving python attr on Tensor and Parameter via torch.save #81616

Closed

Conversation

kshitij12345
Copy link
Collaborator

@kshitij12345 kshitij12345 commented Jul 17, 2022

Fixes: #72129

TODO:

  • Fix for Parameter

Benchmark
(Measurable diff for small tensors)

[-------------- Save and Load --------------]
                    |  After PR  |  Before PR
1 threads: ----------------------------------
      ()            |    111.7   |     106.9 
      (4, 4)        |    114.4   |     109.2 
      (128, 128)    |    135.2   |     128.3 
      (1024, 1024)  |   1431.9   |    1431.3 

Times are in microseconds (us).
Benchmark Script
import torch
from torch.testing._internal.common_utils import BytesIOContext
from torch.utils import benchmark
import pickle

shapes = ((), (4, 4), (128, 128), (1024, 1024))

sizes = [1, 64, 1024, 10000]
results = []

def save_load_fn(t):
    with BytesIOContext() as f:
        torch.save(t, f)
        f.seek(0)
        torch.load(f)

for shape in shapes:
    t = torch.randn(shape)
    label = 'Save and Load'
    sub_label = f'{shape}'
    results.append(benchmark.Timer(
        stmt='save_load_fn(t)',
        globals={'t': t, 'save_load_fn':save_load_fn},
        label=label,
        sub_label=sub_label,
        description='Before PR',
    ).blocked_autorange(min_run_time=2))

compare = benchmark.Compare(results)
compare.print()

with open('before_pr.pkl', 'wb') as f:
    pickle.dump(results, f)

# with open('after_pr.pkl', 'rb') as f:
#     after_pr = pickle.load(f)

# with open('before_pr.pkl', 'rb') as f:
#     before_pr = pickle.load(f)

# compare = benchmark.Compare(after_pr + before_pr)
# compare.print()

NOTE : BC-Breaking : After this PR, all tensors (also regular tensors) will be serialised using _rebuild_from_type_v2.

cc @ezyang @gchanan

@facebook-github-bot
Copy link
Contributor

facebook-github-bot commented Jul 17, 2022

🔗 Helpful links

✅ No Failures (0 Pending)

As of commit 9edff6b (more details on the Dr. CI page):

Expand to see more

💚 💚 Looks good so far! There are no failures yet. 💚 💚


This comment was automatically generated by Dr. CI (expand for details).

Please report bugs/suggestions to the (internal) Dr. CI Users group.

Click here to manually regenerate this comment.

@kshitij12345 kshitij12345 changed the title [fix] allow saving python attr via torch.save [fix] allow saving python attr on Tensor via torch.save Jul 17, 2022
@kshitij12345 kshitij12345 changed the title [fix] allow saving python attr on Tensor via torch.save [fix] allow saving python attr on Tensor and Parameter via torch.save Jul 17, 2022
@kshitij12345 kshitij12345 marked this pull request as ready for review July 17, 2022 18:24
@bdhirsh bdhirsh added the triaged This issue has been looked at a team member, and triaged and prioritized into an appropriate module label Jul 20, 2022
Copy link
Collaborator

@albanD albanD 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 this fix! This code is way too complex :(
Only small nits

torch/_utils.py Outdated
param._backward_hooks = backward_hooks

# Restore state on Parameter like python attr.
param = torch._utils._set_obj_state(param, state)
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit no need for the torch._utils here as it is the current file

torch/_tensor.py Outdated
if type(self) is Tensor:
return self._reduce_ex_internal(proto)
if has_torch_function_unary(self):
if type(self) is not Tensor and has_torch_function_unary(self):
Copy link
Collaborator

Choose a reason for hiding this comment

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

has_torch_function_unary should always be False for regular Tensor. So the first part is not needed.

@kshitij12345
Copy link
Collaborator Author

@pytorchbot merge -g

@pytorchmergebot
Copy link
Collaborator

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

@github-actions
Copy link

Hey @kshitij12345.
You've committed this PR, but it does not have both a 'release notes: ...' and 'topics: ...' label. Please add one of each to the PR. The 'release notes: ...' label should represent the part of PyTorch that this PR changes (fx, autograd, distributed, etc) and the 'topics: ...' label should represent the kind of PR it is (not user facing, new feature, bug fix, perf improvement, etc). The list of valid labels can be found here for the 'release notes: ...' and here for the 'topics: ...'.
For changes that are 'topic: not user facing' there is no need for a release notes label.

@jeanschmidt
Copy link
Contributor

this commit breaks internal tests/builds - https://pastebin.com/fU9T0NMd https://pastebin.com/1fwiE9ZU

@jeanschmidt
Copy link
Contributor

@pytorchbot revert -m "breaking internal builds" -c "ghfirst"

@albanD
Copy link
Collaborator

albanD commented Jul 21, 2022

@jeanschmidt the first one seems to be a network error?

@pytorchmergebot
Copy link
Collaborator

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

@pytorchmergebot
Copy link
Collaborator

@kshitij12345 your PR has been successfully reverted.

pytorchmergebot added a commit that referenced this pull request Jul 21, 2022
…rch.save (#81616)"

This reverts commit f3f8d96.

Reverted #81616 on behalf of https://github.com/jeanschmidt due to breaking internal builds
@albanD
Copy link
Collaborator

albanD commented Jul 21, 2022

@jeanschmidt not sure what to do with the recond one. Is there any instruction to repro this?

@jeanschmidt
Copy link
Contributor

jeanschmidt commented Jul 21, 2022

Yeah, the first one seems to be an internal issue in the build system, the 2nd one seems to be the process dying while running tests (throwing some generic exception :( ).

I believe you don't have access to the code to reproduce it right?

torch/_utils.py Outdated Show resolved Hide resolved
@ezyang
Copy link
Contributor

ezyang commented Nov 11, 2022

If there aren't any Python attributes, it would also be smart to use the old builder function for FC

@kshitij12345
Copy link
Collaborator Author

If there aren't any Python attributes, it would also be smart to use the old builder function for FC

Right!! Now we only dispatch to the new builders only if the state is present. So this should take care of compatibility! Thank you!

Copy link
Collaborator

@albanD albanD left a comment

Choose a reason for hiding this comment

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

This is not FC if the user saves a Tensor with state though?

@ezyang
Copy link
Contributor

ezyang commented Nov 11, 2022

Yes, there is still breakage if there are Python attributes. But there's no way around this, except maybe a kwarg on save that lets you bypass saving python attrs

@albanD
Copy link
Collaborator

albanD commented Nov 11, 2022

Yes, there is still breakage if there are Python attributes. But there's no way around this, except maybe a kwarg on save that lets you bypass saving python attrs

No we will warn but not break on the C++ side.
The problem here is that even in python this will break today. We do want the FC window.

Copy link
Collaborator

@albanD albanD left a comment

Choose a reason for hiding this comment

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

SGTM

@kshitij12345
Copy link
Collaborator Author

@albanD would you be importing it for internal tests? Or is it ok to merge it once CI is green?

@albanD
Copy link
Collaborator

albanD commented Nov 11, 2022

This can't be tested internally as it breaks when publishing. So let's go with this as-is!

@kshitij12345
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

pytorchmergebot pushed a commit that referenced this pull request Nov 29, 2022
kulinseth pushed a commit to kulinseth/pytorch that referenced this pull request Dec 10, 2022
…pytorch#81616)

Fixes: pytorch#72129

TODO:
* [x] Fix for Parameter

Benchmark
(Measurable diff for small tensors)
```
[-------------- Save and Load --------------]
                    |  After PR  |  Before PR
1 threads: ----------------------------------
      ()            |    111.7   |     106.9
      (4, 4)        |    114.4   |     109.2
      (128, 128)    |    135.2   |     128.3
      (1024, 1024)  |   1431.9   |    1431.3

Times are in microseconds (us).
```

<details>

<summary> Benchmark Script </summary>

```python
import torch
from torch.testing._internal.common_utils import BytesIOContext
from torch.utils import benchmark
import pickle

shapes = ((), (4, 4), (128, 128), (1024, 1024))

sizes = [1, 64, 1024, 10000]
results = []

def save_load_fn(t):
    with BytesIOContext() as f:
        torch.save(t, f)
        f.seek(0)
        torch.load(f)

for shape in shapes:
    t = torch.randn(shape)
    label = 'Save and Load'
    sub_label = f'{shape}'
    results.append(benchmark.Timer(
        stmt='save_load_fn(t)',
        globals={'t': t, 'save_load_fn':save_load_fn},
        label=label,
        sub_label=sub_label,
        description='Before PR',
    ).blocked_autorange(min_run_time=2))

compare = benchmark.Compare(results)
compare.print()

with open('before_pr.pkl', 'wb') as f:
    pickle.dump(results, f)

# with open('after_pr.pkl', 'rb') as f:
#     after_pr = pickle.load(f)

# with open('before_pr.pkl', 'rb') as f:
#     before_pr = pickle.load(f)

# compare = benchmark.Compare(after_pr + before_pr)
# compare.print()
```

</details>

NOTE : **BC-Breaking** : After this PR, all tensors (also regular tensors) will be serialised using `_rebuild_from_type_v2`.

Pull Request resolved: pytorch#81616
Approved by: https://github.com/albanD, https://github.com/kurtamohler
kulinseth pushed a commit to kulinseth/pytorch that referenced this pull request Dec 10, 2022
…rch.save (pytorch#81616)"

This reverts commit 54b6188.

Reverted pytorch#81616 on behalf of https://github.com/mehtanirav due to Internal publishing is broken
kulinseth pushed a commit to kulinseth/pytorch that referenced this pull request Dec 10, 2022
…pytorch#81616)

Fixes: pytorch#72129

TODO:
* [x] Fix for Parameter

Benchmark
(Measurable diff for small tensors)
```
[-------------- Save and Load --------------]
                    |  After PR  |  Before PR
1 threads: ----------------------------------
      ()            |    111.7   |     106.9
      (4, 4)        |    114.4   |     109.2
      (128, 128)    |    135.2   |     128.3
      (1024, 1024)  |   1431.9   |    1431.3

Times are in microseconds (us).
```

<details>

<summary> Benchmark Script </summary>

```python
import torch
from torch.testing._internal.common_utils import BytesIOContext
from torch.utils import benchmark
import pickle

shapes = ((), (4, 4), (128, 128), (1024, 1024))

sizes = [1, 64, 1024, 10000]
results = []

def save_load_fn(t):
    with BytesIOContext() as f:
        torch.save(t, f)
        f.seek(0)
        torch.load(f)

for shape in shapes:
    t = torch.randn(shape)
    label = 'Save and Load'
    sub_label = f'{shape}'
    results.append(benchmark.Timer(
        stmt='save_load_fn(t)',
        globals={'t': t, 'save_load_fn':save_load_fn},
        label=label,
        sub_label=sub_label,
        description='Before PR',
    ).blocked_autorange(min_run_time=2))

compare = benchmark.Compare(results)
compare.print()

with open('before_pr.pkl', 'wb') as f:
    pickle.dump(results, f)

# with open('after_pr.pkl', 'rb') as f:
#     after_pr = pickle.load(f)

# with open('before_pr.pkl', 'rb') as f:
#     before_pr = pickle.load(f)

# compare = benchmark.Compare(after_pr + before_pr)
# compare.print()
```

</details>

NOTE : **BC-Breaking** : After this PR, all tensors (also regular tensors) will be serialised using `_rebuild_from_type_v2`.

Pull Request resolved: pytorch#81616
Approved by: https://github.com/albanD, https://github.com/kurtamohler
kulinseth pushed a commit to kulinseth/pytorch that referenced this pull request Dec 10, 2022
pytorchmergebot pushed a commit that referenced this pull request Jan 13, 2023
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 cla signed Merged module: bc-breaking Related to a BC-breaking change open source release notes: jit release notes category Reverted topic: bc breaking topic category triaged This issue has been looked at a team member, and triaged and prioritized into an appropriate module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

torch.save does not save python attributes attached to Tensors or Parameters