-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Pipeline to device #210
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
Pipeline to device #210
Conversation
Note that pipelines will still be moved to the default cuda device during `__call__` unless the same device is used there. Addressing that in a separate commit.
The following will run the pipeline in cuda:1 (not cuda:0) as expected: ```Python pipe = StableDiffusionPipeline.from_pretrained( "CompVis/stable-diffusion-v1-3-diffusers", use_auth_token=True).to("cuda:1") pipe("Some prompt") ``` I debated whether to place this logic in `DiffusionPipeline.to()`. It would make for much simpler code in all pipeline implementations (they just need to invoke `self.to`), but might break the expectations of PyTorch users, where AFAIK using `to(None)` does not move the object anywhere.
The documentation is not available anymore as the PR was closed or merged. |
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.
Thanks for the PR @pcuenca!
Haven't seen cases of .to(None)
in the wild before, so to me it's fine to break the expectations a bit :)
So implementing it like this:
def to(self, torch_device: Optional[Union[str, torch.device]] = None):
if torch_device is None:
torch_device = "cuda" if torch.cuda.is_available() else "cpu"
...
And then just doing self.to(torch_device)
inside the pipelines would be much cleaner and less implementation error-prone for future pipelines
Cool, I agree! That's how I would have done it if it had been for an internal project. Because it's open source, I might have been extremely cautious here :)
One thing, though. If we expect users to use I'll prepare it right away so you can take a look. |
@anton-l not super happy after the change, |
Hmm, indeed. But choosing between the first version and this one, I would still go with the current |
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.
Throwing in an idea -> we could also just remove torch_device
as in input to the forward function. It's more "PyTorch'y" to use the .to(...)
API IMO.
So we could just deprecate the "torch_device"
parameter, saying that it'll be removed in 0.3.0
and only rely on to(...)
.
What do you think?
I think that's a very sensible idea. But I also love that if you do nothing it woks as expected (uses cuda if available), so we'd do an automatic placement on creation. Does that sound right? |
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.
Thanks a lot for the PR @pcuenca !
I agree with @patrickvonplaten about removing the torch_device
argument. Would be nice to have just one API for device handling, rather than having both options. That would be much cleaner IMO.
I'd actually say to not do an automatic displacement to really stay 1-to-1 the same as PyTorch. I really like the fact that you know in PyTorch models are always on "cpu" by default. @anton-l @patil-suraj what do you think? |
That's a breaking change with respect to the current version. No big deal, and it's easy to understand in terms of PyTorch resemblance. I personally liked that you had to do nothing and the pipeline selected the GPU by default; to me, the pipeline is a high-level solution that is there to help you by providing sensible defaults. Similar to disabling gradients computation. But the alternatives are a bit feeble, so this might well be the best compromise. |
+1 it is indeed a bigger breaking change. For me, one of the two options sounds like the best: 1.) 2.) @patil-suraj @anton-l @pcuenca - let's maybe try to decide somewhat quickly now so that we can include this PR in today's release? |
I'm in favor of option 1 out of what Patrick suggested. |
Thinking a bit more about it, I'm actually much more for option 2, mainly because:
Happy to adhere to 1. though if @patil-suraj @anton-l and @pcuenca you prefer |
Those are great points, @patrickvonplaten, let's go for the simpler option and do |
Ok, good points, option 2 it is! :) |
I'm also very much in favor of 2. with |
`pipeline.to()` now has PyTorch semantics.
I did We possibly need to change some documentation and examples. Should we do that in a separate PR? |
Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com>
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.
Looking good! Pretty much the same comment as @anton-l and @patrickvonplaten .
Also think thekwargs
should go in all pipelines.
"`torch_device` is deprecated as an input argument to `__call__` and will be removed in v0.3.0. | ||
Consider using `pipe.to(torch_device)` instead." | ||
) | ||
# ...set device as previously |
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.
(nit) this comment should go above the if cond
Yes, |
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.
Looks great!
Ok, let's resolve the conflicts and merge if @patrickvonplaten and @patil-suraj don't have any objections :) |
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.
Looks good to me! @anton-l feel free to merge!
Sure, no problem at all, that's what I understood :) |
Sorry, I have family business going on and can't fix the conflicts right now. Can you do it @anton-l ?, otherwise I'll do it later. |
* Implement `pipeline.to(device)` * DiffusionPipeline.to() decides best device on None. * Breaking change: torch_device removed from __call__ `pipeline.to()` now has PyTorch semantics. * Use kwargs and deprecation notice Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com> * Apply torch_device compatibility to all pipelines. * style Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com> Co-authored-by: anton-l <anton@huggingface.co>
The PyTorch decomposition for the op `aten.upsample_bilinear2d.vec` is merged in the upstream repo and hence removed from this file.
* Implement `pipeline.to(device)` * DiffusionPipeline.to() decides best device on None. * Breaking change: torch_device removed from __call__ `pipeline.to()` now has PyTorch semantics. * Use kwargs and deprecation notice Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com> * Apply torch_device compatibility to all pipelines. * style Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com> Co-authored-by: anton-l <anton@huggingface.co>
The following will run the pipeline in
cuda:1
(notcuda:0
) as would be expected:However, passing a device to
__call__
will still move the pipeline to that device.The implementation of
DiffusionPipeline.to()
does nothing if the device isNone
. This is to preserve the same semantics as PyTorch, where AFAIK if you useto(None)
the object is not moved anywhere.If we were to forgo that behaviour, we could make
DiffusionPipeline.to(None)
selectcuda
by default (when available). This would make for much simpler code in all pipeline implementations, as they'd just need to invokeself.to
, but might break the expectations of PyTorch users. The current implementation in all the pipelines__call__
methods does exactly that: selectcuda
if available, and if no previous device was already set by the user. It is a bit repetitive and maybe a bit fragile.Is it important to preserve PyTorch semantics in this regard, or is it better to make all
__call__
implementations simpler? What do you think @anton-l @patil-suraj @patrickvonplaten ?Fixes #195