default fast model loading 🔥 (#1115) · ctsims/diffusers@7482178 · GitHub
Skip to content

Commit 7482178

Browse files
patil-surajpatrickvonplatenanton-l
authored
default fast model loading 🔥 (huggingface#1115)
* make accelerate hard dep * default fast init * move params to cpu when device map is None * handle device_map=None * handle torch < 1.9 * remove device_map="auto" * style * add accelerate in torch extra * remove accelerate from extras["test"] * raise an error if torch is available but not accelerate * update installation docs * Apply suggestions from code review Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com> * improve defautl loading speed even further, allow disabling fats loading * address review comments * adapt the tests * fix test_stable_diffusion_fast_load * fix test_read_init * temp fix for dummy checks * Trigger Build * Apply suggestions from code review Co-authored-by: Anton Lozhkov <anton@huggingface.co> Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com> Co-authored-by: Anton Lozhkov <anton@huggingface.co>
1 parent ef2ea33 commit 7482178

23 files changed

Lines changed: 564 additions & 109 deletions

‎README.md‎

Lines changed: 13 additions & 3 deletions

‎docs/source/installation.mdx‎

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ specific language governing permissions and limitations under the License.
1212

1313
# Installation
1414

15-
Install Diffusers for with PyTorch. Support for other libraries will come in the future
15+
Install 🤗 Diffusers for whichever deep learning library you’re working with.
1616

17-
🤗 Diffusers is tested on Python 3.7+, and PyTorch 1.7.0+.
17+
🤗 Diffusers is tested on Python 3.7+, PyTorch 1.7.0+ and flax. Follow the installation instructions below for the deep learning library you are using:
18+
19+
- [PyTorch](https://pytorch.org/get-started/locally/) installation instructions.
20+
- [Flax](https://flax.readthedocs.io/en/latest/) installation instructions.
1821

1922
## Install with pip
2023

@@ -36,12 +39,30 @@ source .env/bin/activate
3639

3740
Now you're ready to install 🤗 Diffusers with the following command:
3841

42+
**For PyTorch**
43+
44+
```bash
45+
pip install diffusers["torch"]
46+
```
47+
48+
**For Flax**
49+
3950
```bash
40-
pip install diffusers
51+
pip install diffusers["flax"]
4152
```
4253

4354
## Install from source
4455

56+
Before intsalling `diffusers` from source, make sure you have `torch` and `accelerate` installed.
57+
58+
For `torch` installation refer to the `torch` [docs](https://pytorch.org/get-started/locally/#start-locally).
59+
60+
To install `accelerate`
61+
62+
```bash
63+
pip install accelerate
64+
```
65+
4566
Install 🤗 Diffusers from source with the following command:
4667

4768
```bash
@@ -67,7 +88,18 @@ Clone the repository and install 🤗 Diffusers with the following commands:
6788
```bash
6889
git clone https://github.com/huggingface/diffusers.git
6990
cd diffusers
70-
pip install -e .
91+
```
92+
93+
**For PyTorch**
94+
95+
```
96+
pip install -e ".[torch]"
97+
```
98+
99+
**For Flax**
100+
101+
```
102+
pip install -e ".[flax]"
71103
```
72104

73105
These commands will link the folder you cloned the repository to and your Python library paths.

‎setup.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,6 @@ def run(self):
178178
extras["docs"] = deps_list("hf-doc-builder")
179179
extras["training"] = deps_list("accelerate", "datasets", "tensorboard", "modelcards")
180180
extras["test"] = deps_list(
181-
"accelerate",
182181
"datasets",
183182
"parameterized",
184183
"pytest",
@@ -188,7 +187,7 @@ def run(self):
188187
"torchvision",
189188
"transformers"
190189
)
191-
extras["torch"] = deps_list("torch")
190+
extras["torch"] = deps_list("torch", "accelerate")
192191

193192
if os.name == "nt": # windows
194193
extras["flax"] = [] # jax is not supported on windows

‎src/diffusers/__init__.py‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .utils import (
2+
is_accelerate_available,
23
is_flax_available,
34
is_inflect_available,
45
is_onnx_available,
@@ -16,6 +17,13 @@
1617
from .utils import logging
1718

1819

20+
# This will create an extra dummy file "dummy_torch_and_accelerate_objects.py"
21+
# TODO: (patil-suraj, anton-l) maybe import everything under is_torch_and_accelerate_available
22+
if is_torch_available() and not is_accelerate_available():
23+
error_msg = "Please install the `accelerate` library to use Diffusers with PyTorch. You can do so by running `pip install diffusers[torch]`. Or if torch is already installed, you can run `pip install accelerate`." # noqa: E501
24+
raise ImportError(error_msg)
25+
26+
1927
if is_torch_available():
2028
from .modeling_utils import ModelMixin
2129
from .models import AutoencoderKL, Transformer2DModel, UNet1DModel, UNet2DConditionModel, UNet2DModel, VQModel

‎src/diffusers/modeling_utils.py‎

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
import torch
2222
from torch import Tensor, device
2323

24-
from diffusers.utils import is_accelerate_available
24+
import accelerate
25+
from accelerate.utils import set_module_tensor_to_device
26+
from accelerate.utils.versions import is_torch_version
2527
from huggingface_hub import hf_hub_download
2628
from huggingface_hub.utils import EntryNotFoundError, RepositoryNotFoundError, RevisionNotFoundError
2729
from requests import HTTPError
@@ -268,6 +270,19 @@ def from_pretrained(cls, pretrained_model_name_or_path: Optional[Union[str, os.P
268270
Mirror source to accelerate downloads in China. If you are from China and have an accessibility
269271
problem, you can set this option to resolve it. Note that we do not guarantee the timeliness or safety.
270272
Please refer to the mirror site for more information.
273+
device_map (`str` or `Dict[str, Union[int, str, torch.device]]`, *optional*):
274+
A map that specifies where each submodule should go. It doesn't need to be refined to each
275+
parameter/buffer name, once a given module name is inside, every submodule of it will be sent to the
276+
same device.
277+
278+
To have Accelerate compute the most optimized `device_map` automatically, set `device_map="auto"`. For
279+
more information about each option see [designing a device
280+
map](https://hf.co/docs/accelerate/main/en/usage_guides/big_modeling#designing-a-device-map).
281+
fast_load (`bool`, *optional*, defaults to `True`):
282+
Speed up model loading by not initializing the weights and only loading the pre-trained weights. This
283+
also tries to not use more than 1x model size in CPU memory (including peak memory) while loading the
284+
model. This is only supported when torch version >= 1.9.0. If you are using an older version of torch,
285+
this argument will be ignored and the model will be loaded normally.
271286
272287
<Tip>
273288
@@ -296,6 +311,16 @@ def from_pretrained(cls, pretrained_model_name_or_path: Optional[Union[str, os.P
296311
torch_dtype = kwargs.pop("torch_dtype", None)
297312
subfolder = kwargs.pop("subfolder", None)
298313
device_map = kwargs.pop("device_map", None)
314+
fast_load = kwargs.pop("fast_load", True)
315+
316+
# Check if we can handle device_map and dispatching the weights
317+
if device_map is not None and not is_torch_version(">=", "1.9.0"):
318+
raise NotImplementedError("Loading and dispatching requires torch >= 1.9.0")
319+
320+
# Fast init is only possible if torch version is >= 1.9.0
321+
_INIT_EMPTY_WEIGHTS = fast_load or device_map is not None
322+
if _INIT_EMPTY_WEIGHTS and not is_torch_version(">=", "1.9.0"):
323+
logger.warn("Loading with `fast_load` requires torch >= 1.9.0. Falling back to normal loading.")
299324

300325
user_agent = {
301326
"diffusers": __version__,
@@ -378,12 +403,8 @@ def from_pretrained(cls, pretrained_model_name_or_path: Optional[Union[str, os.P
378403

379404
# restore default dtype
380405

381-
if device_map == "auto":
382-
if is_accelerate_available():
383-
import accelerate
384-
else:
385-
raise ImportError("Please install accelerate via `pip install accelerate`")
386-
406+
if _INIT_EMPTY_WEIGHTS:
407+
# Instantiate model with empty weights
387408
with accelerate.init_empty_weights():
388409
model, unused_kwargs = cls.from_config(
389410
config_path,
@@ -400,7 +421,17 @@ def from_pretrained(cls, pretrained_model_name_or_path: Optional[Union[str, os.P
400421
**kwargs,
401422
)
402423

403-
accelerate.load_checkpoint_and_dispatch(model, model_file, device_map)
424+
# if device_map is Non,e load the state dict on move the params from meta device to the cpu
425+
if device_map is None:
426+
param_device = "cpu"
427+
state_dict = load_state_dict(model_file)
428+
# move the parms from meta device to cpu
429+
for param_name, param in state_dict.items():
430+
set_module_tensor_to_device(model, param_name, param_device, value=param)
431+
else: # else let accelerate handle loading and dispatching.
432+
# Load weights and dispatch according to the device_map
433+
# by deafult the device_map is None and the weights are loaded on the CPU
434+
accelerate.load_checkpoint_and_dispatch(model, model_file, device_map)
404435

405436
loading_info = {
406437
"missing_keys": [],

‎src/diffusers/pipeline_utils.py‎

Lines changed: 10 additions & 0 deletions

0 commit comments

Comments
 (0)