Prompt48 commited on
Commit
7680122
·
verified ·
1 Parent(s): 5b5ac4d

Upload edit\Qwen3-TTS-test\.venv\Lib\site-packages\accelerate\big_modeling.py with huggingface_hub

Browse files
edit//Qwen3-TTS-test//.venv//Lib//site-packages//accelerate//big_modeling.py ADDED
@@ -0,0 +1,789 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2022 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import logging
16
+ import os
17
+ import re
18
+ from contextlib import contextmanager
19
+ from functools import wraps
20
+ from typing import Optional, Union
21
+
22
+ import torch
23
+ import torch.nn as nn
24
+
25
+ from .hooks import (
26
+ AlignDevicesHook,
27
+ CpuOffload,
28
+ LayerwiseCastingHook,
29
+ UserCpuOffloadHook,
30
+ add_hook_to_module,
31
+ attach_align_device_hook,
32
+ attach_align_device_hook_on_blocks,
33
+ )
34
+ from .utils import (
35
+ OffloadedWeightsLoader,
36
+ check_cuda_p2p_ib_support,
37
+ check_device_map,
38
+ extract_submodules_state_dict,
39
+ find_tied_parameters,
40
+ get_balanced_memory,
41
+ infer_auto_device_map,
42
+ is_bnb_available,
43
+ is_mlu_available,
44
+ is_musa_available,
45
+ is_npu_available,
46
+ is_sdaa_available,
47
+ is_xpu_available,
48
+ load_checkpoint_in_model,
49
+ offload_state_dict,
50
+ parse_flag_from_env,
51
+ retie_parameters,
52
+ )
53
+ from .utils.constants import SUPPORTED_PYTORCH_LAYERS_FOR_UPCASTING
54
+ from .utils.other import recursive_getattr
55
+
56
+
57
+ logger = logging.getLogger(__name__)
58
+
59
+
60
+ @contextmanager
61
+ def init_empty_weights(include_buffers: Optional[bool] = None):
62
+ """
63
+ A context manager under which models are initialized with all parameters on the meta device, therefore creating an
64
+ empty model. Useful when just initializing the model would blow the available RAM.
65
+
66
+ Args:
67
+ include_buffers (`bool`, *optional*):
68
+ Whether or not to also put all buffers on the meta device while initializing.
69
+
70
+ Example:
71
+
72
+ ```python
73
+ import torch.nn as nn
74
+ from accelerate import init_empty_weights
75
+
76
+ # Initialize a model with 100 billions parameters in no time and without using any RAM.
77
+ with init_empty_weights():
78
+ tst = nn.Sequential(*[nn.Linear(10000, 10000) for _ in range(1000)])
79
+ ```
80
+
81
+ <Tip warning={true}>
82
+
83
+ Any model created under this context manager has no weights. As such you can't do something like
84
+ `model.to(some_device)` with it. To load weights inside your empty model, see [`load_checkpoint_and_dispatch`].
85
+ Make sure to overwrite the default device_map param for [`load_checkpoint_and_dispatch`], otherwise dispatch is not
86
+ called.
87
+
88
+ </Tip>
89
+ """
90
+ if include_buffers is None:
91
+ include_buffers = parse_flag_from_env("ACCELERATE_INIT_INCLUDE_BUFFERS", False)
92
+ with init_on_device(torch.device("meta"), include_buffers=include_buffers) as f:
93
+ yield f
94
+
95
+
96
+ @contextmanager
97
+ def init_on_device(device: torch.device, include_buffers: Optional[bool] = None):
98
+ """
99
+ A context manager under which models are initialized with all parameters on the specified device.
100
+
101
+ Args:
102
+ device (`torch.device`):
103
+ Device to initialize all parameters on.
104
+ include_buffers (`bool`, *optional*):
105
+ Whether or not to also put all buffers on the meta device while initializing.
106
+
107
+ Example:
108
+
109
+ ```python
110
+ import torch.nn as nn
111
+ from accelerate import init_on_device
112
+
113
+ with init_on_device(device=torch.device("cuda")):
114
+ tst = nn.Linear(100, 100) # on `cuda` device
115
+ ```
116
+ """
117
+ if include_buffers is None:
118
+ include_buffers = parse_flag_from_env("ACCELERATE_INIT_INCLUDE_BUFFERS", False)
119
+
120
+ if include_buffers:
121
+ with device:
122
+ yield
123
+ return
124
+
125
+ old_register_parameter = nn.Module.register_parameter
126
+ if include_buffers:
127
+ old_register_buffer = nn.Module.register_buffer
128
+
129
+ def register_empty_parameter(module, name, param):
130
+ old_register_parameter(module, name, param)
131
+ if param is not None:
132
+ param_cls = type(module._parameters[name])
133
+ kwargs = module._parameters[name].__dict__
134
+ kwargs["requires_grad"] = param.requires_grad
135
+ module._parameters[name] = param_cls(module._parameters[name].to(device), **kwargs)
136
+
137
+ def register_empty_buffer(module, name, buffer, persistent=True):
138
+ old_register_buffer(module, name, buffer, persistent=persistent)
139
+ if buffer is not None:
140
+ module._buffers[name] = module._buffers[name].to(device)
141
+
142
+ # Patch tensor creation
143
+ if include_buffers:
144
+ tensor_constructors_to_patch = {
145
+ torch_function_name: getattr(torch, torch_function_name)
146
+ for torch_function_name in ["empty", "zeros", "ones", "full"]
147
+ }
148
+ else:
149
+ tensor_constructors_to_patch = {}
150
+
151
+ def patch_tensor_constructor(fn):
152
+ def wrapper(*args, **kwargs):
153
+ kwargs["device"] = device
154
+ return fn(*args, **kwargs)
155
+
156
+ return wrapper
157
+
158
+ try:
159
+ nn.Module.register_parameter = register_empty_parameter
160
+ if include_buffers:
161
+ nn.Module.register_buffer = register_empty_buffer
162
+ for torch_function_name in tensor_constructors_to_patch.keys():
163
+ setattr(torch, torch_function_name, patch_tensor_constructor(getattr(torch, torch_function_name)))
164
+ yield
165
+ finally:
166
+ nn.Module.register_parameter = old_register_parameter
167
+ if include_buffers:
168
+ nn.Module.register_buffer = old_register_buffer
169
+ for torch_function_name, old_torch_function in tensor_constructors_to_patch.items():
170
+ setattr(torch, torch_function_name, old_torch_function)
171
+
172
+
173
+ def cpu_offload(
174
+ model: nn.Module,
175
+ execution_device: Optional[torch.device] = None,
176
+ offload_buffers: bool = False,
177
+ state_dict: Optional[dict[str, torch.Tensor]] = None,
178
+ preload_module_classes: Optional[list[str]] = None,
179
+ ):
180
+ """
181
+ Activates full CPU offload for a model. As a result, all parameters of the model will be offloaded and only one
182
+ copy of the state dict of the model will be kept. During the forward pass, parameters will be extracted from that
183
+ state dict and put on the execution device passed as they are needed, then offloaded again.
184
+
185
+ Args:
186
+ model (`torch.nn.Module`):
187
+ The model to offload.
188
+ execution_device (`torch.device`, *optional*):
189
+ The device on which the forward pass of the model will be executed (should be a GPU). Will default to the
190
+ model first parameter device.
191
+ offload_buffers (`bool`, *optional*, defaults to `False`):
192
+ Whether or not to offload the buffers with the model parameters.
193
+ state_dict (`Dict[str, torch.Tensor]`, *optional*):
194
+ The state dict of the model that will be kept on CPU.
195
+ preload_module_classes (`List[str]`, *optional*):
196
+ A list of classes whose instances should load all their weights (even in the submodules) at the beginning
197
+ of the forward. This should only be used for classes that have submodules which are registered but not
198
+ called directly during the forward, for instance if a `dense` linear layer is registered, but at forward,
199
+ `dense.weight` and `dense.bias` are used in some operations instead of calling `dense` directly.
200
+ """
201
+ if execution_device is None:
202
+ execution_device = next(iter(model.parameters())).device
203
+ if state_dict is None:
204
+ state_dict = {n: p.to("cpu") for n, p in model.state_dict().items()}
205
+
206
+ add_hook_to_module(model, AlignDevicesHook(io_same_device=True), append=True)
207
+ attach_align_device_hook(
208
+ model,
209
+ execution_device=execution_device,
210
+ offload=True,
211
+ offload_buffers=offload_buffers,
212
+ weights_map=state_dict,
213
+ preload_module_classes=preload_module_classes,
214
+ )
215
+
216
+ return model
217
+
218
+
219
+ def cpu_offload_with_hook(
220
+ model: torch.nn.Module,
221
+ execution_device: Optional[Union[int, str, torch.device]] = None,
222
+ prev_module_hook: Optional[UserCpuOffloadHook] = None,
223
+ ):
224
+ """
225
+ Offloads a model on the CPU and puts it back to an execution device when executed. The difference with
226
+ [`cpu_offload`] is that the model stays on the execution device after the forward and is only offloaded again when
227
+ the `offload` method of the returned `hook` is called. Useful for pipelines running a model in a loop.
228
+
229
+ Args:
230
+ model (`torch.nn.Module`):
231
+ The model to offload.
232
+ execution_device(`str`, `int` or `torch.device`, *optional*):
233
+ The device on which the model should be executed. Will default to the MPS device if it's available, then
234
+ GPU 0 if there is a GPU, and finally to the CPU.
235
+ prev_module_hook (`UserCpuOffloadHook`, *optional*):
236
+ The hook sent back by this function for a previous model in the pipeline you are running. If passed, its
237
+ offload method will be called just before the forward of the model to which this hook is attached.
238
+
239
+ Example:
240
+
241
+ ```py
242
+ model_1, hook_1 = cpu_offload_with_hook(model_1, cuda_device)
243
+ model_2, hook_2 = cpu_offload_with_hook(model_2, cuda_device, prev_module_hook=hook_1)
244
+ model_3, hook_3 = cpu_offload_with_hook(model_3, cuda_device, prev_module_hook=hook_2)
245
+
246
+ hid_1 = model_1(input)
247
+ for i in range(50):
248
+ # model1 is offloaded on the CPU at the first iteration, model 2 stays on the GPU for this whole loop.
249
+ hid_2 = model_2(hid_1)
250
+ # model2 is offloaded to the CPU just before this forward.
251
+ hid_3 = model_3(hid_3)
252
+
253
+ # For model3, you need to manually call the hook offload method.
254
+ hook_3.offload()
255
+ ```
256
+ """
257
+ hook = CpuOffload(execution_device=execution_device, prev_module_hook=prev_module_hook)
258
+ add_hook_to_module(model, hook, append=True)
259
+ user_hook = UserCpuOffloadHook(model, hook)
260
+ return model, user_hook
261
+
262
+
263
+ def disk_offload(
264
+ model: nn.Module,
265
+ offload_dir: Union[str, os.PathLike],
266
+ execution_device: Optional[torch.device] = None,
267
+ offload_buffers: bool = False,
268
+ preload_module_classes: Optional[list[str]] = None,
269
+ ):
270
+ """
271
+ Activates full disk offload for a model. As a result, all parameters of the model will be offloaded as
272
+ memory-mapped array in a given folder. During the forward pass, parameters will be accessed from that folder and
273
+ put on the execution device passed as they are needed, then offloaded again.
274
+
275
+ Args:
276
+ model (`torch.nn.Module`): The model to offload.
277
+ offload_dir (`str` or `os.PathLike`):
278
+ The folder in which to offload the model weights (or where the model weights are already offloaded).
279
+ execution_device (`torch.device`, *optional*):
280
+ The device on which the forward pass of the model will be executed (should be a GPU). Will default to the
281
+ model's first parameter device.
282
+ offload_buffers (`bool`, *optional*, defaults to `False`):
283
+ Whether or not to offload the buffers with the model parameters.
284
+ preload_module_classes (`List[str]`, *optional*):
285
+ A list of classes whose instances should load all their weights (even in the submodules) at the beginning
286
+ of the forward. This should only be used for classes that have submodules which are registered but not
287
+ called directly during the forward, for instance if a `dense` linear layer is registered, but at forward,
288
+ `dense.weight` and `dense.bias` are used in some operations instead of calling `dense` directly.
289
+ """
290
+ if not os.path.isdir(offload_dir) or not os.path.isfile(os.path.join(offload_dir, "index.json")):
291
+ offload_state_dict(offload_dir, model.state_dict())
292
+ if execution_device is None:
293
+ execution_device = next(iter(model.parameters())).device
294
+ weights_map = OffloadedWeightsLoader(save_folder=offload_dir)
295
+
296
+ add_hook_to_module(model, AlignDevicesHook(io_same_device=True), append=True)
297
+ attach_align_device_hook(
298
+ model,
299
+ execution_device=execution_device,
300
+ offload=True,
301
+ offload_buffers=offload_buffers,
302
+ weights_map=weights_map,
303
+ preload_module_classes=preload_module_classes,
304
+ )
305
+
306
+ return model
307
+
308
+
309
+ def dispatch_model(
310
+ model: nn.Module,
311
+ device_map: dict[str, Union[str, int, torch.device]],
312
+ main_device: Optional[torch.device] = None,
313
+ state_dict: Optional[dict[str, torch.Tensor]] = None,
314
+ offload_dir: Optional[Union[str, os.PathLike]] = None,
315
+ offload_index: Optional[dict[str, str]] = None,
316
+ offload_buffers: bool = False,
317
+ skip_keys: Optional[Union[str, list[str]]] = None,
318
+ preload_module_classes: Optional[list[str]] = None,
319
+ force_hooks: bool = False,
320
+ ):
321
+ """
322
+ Dispatches a model according to a given device map. Layers of the model might be spread across GPUs, offloaded on
323
+ the CPU or even the disk.
324
+
325
+ Args:
326
+ model (`torch.nn.Module`):
327
+ The model to dispatch.
328
+ device_map (`Dict[str, Union[str, int, torch.device]]`):
329
+ A dictionary mapping module names in the models `state_dict` to the device they should go to. Note that
330
+ `"disk"` is accepted even if it's not a proper value for `torch.device`.
331
+ main_device (`str`, `int` or `torch.device`, *optional*):
332
+ The main execution device. Will default to the first device in the `device_map` different from `"cpu"` or
333
+ `"disk"`.
334
+ state_dict (`Dict[str, torch.Tensor]`, *optional*):
335
+ The state dict of the part of the model that will be kept on CPU.
336
+ offload_dir (`str` or `os.PathLike`):
337
+ The folder in which to offload the model weights (or where the model weights are already offloaded).
338
+ offload_index (`Dict`, *optional*):
339
+ A dictionary from weight name to their information (`dtype`/ `shape` or safetensors filename). Will default
340
+ to the index saved in `save_folder`.
341
+ offload_buffers (`bool`, *optional*, defaults to `False`):
342
+ Whether or not to offload the buffers with the model parameters.
343
+ skip_keys (`str` or `List[str]`, *optional*):
344
+ A list of keys to ignore when moving inputs or outputs between devices.
345
+ preload_module_classes (`List[str]`, *optional*):
346
+ A list of classes whose instances should load all their weights (even in the submodules) at the beginning
347
+ of the forward. This should only be used for classes that have submodules which are registered but not
348
+ called directly during the forward, for instance if a `dense` linear layer is registered, but at forward,
349
+ `dense.weight` and `dense.bias` are used in some operations instead of calling `dense` directly.
350
+ force_hooks (`bool`, *optional*, defaults to `False`):
351
+ Whether or not to force device hooks to be attached to the model even if all layers are dispatched to a
352
+ single device.
353
+ """
354
+ # Error early if the device map is incomplete.
355
+ check_device_map(model, device_map)
356
+
357
+ # We need to force hook for quantized model that can't be moved with to()
358
+ if getattr(model, "quantization_method", "bitsandbytes") == "bitsandbytes":
359
+ # since bnb 0.43.2, we can move 4-bit model
360
+ if getattr(model, "is_loaded_in_8bit", False) or (
361
+ getattr(model, "is_loaded_in_4bit", False) and not is_bnb_available(min_version="0.43.2")
362
+ ):
363
+ force_hooks = True
364
+
365
+ # We attach hooks if the device_map has at least 2 different devices or if
366
+ # force_hooks is set to `True`. Otherwise, the model in already loaded
367
+ # in the unique device and the user can decide where to dispatch the model.
368
+ # If the model is quantized, we always force-dispatch the model
369
+ if (len(set(device_map.values())) > 1) or force_hooks:
370
+ if main_device is None:
371
+ if set(device_map.values()) == {"cpu"} or set(device_map.values()) == {"cpu", "disk"}:
372
+ main_device = "cpu"
373
+ else:
374
+ main_device = [d for d in device_map.values() if d not in ["cpu", "disk"]][0]
375
+
376
+ if main_device != "cpu":
377
+ cpu_modules = [name for name, device in device_map.items() if device == "cpu"]
378
+ if state_dict is None and len(cpu_modules) > 0:
379
+ state_dict = extract_submodules_state_dict(model.state_dict(), cpu_modules)
380
+
381
+ disk_modules = [name for name, device in device_map.items() if device == "disk"]
382
+ if offload_dir is None and offload_index is None and len(disk_modules) > 0:
383
+ raise ValueError(
384
+ "We need an `offload_dir` to dispatch this model according to this `device_map`, the following submodules "
385
+ f"need to be offloaded: {', '.join(disk_modules)}."
386
+ )
387
+ if (
388
+ len(disk_modules) > 0
389
+ and offload_index is None
390
+ and (not os.path.isdir(offload_dir) or not os.path.isfile(os.path.join(offload_dir, "index.json")))
391
+ ):
392
+ disk_state_dict = extract_submodules_state_dict(model.state_dict(), disk_modules)
393
+ offload_state_dict(offload_dir, disk_state_dict)
394
+
395
+ execution_device = {
396
+ name: main_device if device in ["cpu", "disk"] else device for name, device in device_map.items()
397
+ }
398
+ execution_device[""] = main_device
399
+ offloaded_devices = ["disk"] if main_device == "cpu" or main_device == "mps" else ["cpu", "disk"]
400
+ offload = {name: device in offloaded_devices for name, device in device_map.items()}
401
+ save_folder = offload_dir if len(disk_modules) > 0 else None
402
+ if state_dict is not None or save_folder is not None or offload_index is not None:
403
+ device = main_device if offload_index is not None else None
404
+ weights_map = OffloadedWeightsLoader(
405
+ state_dict=state_dict, save_folder=save_folder, index=offload_index, device=device
406
+ )
407
+ else:
408
+ weights_map = None
409
+
410
+ # When dispatching the model's parameters to the devices specified in device_map, we want to avoid allocating memory several times for the
411
+ # tied parameters. The dictionary tied_params_map keeps track of the already allocated data for a given tied parameter (represented by its
412
+ # original pointer) on each devices.
413
+ tied_params = find_tied_parameters(model)
414
+
415
+ tied_params_map = {}
416
+ for group in tied_params:
417
+ for param_name in group:
418
+ # data_ptr() is enough here, as `find_tied_parameters` finds tied params simply by comparing `param1 is param2`, so we don't need
419
+ # to care about views of tensors through storage_offset.
420
+ data_ptr = recursive_getattr(model, param_name).data_ptr()
421
+ tied_params_map[data_ptr] = {}
422
+
423
+ # Note: To handle the disk offloading case, we can not simply use weights_map[param_name].data_ptr() as the reference pointer,
424
+ # as we have no guarantee that safetensors' `file.get_tensor()` will always give the same pointer.
425
+
426
+ attach_align_device_hook_on_blocks(
427
+ model,
428
+ execution_device=execution_device,
429
+ offload=offload,
430
+ offload_buffers=offload_buffers,
431
+ weights_map=weights_map,
432
+ skip_keys=skip_keys,
433
+ preload_module_classes=preload_module_classes,
434
+ tied_params_map=tied_params_map,
435
+ )
436
+
437
+ # warn if there is any params on the meta device
438
+ offloaded_devices_str = " and ".join(
439
+ [device for device in set(device_map.values()) if device in ("cpu", "disk")]
440
+ )
441
+ if len(offloaded_devices_str) > 0:
442
+ logger.warning(
443
+ f"Some parameters are on the meta device because they were offloaded to the {offloaded_devices_str}."
444
+ )
445
+
446
+ # Attaching the hook may break tied weights, so we retie them
447
+ retie_parameters(model, tied_params)
448
+
449
+ # add warning to cuda and to method
450
+ def add_warning(fn, model):
451
+ @wraps(fn)
452
+ def wrapper(*args, **kwargs):
453
+ warning_msg = "You shouldn't move a model that is dispatched using accelerate hooks."
454
+ if str(fn.__name__) == "to":
455
+ to_device = torch._C._nn._parse_to(*args, **kwargs)[0]
456
+ if to_device is not None:
457
+ logger.warning(warning_msg)
458
+ else:
459
+ logger.warning(warning_msg)
460
+ for param in model.parameters():
461
+ if param.device == torch.device("meta"):
462
+ raise RuntimeError("You can't move a model that has some modules offloaded to cpu or disk.")
463
+ return fn(*args, **kwargs)
464
+
465
+ return wrapper
466
+
467
+ # Make sure to update _accelerate_added_attributes in hooks.py if you add any hook
468
+ model.to = add_warning(model.to, model)
469
+ if is_npu_available():
470
+ model.npu = add_warning(model.npu, model)
471
+ elif is_mlu_available():
472
+ model.mlu = add_warning(model.mlu, model)
473
+ elif is_sdaa_available():
474
+ model.sdaa = add_warning(model.sdaa, model)
475
+ elif is_musa_available():
476
+ model.musa = add_warning(model.musa, model)
477
+ elif is_xpu_available():
478
+ model.xpu = add_warning(model.xpu, model)
479
+ else:
480
+ model.cuda = add_warning(model.cuda, model)
481
+
482
+ # Check if we are using multi-gpus with RTX 4000 series
483
+ use_multi_gpu = len([device for device in set(device_map.values()) if device not in ("cpu", "disk")]) > 1
484
+ if use_multi_gpu and not check_cuda_p2p_ib_support():
485
+ logger.warning(
486
+ "We've detected an older driver with an RTX 4000 series GPU. These drivers have issues with P2P. "
487
+ "This can affect the multi-gpu inference when using accelerate device_map."
488
+ "Please make sure to update your driver to the latest version which resolves this."
489
+ )
490
+ else:
491
+ device = list(device_map.values())[0]
492
+ # `torch.Tensor.to(<int num>)` is not supported by `torch_npu` (see this [issue](https://github.com/Ascend/pytorch/issues/16)).
493
+ if is_npu_available() and isinstance(device, int):
494
+ device = f"npu:{device}"
495
+ elif is_mlu_available() and isinstance(device, int):
496
+ device = f"mlu:{device}"
497
+ elif is_sdaa_available() and isinstance(device, int):
498
+ device = f"sdaa:{device}"
499
+ elif is_musa_available() and isinstance(device, int):
500
+ device = f"musa:{device}"
501
+ if device != "disk":
502
+ model.to(device)
503
+ else:
504
+ raise ValueError(
505
+ "You are trying to offload the whole model to the disk. Please use the `disk_offload` function instead."
506
+ )
507
+ # Convert OrderedDict back to dict for easier usage
508
+ model.hf_device_map = dict(device_map)
509
+ return model
510
+
511
+
512
+ def load_checkpoint_and_dispatch(
513
+ model: nn.Module,
514
+ checkpoint: Union[str, os.PathLike],
515
+ device_map: Optional[Union[str, dict[str, Union[int, str, torch.device]]]] = None,
516
+ max_memory: Optional[dict[Union[int, str], Union[int, str]]] = None,
517
+ no_split_module_classes: Optional[list[str]] = None,
518
+ offload_folder: Optional[Union[str, os.PathLike]] = None,
519
+ offload_buffers: bool = False,
520
+ dtype: Optional[Union[str, torch.dtype]] = None,
521
+ offload_state_dict: Optional[bool] = None,
522
+ skip_keys: Optional[Union[str, list[str]]] = None,
523
+ preload_module_classes: Optional[list[str]] = None,
524
+ force_hooks: bool = False,
525
+ strict: bool = False,
526
+ full_state_dict: bool = True,
527
+ broadcast_from_rank0: bool = False,
528
+ ):
529
+ """
530
+ Loads a (potentially sharded) checkpoint inside a model, potentially sending weights to a given device as they are
531
+ loaded and adds the various hooks that will make this model run properly (even if split across devices).
532
+
533
+ Args:
534
+ model (`torch.nn.Module`): The model in which we want to load a checkpoint.
535
+ checkpoint (`str` or `os.PathLike`):
536
+ The folder checkpoint to load. It can be:
537
+ - a path to a file containing a whole model state dict
538
+ - a path to a `.json` file containing the index to a sharded checkpoint
539
+ - a path to a folder containing a unique `.index.json` file and the shards of a checkpoint.
540
+ device_map (`Dict[str, Union[int, str, torch.device]]`, *optional*):
541
+ A map that specifies where each submodule should go. It doesn't need to be refined to each parameter/buffer
542
+ name, once a given module name is inside, every submodule of it will be sent to the same device.
543
+
544
+ To have Accelerate compute the most optimized `device_map` automatically, set `device_map="auto"`. For more
545
+ information about each option see [here](../concept_guides/big_model_inference#designing-a-device-map).
546
+ Defaults to None, which means [`dispatch_model`] will not be called.
547
+ max_memory (`Dict`, *optional*):
548
+ A dictionary device identifier to maximum memory. Will default to the maximum memory available for each GPU
549
+ and the available CPU RAM if unset.
550
+ no_split_module_classes (`List[str]`, *optional*):
551
+ A list of layer class names that should never be split across device (for instance any layer that has a
552
+ residual connection).
553
+ offload_folder (`str` or `os.PathLike`, *optional*):
554
+ If the `device_map` contains any value `"disk"`, the folder where we will offload weights.
555
+ offload_buffers (`bool`, *optional*, defaults to `False`):
556
+ In the layers that are offloaded on the CPU or the hard drive, whether or not to offload the buffers as
557
+ well as the parameters.
558
+ dtype (`str` or `torch.dtype`, *optional*):
559
+ If provided, the weights will be converted to that type when loaded.
560
+ offload_state_dict (`bool`, *optional*):
561
+ If `True`, will temporarily offload the CPU state dict on the hard drive to avoid getting out of CPU RAM if
562
+ the weight of the CPU state dict + the biggest shard does not fit. Will default to `True` if the device map
563
+ picked contains `"disk"` values.
564
+ skip_keys (`str` or `List[str]`, *optional*):
565
+ A list of keys to ignore when moving inputs or outputs between devices.
566
+ preload_module_classes (`List[str]`, *optional*):
567
+ A list of classes whose instances should load all their weights (even in the submodules) at the beginning
568
+ of the forward. This should only be used for classes that have submodules which are registered but not
569
+ called directly during the forward, for instance if a `dense` linear layer is registered, but at forward,
570
+ `dense.weight` and `dense.bias` are used in some operations instead of calling `dense` directly.
571
+ force_hooks (`bool`, *optional*, defaults to `False`):
572
+ Whether or not to force device hooks to be attached to the model even if all layers are dispatched to a
573
+ single device.
574
+ strict (`bool`, *optional*, defaults to `False`):
575
+ Whether to strictly enforce that the keys in the checkpoint state_dict match the keys of the model's
576
+ state_dict.
577
+ full_state_dict (`bool`, *optional*, defaults to `True`): if this is set to `True`, all the tensors in the
578
+ loaded state_dict will be gathered. No ShardedTensor and DTensor will be in the loaded state_dict.
579
+ broadcast_from_rank0 (`False`, *optional*, defaults to `False`): when the option is `True`, a distributed
580
+ `ProcessGroup` must be initialized. rank0 should receive a full state_dict and will broadcast the tensors
581
+ in the state_dict one by one to other ranks. Other ranks will receive the tensors and shard (if applicable)
582
+ according to the local shards in the model.
583
+
584
+ Example:
585
+
586
+ ```python
587
+ >>> from accelerate import init_empty_weights, load_checkpoint_and_dispatch
588
+ >>> from huggingface_hub import hf_hub_download
589
+ >>> from transformers import AutoConfig, AutoModelForCausalLM
590
+
591
+ >>> # Download the Weights
592
+ >>> checkpoint = "EleutherAI/gpt-j-6B"
593
+ >>> weights_location = hf_hub_download(checkpoint, "pytorch_model.bin")
594
+
595
+ >>> # Create a model and initialize it with empty weights
596
+ >>> config = AutoConfig.from_pretrained(checkpoint)
597
+ >>> with init_empty_weights():
598
+ ... model = AutoModelForCausalLM.from_config(config)
599
+
600
+ >>> # Load the checkpoint and dispatch it to the right devices
601
+ >>> model = load_checkpoint_and_dispatch(
602
+ ... model, weights_location, device_map="auto", no_split_module_classes=["GPTJBlock"]
603
+ ... )
604
+ ```
605
+ """
606
+ if isinstance(device_map, str) and device_map not in ["auto", "balanced", "balanced_low_0", "sequential"]:
607
+ raise ValueError(
608
+ "If passing a string for `device_map`, please choose 'auto', 'balanced', 'balanced_low_0' or 'sequential'."
609
+ )
610
+ if isinstance(device_map, str):
611
+ if device_map != "sequential":
612
+ max_memory = get_balanced_memory(
613
+ model,
614
+ max_memory=max_memory,
615
+ no_split_module_classes=no_split_module_classes,
616
+ dtype=dtype,
617
+ low_zero=(device_map == "balanced_low_0"),
618
+ )
619
+ device_map = infer_auto_device_map(
620
+ model,
621
+ max_memory=max_memory,
622
+ no_split_module_classes=no_split_module_classes,
623
+ dtype=dtype,
624
+ offload_buffers=offload_buffers,
625
+ )
626
+ if offload_state_dict is None and device_map is not None and "disk" in device_map.values():
627
+ offload_state_dict = True
628
+ load_checkpoint_in_model(
629
+ model,
630
+ checkpoint,
631
+ device_map=device_map,
632
+ offload_folder=offload_folder,
633
+ dtype=dtype,
634
+ offload_state_dict=offload_state_dict,
635
+ offload_buffers=offload_buffers,
636
+ strict=strict,
637
+ full_state_dict=full_state_dict,
638
+ broadcast_from_rank0=broadcast_from_rank0,
639
+ )
640
+ if device_map is None:
641
+ return model
642
+ return dispatch_model(
643
+ model,
644
+ device_map=device_map,
645
+ offload_dir=offload_folder,
646
+ offload_buffers=offload_buffers,
647
+ skip_keys=skip_keys,
648
+ preload_module_classes=preload_module_classes,
649
+ force_hooks=force_hooks,
650
+ )
651
+
652
+
653
+ def attach_layerwise_casting_hooks(
654
+ module: torch.nn.Module,
655
+ storage_dtype: torch.dtype,
656
+ compute_dtype: torch.dtype,
657
+ skip_modules_pattern: Optional[Union[str, tuple[str, ...]]] = None,
658
+ skip_modules_classes: Optional[tuple[type[torch.nn.Module], ...]] = None,
659
+ non_blocking: bool = False,
660
+ ) -> None:
661
+ r"""
662
+ Applies layerwise casting to a given module. The module expected here is a PyTorch `nn.Module`. This is helpful for
663
+ reducing memory requirements when one doesn't want to fully quantize a model. Model params can be kept in say,
664
+ `torch.float8_e4m3fn` and upcasted to a higher precision like `torch.bfloat16` during forward pass and downcasted
665
+ back to `torch.float8_e4m3fn` to realize memory savings.
666
+
667
+ Args:
668
+ module (`torch.nn.Module`):
669
+ The module whose leaf modules will be cast to a high precision dtype for computation, and to a low
670
+ precision dtype for storage.
671
+ storage_dtype (`torch.dtype`):
672
+ The dtype to cast the module to before/after the forward pass for storage.
673
+ compute_dtype (`torch.dtype`):
674
+ The dtype to cast the module to during the forward pass for computation.
675
+ skip_modules_pattern (`tuple[str, ...]`, defaults to `None`):
676
+ A list of patterns to match the names of the modules to skip during the layerwise casting process. If set
677
+ to `None` alongside `skip_modules_classes` being `None`, the layerwise casting is applied directly to the
678
+ module instead of its internal submodules.
679
+ skip_modules_classes (`tuple[type[torch.nn.Module], ...]`, defaults to `None`):
680
+ A list of module classes to skip during the layerwise casting process.
681
+ non_blocking (`bool`, defaults to `False`):
682
+ If `True`, the weight casting operations are non-blocking.
683
+
684
+ Example:
685
+
686
+ ```python
687
+ >>> from accelerate.hooks import attach_layerwise_casting_hooks
688
+ >>> from transformers import AutoModelForCausalLM
689
+ >>> import torch
690
+
691
+ >>> # Model
692
+ >>> checkpoint = "EleutherAI/gpt-j-6B"
693
+ >>> model = AutoModelForCausalLM.from_pretrained(checkpoint)
694
+
695
+ >>> # Attach hooks and perform inference
696
+ >>> attach_layerwise_casting_hooks(model, storage_dtype=torch.float8_e4m3fn, compute_dtype=torch.bfloat16)
697
+ >>> with torch.no_grad():
698
+ ... model(...)
699
+ ```
700
+
701
+ Users can also pass modules they want to avoid from getting downcasted.
702
+
703
+ ```py
704
+ >>> attach_layerwise_casting_hooks(
705
+ ... model, storage_dtype=torch.float8_e4m3fn, compute_dtype=torch.bfloat16, skip_modules_pattern=["norm"]
706
+ ... )
707
+ ```
708
+ """
709
+ _attach_layerwise_casting_hooks(
710
+ module, storage_dtype, compute_dtype, skip_modules_pattern, skip_modules_classes, non_blocking
711
+ )
712
+
713
+
714
+ def _attach_layerwise_casting_hooks(
715
+ module: torch.nn.Module,
716
+ storage_dtype: torch.dtype,
717
+ compute_dtype: torch.dtype,
718
+ skip_modules_pattern: Optional[Union[str, tuple[str, ...]]] = None,
719
+ skip_modules_classes: Optional[tuple[type[torch.nn.Module], ...]] = None,
720
+ non_blocking: bool = False,
721
+ _prefix: str = "",
722
+ ):
723
+ should_skip = (skip_modules_classes is not None and isinstance(module, skip_modules_classes)) or (
724
+ skip_modules_pattern is not None and any(re.search(pattern, _prefix) for pattern in skip_modules_pattern)
725
+ )
726
+ if should_skip:
727
+ logger.debug(f'Skipping layerwise casting for layer "{_prefix}"')
728
+ return
729
+
730
+ if isinstance(module, SUPPORTED_PYTORCH_LAYERS_FOR_UPCASTING):
731
+ logger.debug(f'Applying layerwise casting to layer "{_prefix}"')
732
+ add_hook_to_module(
733
+ module,
734
+ LayerwiseCastingHook(storage_dtype=storage_dtype, compute_dtype=compute_dtype, non_blocking=non_blocking),
735
+ append=True,
736
+ )
737
+ return
738
+
739
+ for name, submodule in module.named_children():
740
+ layer_name = f"{_prefix}.{name}" if _prefix else name
741
+ _attach_layerwise_casting_hooks(
742
+ submodule,
743
+ storage_dtype,
744
+ compute_dtype,
745
+ skip_modules_pattern,
746
+ skip_modules_classes,
747
+ non_blocking,
748
+ _prefix=layer_name,
749
+ )
750
+
751
+
752
+ def _attach_context_parallel_hooks(
753
+ model: nn.Module,
754
+ ):
755
+ """
756
+ Monkeypatch huggingface's `transformers` model to fix attention mask issues when using context parallelism.
757
+
758
+ This function attaches forward_pre_hooks to each self_attn module of the model, where each hook checks the
759
+ args/kwargs, if they contain an attention mask, if it does, it will remove this mask, check if it is a causal mask,
760
+ if yes, will add a kwarg `is_causal=True`, otherwise will raise an error. This is because context parallelism does
761
+ not support attention masks. This function modifies the model in place.
762
+
763
+ Args:
764
+ model (`nn.Module`):
765
+ The model to attach the hooks to.
766
+
767
+ """
768
+
769
+ def _self_attn_pre_forward_hook(_module, module_args, module_kwargs):
770
+ if "attention_mask" in module_kwargs:
771
+ module_kwargs["attention_mask"] = None
772
+ module_kwargs["is_causal"] = True
773
+
774
+ return module_args, module_kwargs
775
+
776
+ for name, module in model.named_modules():
777
+ # We hope (assume) that if user uses their own model (without this structure which transformers uses), they read the docs saying they can't pass in attention masks
778
+ # Then these cases can happen:
779
+ # 1) some modules end with a `self-attn` module, in which case we attach the hook, but the
780
+ # there's no attention mask kwarg -> hook is a no-op
781
+ # 2) some modules end with a `self-attn` module, in which case we attach the hook, and the
782
+ # attention mask kwarg is passed -> hook will remove the attention mask and add
783
+ # `is_causal=True` kwarg, which either crashes the training or fixes it
784
+ # (training would crash anyway as attention mask isn't supported)
785
+ # 3) no modules end with a `self-attn` module, in which case we don't attach the hook, this is
786
+ # a no-op as well
787
+ if name.endswith("self_attn"):
788
+ # we want the hook to be executed first, to avoid any other hooks doing work on the attention mask
789
+ module.register_forward_pre_hook(_self_attn_pre_forward_hook, with_kwargs=True, prepend=True)