Skip to content

Conversation

pcuenca
Copy link
Member

@pcuenca pcuenca commented Mar 17, 2023

Experimental, not sure if there's a better way to do it. We'd also need to do something similar in modeling_utils.py.

Addresses #2709.

@HuggingFaceDocBuilderDev
Copy link

HuggingFaceDocBuilderDev commented Mar 17, 2023

The documentation is not available anymore as the PR was closed or merged.

@sayakpaul
Copy link
Member

I don't see other way around either.


# Dynamo wraps the original mode and changes the class.
# Is there a principled way to obtain the original class?
if "_dynamo.eval_frame" in str(model_cls):
Copy link
Contributor

Choose a reason for hiding this comment

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

Think that's a bit cleaner

Suggested change
if "_dynamo.eval_frame" in str(model_cls):
if is_torch_version(">=", "2.0.0") and isinstance(sub_model, torch._dynamo.eval_frame.OptimizedModule):

Copy link
Contributor

Choose a reason for hiding this comment

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

@pcuenca quick question - why don't we go for this API? Think isinstance is a better check here than the string checking

Copy link
Member Author

Choose a reason for hiding this comment

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

Because torch._dynamo is not available in all platforms, just on cuda builds.

Copy link
Contributor

@patrickvonplaten patrickvonplaten Mar 21, 2023

Choose a reason for hiding this comment

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

How about this then:

Suggested change
if "_dynamo.eval_frame" in str(model_cls):
if is_torch_version(">=", "2.0.0") and hasattr(torch, "_dynamo") and isinstance(sub_model, torch._dynamo.eval_frame.OptimizedModule):

Copy link
Member Author

Choose a reason for hiding this comment

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

It's a bit too verbose and distracting for my taste, specially if we are going to use it in multiple places. We could create a helper function somewhere. The other issue is that using a private symbol makes me uneasy about the class hierarchy changing in future revisions, making the code crash. Which is not necessarily bad, because if we use a string then we'd silently fail.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see! Tbh, both ways are fine by me - I do prefer to avoid silent errors and generally don't like string "in" testing for classes as this is a very brittle test in my opinion.

Would prefer a helper function here, but also ok to leave as is as it's an edge case.

Copy link
Contributor

@patrickvonplaten patrickvonplaten left a comment

Choose a reason for hiding this comment

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

Looks nice - thanks for the fix! Let's maybe do the same in modeling_utils.py. Would just recommend to use the isinstance(...) check instead of string matching check - think that's a bit less brittle.

The way you retrieve the original class here is good IMO

@pcuenca
Copy link
Member Author

pcuenca commented Mar 20, 2023

I created a simple test that unsurfaced additional problems in the configuration (the wrong class was saved to config.json).

Copy link
Member

@sayakpaul sayakpaul left a comment

Choose a reason for hiding this comment

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

Thanks!

register_dict = {name: (None, None)}
else:
# register the original module, not the dynamo compiled one
if "_dynamo.eval_frame" in str(module.__class__):
Copy link
Contributor

Choose a reason for hiding this comment

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

Think this check is better:

if is_torch_version(">=", "2.0.0") and isinstance(sub_model, torch._dynamo.eval_frame.OptimizedModule):

Copy link
Member Author

Choose a reason for hiding this comment

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

As commented above, torch._dynamo does not exist in all platforms.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah sorry, now I get it

# I didn't find a public API to get the original class.
sub_model = passed_class_obj[name]
model_cls = sub_model.__class__
if "_dynamo.eval_frame" in str(model_cls):
Copy link
Contributor

Choose a reason for hiding this comment

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

Think this check is better:

if is_torch_version(">=", "2.0.0") and isinstance(sub_model, torch._dynamo.eval_frame.OptimizedModule):

Copy link
Contributor

@patrickvonplaten patrickvonplaten left a comment

Choose a reason for hiding this comment

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

Can we apply the same changes to the model save_pretrained function?

@patrickvonplaten
Copy link
Contributor

Thanks for clarifying the design here. Could we then maybe go with: #2726 (comment) or do you prefer how it is now?

@pcuenca
Copy link
Member Author

pcuenca commented Mar 21, 2023

Can we apply the same changes to the model save_pretrained function?

It works, actually; at first I thought it wouldn't but I was wrong. When save_pretrained is invoked on a compiled model, self is the appropriate class and saving succeeds. I verified that the json file is correct and it refers to the right class. I also added a very small test case.

@pcuenca
Copy link
Member Author

pcuenca commented Mar 21, 2023

@patrickvonplaten so the only thing missing here would be to decide whether to use a helper function to verify the class. I'm undecided because I think that testing for a private class that might change is not very much better than testing for a name, but we might want to make it fail so we can fix it when it changes. What do you think?

Copy link
Contributor

@patrickvonplaten patrickvonplaten left a comment

Choose a reason for hiding this comment

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

Thanks! Summarized my thoughts here: https://github.com/huggingface/diffusers/pull/2726/files#r1146130475

Good to go whenever you want :-)

@pcuenca
Copy link
Member Author

pcuenca commented Mar 27, 2023

I used the helper function and I think it's ok, can one of you give it a final look before merge? @sayakpaul @patrickvonplaten

@sayakpaul
Copy link
Member

Nice! Looks clean to me :)

@pcuenca pcuenca merged commit 81125d8 into main Mar 28, 2023
@pcuenca pcuenca deleted the dynamo-save-pretrained branch March 28, 2023 07:03
w4ffl35 pushed a commit to w4ffl35/diffusers that referenced this pull request Apr 14, 2023
* Workaround for saving dynamo-wrapped models.

* Accept suggestion from code review

Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com>

* Apply workaround when overriding pipeline components.

* Ensure the correct config.json is saved to disk.

Instead of the dynamo class.

* Save correct module (not compiled one)

* Add test

* style

* fix docstrings

* Go back to using string comparisons.

PyTorch CPU does not have _dynamo.

* Simple test for save_pretrained of compiled models.

* Helper function to test whether module is compiled.

---------

Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com>
yoonseokjin pushed a commit to yoonseokjin/diffusers that referenced this pull request Dec 25, 2023
* Workaround for saving dynamo-wrapped models.

* Accept suggestion from code review

Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com>

* Apply workaround when overriding pipeline components.

* Ensure the correct config.json is saved to disk.

Instead of the dynamo class.

* Save correct module (not compiled one)

* Add test

* style

* fix docstrings

* Go back to using string comparisons.

PyTorch CPU does not have _dynamo.

* Simple test for save_pretrained of compiled models.

* Helper function to test whether module is compiled.

---------

Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com>
AmericanPresidentJimmyCarter pushed a commit to AmericanPresidentJimmyCarter/diffusers that referenced this pull request Apr 26, 2024
* Workaround for saving dynamo-wrapped models.

* Accept suggestion from code review

Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com>

* Apply workaround when overriding pipeline components.

* Ensure the correct config.json is saved to disk.

Instead of the dynamo class.

* Save correct module (not compiled one)

* Add test

* style

* fix docstrings

* Go back to using string comparisons.

PyTorch CPU does not have _dynamo.

* Simple test for save_pretrained of compiled models.

* Helper function to test whether module is compiled.

---------

Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com>
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.

4 participants