ZhengyangZhang commited on
Commit
72d7e80
·
verified ·
1 Parent(s): 156f6c0

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.12/site-packages/torch/distributed/__pycache__/__init__.cpython-312.pyc +0 -0
  2. lib/python3.12/site-packages/torch/distributed/__pycache__/_state_dict_utils.cpython-312.pyc +0 -0
  3. lib/python3.12/site-packages/torch/distributed/__pycache__/argparse_util.cpython-312.pyc +0 -0
  4. lib/python3.12/site-packages/torch/distributed/__pycache__/launch.cpython-312.pyc +0 -0
  5. lib/python3.12/site-packages/torch/distributed/__pycache__/logging_handlers.cpython-312.pyc +0 -0
  6. lib/python3.12/site-packages/torch/distributed/__pycache__/remote_device.cpython-312.pyc +0 -0
  7. lib/python3.12/site-packages/torch/distributed/__pycache__/run.cpython-312.pyc +0 -0
  8. lib/python3.12/site-packages/torch/distributed/__pycache__/utils.cpython-312.pyc +0 -0
  9. lib/python3.12/site-packages/torch/distributed/_composable/__init__.py +3 -0
  10. lib/python3.12/site-packages/torch/distributed/_composable/__pycache__/__init__.cpython-312.pyc +0 -0
  11. lib/python3.12/site-packages/torch/distributed/_composable/__pycache__/checkpoint_activation.cpython-312.pyc +0 -0
  12. lib/python3.12/site-packages/torch/distributed/_composable/__pycache__/contract.cpython-312.pyc +0 -0
  13. lib/python3.12/site-packages/torch/distributed/_composable/__pycache__/replicate.cpython-312.pyc +0 -0
  14. lib/python3.12/site-packages/torch/distributed/_composable/checkpoint_activation.py +126 -0
  15. lib/python3.12/site-packages/torch/distributed/_composable/contract.py +224 -0
  16. lib/python3.12/site-packages/torch/distributed/_composable/fsdp/__init__.py +3 -0
  17. lib/python3.12/site-packages/torch/distributed/_composable/fsdp/__pycache__/__init__.cpython-312.pyc +0 -0
  18. lib/python3.12/site-packages/torch/distributed/_composable/fsdp/__pycache__/fully_shard.cpython-312.pyc +0 -0
  19. lib/python3.12/site-packages/torch/distributed/_composable/fsdp/fully_shard.py +8 -0
  20. lib/python3.12/site-packages/torch/distributed/_composable/replicate.py +254 -0
  21. lib/python3.12/site-packages/torch/distributed/_sharded_tensor/__init__.py +21 -0
  22. lib/python3.12/site-packages/torch/distributed/_sharded_tensor/__pycache__/__init__.cpython-312.pyc +0 -0
  23. lib/python3.12/site-packages/torch/distributed/algorithms/__init__.py +1 -0
  24. lib/python3.12/site-packages/torch/distributed/algorithms/__pycache__/__init__.cpython-312.pyc +0 -0
  25. lib/python3.12/site-packages/torch/distributed/algorithms/__pycache__/join.cpython-312.pyc +0 -0
  26. lib/python3.12/site-packages/torch/distributed/algorithms/_checkpoint/__init__.py +0 -0
  27. lib/python3.12/site-packages/torch/distributed/algorithms/_checkpoint/__pycache__/__init__.cpython-312.pyc +0 -0
  28. lib/python3.12/site-packages/torch/distributed/algorithms/_checkpoint/__pycache__/checkpoint_wrapper.cpython-312.pyc +0 -0
  29. lib/python3.12/site-packages/torch/distributed/algorithms/_checkpoint/checkpoint_wrapper.py +323 -0
  30. lib/python3.12/site-packages/torch/distributed/algorithms/_comm_hooks/__init__.py +7 -0
  31. lib/python3.12/site-packages/torch/distributed/algorithms/_comm_hooks/__pycache__/__init__.cpython-312.pyc +0 -0
  32. lib/python3.12/site-packages/torch/distributed/algorithms/_comm_hooks/__pycache__/default_hooks.cpython-312.pyc +0 -0
  33. lib/python3.12/site-packages/torch/distributed/algorithms/_comm_hooks/default_hooks.py +192 -0
  34. lib/python3.12/site-packages/torch/distributed/algorithms/_optimizer_overlap/__init__.py +1 -0
  35. lib/python3.12/site-packages/torch/distributed/algorithms/_optimizer_overlap/__pycache__/__init__.cpython-312.pyc +0 -0
  36. lib/python3.12/site-packages/torch/distributed/algorithms/_optimizer_overlap/__pycache__/optimizer_overlap.cpython-312.pyc +0 -0
  37. lib/python3.12/site-packages/torch/distributed/algorithms/_optimizer_overlap/optimizer_overlap.py +97 -0
  38. lib/python3.12/site-packages/torch/distributed/algorithms/_quantization/__init__.py +0 -0
  39. lib/python3.12/site-packages/torch/distributed/algorithms/_quantization/__pycache__/__init__.cpython-312.pyc +0 -0
  40. lib/python3.12/site-packages/torch/distributed/algorithms/_quantization/__pycache__/quantization.cpython-312.pyc +0 -0
  41. lib/python3.12/site-packages/torch/distributed/algorithms/_quantization/quantization.py +150 -0
  42. lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__init__.py +110 -0
  43. lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/__init__.cpython-312.pyc +0 -0
  44. lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/ddp_zero_hook.cpython-312.pyc +0 -0
  45. lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/debugging_hooks.cpython-312.pyc +0 -0
  46. lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/default_hooks.cpython-312.pyc +0 -0
  47. lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/mixed_precision_hooks.cpython-312.pyc +0 -0
  48. lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/optimizer_overlap_hooks.cpython-312.pyc +0 -0
  49. lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/post_localSGD_hook.cpython-312.pyc +0 -0
  50. lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/powerSGD_hook.cpython-312.pyc +0 -0
lib/python3.12/site-packages/torch/distributed/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (6.1 kB). View file
 
lib/python3.12/site-packages/torch/distributed/__pycache__/_state_dict_utils.cpython-312.pyc ADDED
Binary file (30 kB). View file
 
lib/python3.12/site-packages/torch/distributed/__pycache__/argparse_util.cpython-312.pyc ADDED
Binary file (4.53 kB). View file
 
lib/python3.12/site-packages/torch/distributed/__pycache__/launch.cpython-312.pyc ADDED
Binary file (8.16 kB). View file
 
lib/python3.12/site-packages/torch/distributed/__pycache__/logging_handlers.cpython-312.pyc ADDED
Binary file (529 Bytes). View file
 
lib/python3.12/site-packages/torch/distributed/__pycache__/remote_device.cpython-312.pyc ADDED
Binary file (5.77 kB). View file
 
lib/python3.12/site-packages/torch/distributed/__pycache__/run.cpython-312.pyc ADDED
Binary file (35.7 kB). View file
 
lib/python3.12/site-packages/torch/distributed/__pycache__/utils.cpython-312.pyc ADDED
Binary file (18.5 kB). View file
 
lib/python3.12/site-packages/torch/distributed/_composable/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from .checkpoint_activation import checkpoint
2
+ from .contract import _get_registry, contract
3
+ from .replicate import replicate
lib/python3.12/site-packages/torch/distributed/_composable/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (356 Bytes). View file
 
lib/python3.12/site-packages/torch/distributed/_composable/__pycache__/checkpoint_activation.cpython-312.pyc ADDED
Binary file (6.28 kB). View file
 
lib/python3.12/site-packages/torch/distributed/_composable/__pycache__/contract.cpython-312.pyc ADDED
Binary file (9.14 kB). View file
 
lib/python3.12/site-packages/torch/distributed/_composable/__pycache__/replicate.cpython-312.pyc ADDED
Binary file (10.9 kB). View file
 
lib/python3.12/site-packages/torch/distributed/_composable/checkpoint_activation.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-decorators
2
+ # mypy: allow-untyped-defs
3
+ from contextlib import contextmanager, nullcontext
4
+ from typing import Any, ContextManager, Dict, Optional, Tuple
5
+
6
+ import torch
7
+ import torch.nn as nn
8
+ from torch.utils.checkpoint import (
9
+ _checkpoint_without_reentrant_generator,
10
+ _DEFAULT_DETERMINISM_MODE,
11
+ )
12
+
13
+ from .contract import contract
14
+
15
+
16
+ @contextmanager
17
+ def _no_hook(module: nn.Module, user_ctx: Optional[ContextManager] = None):
18
+ r"""
19
+ Disable hooks installed by checkpoint to avoid unintentional recursion
20
+ during backward recomputation.
21
+ """
22
+
23
+ with user_ctx if user_ctx else nullcontext():
24
+ orig_enable_hook = checkpoint.state(module).enable_hook
25
+ checkpoint.state(module).enable_hook = False
26
+ try:
27
+ yield
28
+ finally:
29
+ checkpoint.state(module).enable_hook = orig_enable_hook
30
+
31
+
32
+ @contract()
33
+ def checkpoint(module: nn.Module, **kwargs) -> nn.Module:
34
+ r"""
35
+ This is a composable activation checkpointing API. Unlike functional
36
+ activation checkpointing APIs, this one does not require changing model
37
+ source code. Unlike ``nn.Module`` wrapper activation checkpointing APIs,
38
+ this one does not modify model structure or fully-qualified names either.
39
+ Under the hood, it registers activation checkpointing logic as pre- and
40
+ post-forward hooks. Hence, this API can be easily applied to any model or
41
+ sub-modules in the model.
42
+
43
+ Args:
44
+ module (nn.Module): the target model or sub-module to apply activation
45
+ checkpointing.
46
+
47
+ Example::
48
+ >>> # xdoctest: +SKIP
49
+ >>> import torch.nn as nn
50
+ >>>
51
+ >>> class MyModel(nn.Module):
52
+ >>> def __init__(self) -> None:
53
+ >>> super().__init__()
54
+ >>> self.l1 = nn.Linear(10, 10)
55
+ >>> self.l2 = nn.Linear(10, 10)
56
+ >>>
57
+ >>> def forward(self, x):
58
+ >>> return self.l2(self.l1(x))
59
+ >>>
60
+ >>> model = MyModel()
61
+ >>> checkpoint(model.l1) # apply activation checkpointing only to l1
62
+ >>> model(torch.zeros(2, 10)).sum().backward()
63
+
64
+ """
65
+ torch._C._log_api_usage_once("torch.distributed.checkpoint")
66
+
67
+ use_reentrant = kwargs.pop("use_reentrant", False)
68
+ if use_reentrant:
69
+ raise NotImplementedError(
70
+ "use_reentrant=True is not supported in composable checkpoint. "
71
+ "Please use torch.utils.checkpoint.checkpoint instead."
72
+ )
73
+ preserve_rng_state = kwargs.pop("preserve_rng_state", True)
74
+ user_context_fns = kwargs.pop("context_fn", None)
75
+ determinism_check = kwargs.pop("determinism_check", _DEFAULT_DETERMINISM_MODE)
76
+ debug = kwargs.pop("debug", False)
77
+
78
+ if kwargs:
79
+ raise ValueError(
80
+ "Unexpected keyword arguments: " + ",".join(arg for arg in kwargs)
81
+ )
82
+
83
+ def forward_pre_hook(
84
+ module: nn.Module, args: Tuple[Any, ...], kwargs: Dict[str, Any]
85
+ ) -> None:
86
+ if checkpoint.state(module).enable_hook:
87
+
88
+ def context_fns():
89
+ if user_context_fns is not None:
90
+ ctx1, ctx2 = user_context_fns()
91
+ return ctx1, _no_hook(module, ctx2)
92
+ else:
93
+ return nullcontext(), _no_hook(module)
94
+
95
+ checkpoint.state(
96
+ module
97
+ )._ac_generator = _checkpoint_without_reentrant_generator(
98
+ module,
99
+ preserve_rng_state,
100
+ context_fns,
101
+ determinism_check,
102
+ debug,
103
+ *args,
104
+ **kwargs,
105
+ )
106
+ next(checkpoint.state(module)._ac_generator)
107
+
108
+ def forward_hook(module: nn.Module, inputs: Tuple[Any, ...], output: Any) -> Any:
109
+ if checkpoint.state(module).enable_hook:
110
+ try:
111
+ next(checkpoint.state(module)._ac_generator)
112
+ except StopIteration:
113
+ pass
114
+ else:
115
+ raise RuntimeError(
116
+ "Expected non-reentrant activation checkpoint generator to be exhausted, but it was not!"
117
+ )
118
+
119
+ # Ensure that we no longer hold on to the generator. always_call=True helps ensure we
120
+ # clear this even in the case of exception in fwd pass.
121
+ checkpoint.state(module)._ac_generator = None
122
+
123
+ checkpoint.state(module).enable_hook = True
124
+ module.register_forward_pre_hook(forward_pre_hook, with_kwargs=True)
125
+ module.register_forward_hook(forward_hook, prepend=True, always_call=True)
126
+ return module
lib/python3.12/site-packages/torch/distributed/_composable/contract.py ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import uuid
3
+ from collections import OrderedDict
4
+ from functools import wraps
5
+ from typing import Callable, Dict, List, Optional, Sequence, Type, Union
6
+
7
+ import torch
8
+ import torch.nn as nn
9
+ from torch.distributed._composable_state import _State
10
+ from torch.distributed.utils import _get_root_modules
11
+
12
+
13
+ def generate_state_key(string="__composable_api_state_key"):
14
+ return f"{string}_{str(uuid.uuid4())}"
15
+
16
+
17
+ STATE_KEY = generate_state_key()
18
+ REGISTRY_KEY = generate_state_key()
19
+
20
+
21
+ # TODO: we can add additional info to RegistryItem to share across APIs. E.g.,
22
+ # we can add args and kwargs here, and then we can detect whether fully_shard
23
+ # is combined with reentrant activation checkpointing and error out with a clear
24
+ # message.
25
+ class RegistryItem:
26
+ pass
27
+
28
+
29
+ def contract(state_cls: Type[_State] = _State):
30
+ r"""
31
+ Decorate a function as a composable distributed API, where the first
32
+ argument of the function must be an :class:`nn.Module` instance or sequence
33
+ of :class:`nn.Module` instances.
34
+
35
+ The decorator verifies that the decorated function does not modify
36
+ fully-qualified names (FQNs) for parameters, buffers, or modules. The
37
+ decorated function can return different module instances than the input
38
+ modules; the FQN invariant will be enforced following the input order.
39
+
40
+ When a function ``func`` is decorated by ``@contract()``, a
41
+ ``.state(module: nn.Module)`` method will be installed to the decorated
42
+ function. Then you can retrieve and modify the state on a module by calling
43
+ ``func.state(module)``.
44
+
45
+ Example::
46
+ >>> # xdoctest: +SKIP
47
+ >>> import torch.nn as nn
48
+ >>>
49
+ >>> class MyModel(nn.Module):
50
+ >>> def __init__(self) -> None:
51
+ >>> super().__init__()
52
+ >>> self.l1 = nn.Linear(10, 10)
53
+ >>> self.l2 = nn.Linear(10, 10)
54
+ >>>
55
+ >>> def forward(self, x):
56
+ >>> return self.l2(self.l1(x))
57
+ >>>
58
+ >>> @contract()
59
+ >>> def my_feature(module: nn.Module) -> nn.Module:
60
+ >>> my_feature.state(module).some_state = "any value"
61
+ >>> return module
62
+ >>>
63
+ >>> model = MyModel()
64
+ >>> my_feature(model.l1)
65
+ >>> assert my_feature.state(model.l1).some_state == "any value"
66
+ >>> my_feature(model.l2)
67
+ >>> model(torch.randn(2, 10)).sum().backward()
68
+ """
69
+
70
+ # wraps will make functions decorated with contract() pickleable - needed for integration with torch.package
71
+ @wraps(state_cls)
72
+ def inner(func):
73
+ @wraps(func)
74
+ def wrapper(
75
+ module: Union[nn.Module, Sequence[nn.Module]], *args, **kwargs
76
+ ) -> Optional[nn.Module]:
77
+ inp_module = module
78
+ if isinstance(module, nn.Module):
79
+ modules = [module]
80
+ else:
81
+ # If the user passes a sequence of modules, then we assume that
82
+ # we only need to insert the state object on the root modules
83
+ # (i.e. those without a parent) among the passed-in modules.
84
+ modules = _get_root_modules(list(module))
85
+ state = state_cls() # shared across all modules
86
+ registry_item = RegistryItem() # shared across all modules
87
+
88
+ # `func` is allowed to return different module instances than the
89
+ # input modules as long as FQNs are preserved following the input
90
+ # module order
91
+ all_orig_named_params: List[Dict[str, nn.Parameter]] = []
92
+ all_orig_named_buffers: List[Dict[str, torch.Tensor]] = []
93
+ all_orig_named_modules: List[Dict[str, nn.Module]] = []
94
+
95
+ for module in modules:
96
+ default_all_state: Dict[Callable, _State] = OrderedDict()
97
+ default_registry: Dict[str, RegistryItem] = OrderedDict()
98
+ all_state: Dict[Callable, _State] = module.__dict__.setdefault( # type: ignore[call-overload]
99
+ STATE_KEY, default_all_state
100
+ )
101
+ if not isinstance(all_state, dict):
102
+ raise AssertionError(
103
+ f"Distributed composable API states corrupted: {all_state}"
104
+ )
105
+ registry: Dict[str, RegistryItem] = module.__dict__.setdefault( # type: ignore[call-overload]
106
+ REGISTRY_KEY, default_registry
107
+ )
108
+ if not isinstance(registry, dict):
109
+ raise AssertionError(
110
+ f"Distributed composable API registry corrupted: {registry}"
111
+ )
112
+ if func in all_state or func.__name__ in registry:
113
+ raise AssertionError(
114
+ "Each distinct composable distributed API can only be applied to a "
115
+ f"module once. {func.__name__} has already been applied to the "
116
+ f"following module:\n{module}"
117
+ )
118
+ all_state.setdefault(func, state)
119
+ registry.setdefault(func.__name__, registry_item)
120
+
121
+ all_orig_named_params.append(OrderedDict(module.named_parameters()))
122
+ all_orig_named_buffers.append(OrderedDict(module.named_buffers()))
123
+ all_orig_named_modules.append(OrderedDict(module.named_modules()))
124
+
125
+ updated = func(inp_module, *args, **kwargs)
126
+ if updated is None:
127
+ updated = inp_module
128
+ if isinstance(updated, nn.Module):
129
+ updated_modules = [updated]
130
+ else:
131
+ updated_modules = _get_root_modules(list(inp_module)) # type: ignore[arg-type]
132
+
133
+ all_new_named_params: List[Dict[str, nn.Parameter]] = []
134
+ all_new_named_buffers: List[Dict[str, torch.Tensor]] = []
135
+ all_new_named_modules: List[Dict[str, nn.Module]] = []
136
+ for module in updated_modules:
137
+ all_new_named_params.append(OrderedDict(module.named_parameters()))
138
+ all_new_named_buffers.append(OrderedDict(module.named_buffers()))
139
+ all_new_named_modules.append(OrderedDict(module.named_modules()))
140
+
141
+ num_orig_modules = len(all_orig_named_modules)
142
+ num_new_modules = len(all_new_named_modules)
143
+ if num_orig_modules != num_new_modules:
144
+ raise AssertionError(
145
+ f"{func.__name__} should return the same number of modules as input modules"
146
+ f"Inputs: {num_orig_modules} modules\n"
147
+ f"Outputs: {num_new_modules} modules"
148
+ )
149
+
150
+ def check_fqn(orig_fqns: List[str], new_fqns: List[str], check_key: str):
151
+ if orig_fqns == new_fqns:
152
+ return
153
+
154
+ orig_fqn_set, new_fqn_set = set(orig_fqns), set(new_fqns)
155
+ orig_only = orig_fqn_set - new_fqn_set
156
+ new_only = new_fqn_set - orig_fqn_set
157
+ if len(orig_only) or len(new_only):
158
+ raise RuntimeError(
159
+ f"{check_key}"
160
+ "Composable distributed API implementations cannot modify FQNs.\n"
161
+ f"FQNs only in original: {orig_only}\n"
162
+ f"FQNs only in new: {new_only}"
163
+ )
164
+ else:
165
+ raise RuntimeError(
166
+ f"{check_key}"
167
+ "Composable distributed API implementations cannot modify "
168
+ "the order of FQNs.\n"
169
+ f"Original FQNs: {orig_only}\n"
170
+ f"New FQNs: {new_only}"
171
+ )
172
+
173
+ for orig_named_params, new_named_params in zip(
174
+ all_orig_named_params, all_new_named_params
175
+ ):
176
+ check_fqn(
177
+ list(orig_named_params.keys()),
178
+ list(new_named_params.keys()),
179
+ "Checking parameters: ",
180
+ )
181
+ for orig_named_buffers, new_named_buffers in zip(
182
+ all_orig_named_buffers, all_new_named_buffers
183
+ ):
184
+ check_fqn(
185
+ list(orig_named_buffers.keys()),
186
+ list(new_named_buffers.keys()),
187
+ "Checking buffers: ",
188
+ )
189
+ for orig_named_modules, new_named_modules in zip(
190
+ all_orig_named_modules, all_new_named_modules
191
+ ):
192
+ check_fqn(
193
+ list(orig_named_modules.keys()),
194
+ list(new_named_modules.keys()),
195
+ "Checking modules: ",
196
+ )
197
+
198
+ # TODO: verify that installed distributed paradigms are compatible with
199
+ # each other.
200
+
201
+ return updated
202
+
203
+ def get_state(module: nn.Module) -> Optional[_State]:
204
+ return module.__dict__.setdefault( # type: ignore[call-overload]
205
+ STATE_KEY,
206
+ {}, # TODO(@yhcharles): this is a temporary fix, need a better way
207
+ ).get(
208
+ func
209
+ ) # type: ignore[call-overload]
210
+
211
+ wrapper.state = get_state # type: ignore[attr-defined]
212
+
213
+ return wrapper
214
+
215
+ return inner
216
+
217
+
218
+ def _get_registry(module: nn.Module) -> Optional[Dict[str, RegistryItem]]:
219
+ r"""
220
+ Get an ``OrderedDict`` of composable APIs that have been applied to the
221
+ ``module``, indexed by the API name. If no API has been applied, then this
222
+ returns ``None``.
223
+ """
224
+ return getattr(module, REGISTRY_KEY, None)
lib/python3.12/site-packages/torch/distributed/_composable/fsdp/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from torch.distributed.fsdp import CPUOffloadPolicy, MixedPrecisionPolicy, OffloadPolicy
2
+
3
+ from .fully_shard import FSDPModule, fully_shard, register_fsdp_forward_method
lib/python3.12/site-packages/torch/distributed/_composable/fsdp/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (440 Bytes). View file
 
lib/python3.12/site-packages/torch/distributed/_composable/fsdp/__pycache__/fully_shard.cpython-312.pyc ADDED
Binary file (368 Bytes). View file
 
lib/python3.12/site-packages/torch/distributed/_composable/fsdp/fully_shard.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # TODO: For backward compatibility, we are importing the public objects
2
+ # originally from this file.
3
+ from torch.distributed.fsdp import ( # noqa: F401
4
+ FSDPModule,
5
+ fully_shard,
6
+ register_fsdp_forward_method,
7
+ UnshardHandle,
8
+ )
lib/python3.12/site-packages/torch/distributed/_composable/replicate.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-decorators
2
+ # mypy: allow-untyped-defs
3
+ import weakref
4
+ from typing import Any, cast, Dict, Iterable, List, NoReturn, Optional, Set, Tuple
5
+
6
+ import torch
7
+ import torch.nn as nn
8
+ from torch.distributed._composable_state import _State
9
+ from torch.nn.parallel import DistributedDataParallel
10
+
11
+ from .contract import _get_registry, contract
12
+
13
+
14
+ _ROOT_MODULE_PREFIX = ""
15
+
16
+
17
+ class _ReplicateState(_State):
18
+ def __init__(self) -> None:
19
+ super().__init__()
20
+ self.module: nn.Module = nn.ParameterList()
21
+ self.has_initialized: bool = False
22
+ self._param_list: nn.ParameterList = nn.ParameterList()
23
+ # TODO(@fegin): this variable is originally create for testing, we
24
+ # should remove this if possible.
25
+ self._orig_module = self.module
26
+ self._param_names: List[str] = []
27
+ self._no_sync: bool = False
28
+ self._init_args: Optional[Tuple[Any, ...]] = None
29
+ self._init_kwargs: Dict[str, Any] = {}
30
+ self._comm_hook_args: List[Any] = []
31
+
32
+ def _collect_params(
33
+ self,
34
+ module: nn.Module,
35
+ ignored_modules: Set[nn.Module],
36
+ ignored_params: Set[nn.Parameter],
37
+ prefix: str = _ROOT_MODULE_PREFIX,
38
+ ) -> None:
39
+ # skip if managed by fully_sharded API
40
+ if _is_fully_sharded(module):
41
+ return
42
+
43
+ # if a module is ignored, all descendants of the module are ignored.
44
+ if module in ignored_modules:
45
+ return
46
+
47
+ recurse_prefix = (
48
+ f"{prefix}." if prefix != _ROOT_MODULE_PREFIX else _ROOT_MODULE_PREFIX
49
+ )
50
+
51
+ for n, p in module.named_parameters(recurse=False):
52
+ if p not in ignored_params:
53
+ self._param_list.append(p)
54
+ self._param_names.append(f"{recurse_prefix}{n}")
55
+
56
+ for name, child_module in module.named_children():
57
+ self._collect_params(
58
+ child_module,
59
+ ignored_modules,
60
+ ignored_params,
61
+ prefix=f"{recurse_prefix}{name}",
62
+ )
63
+
64
+ def lazy_init(self) -> None:
65
+ @torch._disable_dynamo(recursive=True)
66
+ def _lazy_init():
67
+ assert self._init_args is not None
68
+ self.init(*self._init_args, **self._init_kwargs)
69
+ self.register_comm_hook()
70
+ self._init_args = ()
71
+ self._init_kwargs = {}
72
+
73
+ _lazy_init()
74
+
75
+ def init(
76
+ self,
77
+ module: nn.Module,
78
+ ignored_modules: Set[nn.Module],
79
+ **kwargs,
80
+ ) -> None:
81
+ if self.has_initialized:
82
+ return
83
+
84
+ self.has_initialized = True
85
+ self.module = module
86
+ ignored_params = {p for m in ignored_modules for p in m.parameters()}
87
+ for submodule in module.modules():
88
+ if _is_fully_sharded(submodule):
89
+ ignored_params.update(submodule.parameters())
90
+ from torch.distributed.tensor.parallel.ddp import _localize_dtensor
91
+
92
+ _localize_dtensor(module, ignored_params=ignored_params)
93
+ self._collect_params(module, ignored_modules, ignored_params)
94
+
95
+ if "device_id" in kwargs:
96
+ # replicate() supports a small usability enhancement where
97
+ # user can pass in device_id as a Union[int, torch.device] even for
98
+ # CPU devices so users don't have to change code for CPU/GPU runs.
99
+ # We derive the right device_ids to feed into DDP to support this.
100
+ if kwargs["device_id"] is not None:
101
+ device_id = kwargs["device_id"]
102
+ # Convert to device_ids that DDP expects.
103
+ if isinstance(device_id, torch.device) and device_id.type == "cpu":
104
+ # CPU modules receive device_ids None
105
+ kwargs["device_ids"] = None
106
+ else:
107
+ # GPU modules expect device_ids=[cuda_device]
108
+ kwargs["device_ids"] = [device_id]
109
+ else:
110
+ kwargs["device_ids"] = None
111
+ kwargs.pop("device_id")
112
+
113
+ self._ddp = DistributedDataParallel(self._param_list, **kwargs)
114
+ # Weakref to the DDP instance is currently only used for testing.
115
+ replicate.state(self.module)._ddp_weakref = weakref.ref(self._ddp)
116
+
117
+ def register_comm_hook(self) -> None:
118
+ for comm_args, comm_kwargs in self._comm_hook_args:
119
+ self._ddp.register_comm_hook(*comm_args, **comm_kwargs)
120
+ self._comm_hook_args.clear()
121
+
122
+ def record_init_args(self, *args, **kwargs) -> None:
123
+ self._init_args = args
124
+ self._init_kwargs = kwargs
125
+
126
+ def forward_pre_hook(
127
+ self, module: nn.Module, args: Tuple[Any, ...], kwargs: Dict[str, Any]
128
+ ) -> Any:
129
+ if self._init_args or self._init_kwargs:
130
+ self.lazy_init()
131
+ self._ddp.require_backward_grad_sync = not self._no_sync
132
+ return self._ddp._pre_forward(*args, **kwargs)
133
+
134
+ def forward_post_hook(
135
+ self,
136
+ module: nn.Module,
137
+ input: Tuple[torch.Tensor],
138
+ output: torch.Tensor,
139
+ ) -> torch.Tensor:
140
+ return self._ddp._post_forward(output)
141
+
142
+
143
+ def unimplemented_deepcopy(*args: Any, **kwargs: Any) -> NoReturn:
144
+ raise AssertionError(
145
+ "DDP does not support deepcopy. Please use state dict for serialization."
146
+ )
147
+
148
+
149
+ # Follow the same pattern as FSDP/fully_shard
150
+ class DDP:
151
+ def __new__(cls, *args, **kwargs):
152
+ """
153
+ Override ``__new__`` to remove the DDP class and directly construct
154
+ the original class for cases like indexing into a container module.
155
+ """
156
+ # Use index 2 since 0 is the dynamically constructed `DDP<...>` class
157
+ # and index 1 is the `DDP` class itself
158
+ orig_cls = cls.__mro__[2]
159
+ return orig_cls.__new__(orig_cls, *args, **kwargs)
160
+
161
+ def set_requires_gradient_sync(self, requires_gradient_sync: bool) -> None:
162
+ """
163
+ Sets if the module should sync gradients. This can be used to implement
164
+ gradient accumulation without communication.
165
+
166
+ Args:
167
+ requires_gradient_sync (bool): Whether to reduce gradients for the
168
+ module's parameters.
169
+ """
170
+ replicate.state(self)._no_sync = not requires_gradient_sync
171
+
172
+ def register_comm_hook(self, *args, **kwargs) -> None:
173
+ replicate.state(self)._comm_hook_args.append((args, kwargs))
174
+
175
+
176
+ @contract(state_cls=_ReplicateState)
177
+ def replicate(
178
+ module: nn.Module,
179
+ ignored_modules: Optional[Iterable[torch.nn.Module]] = None,
180
+ **kwargs,
181
+ ) -> nn.Module:
182
+ r"""Replicates a module
183
+
184
+ Args:
185
+ module (torch.nn.Module): module to replicate
186
+
187
+ Example::
188
+ >>> # xdoctest: +REQUIRES(module:torch._C._distributed_c10d)
189
+ >>> module = nn.Linear(3, 3)
190
+ >>> replicate(module)
191
+ """
192
+ torch._C._log_api_usage_once("torch.distributed.replicate")
193
+
194
+ # TODO(fegin): using kwargs is not a good idea if we would like to make
195
+ # replicate a formal API to replace DDP.
196
+ if "device_id" in kwargs:
197
+ if not isinstance(kwargs["device_id"], (int, torch.device)):
198
+ raise RuntimeError(
199
+ "Expected device_id to be int or torch.device, "
200
+ f"but got {type(kwargs['device_id'])}"
201
+ )
202
+
203
+ if _is_fully_sharded(module):
204
+ raise RuntimeError(
205
+ "Cannot apply `replicate()` on a Module already managed by `fully_shard`"
206
+ )
207
+
208
+ if ignored_modules is None:
209
+ ignored_modules = {}
210
+ else:
211
+ ignored_modules = set(ignored_modules)
212
+
213
+ state = cast(_ReplicateState, replicate.state(module))
214
+ module.register_forward_pre_hook(state.forward_pre_hook, with_kwargs=True)
215
+ device_mesh = kwargs.get("device_mesh", None)
216
+ if device_mesh is not None:
217
+ from torch.distributed.device_mesh import _mesh_resources
218
+
219
+ root_mesh = _mesh_resources.get_root_mesh(device_mesh)
220
+ # if a root mesh is not the same as device_mesh,
221
+ # meaning the device_mesh is sliced out from the root mesh.
222
+ if root_mesh != device_mesh:
223
+ # TODO: This is a temporary work around to enable DDP + TP.
224
+ # We should do the logic in DDP so that the 2D implementation is
225
+ # sound and the state_dict works out of the box.
226
+ #
227
+ # This won't conflict with what is done in DDP class as the module
228
+ # replicate is going to pass is NOT the original module.
229
+ from torch.distributed.tensor.parallel.ddp import (
230
+ _localize_dtensor,
231
+ _reconstruct_dtensor,
232
+ )
233
+
234
+ module.register_forward_pre_hook(_reconstruct_dtensor)
235
+ module.register_forward_hook(_localize_dtensor)
236
+
237
+ module.register_forward_hook(state.forward_post_hook) # type: ignore[arg-type]
238
+
239
+ state.record_init_args(module, ignored_modules, **kwargs)
240
+
241
+ # Place DDP leftmost for highest priority in the method resolution order
242
+ cls = module.__class__
243
+ dct = {"__deepcopy__": unimplemented_deepcopy}
244
+ new_cls = type(f"DDP{cls.__name__}", (DDP, cls), dct)
245
+ module.__class__ = new_cls
246
+ return module
247
+
248
+
249
+ def _is_fully_sharded(module: nn.Module) -> bool:
250
+ r"""Check if module is marked with fully_shard."""
251
+ registry = _get_registry(module)
252
+ if registry is None:
253
+ return False
254
+ return "fully_shard" in registry
lib/python3.12/site-packages/torch/distributed/_sharded_tensor/__init__.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Keep old package for BC purposes, this file should be removed once
2
+ # everything moves to the `torch.distributed._shard` package.
3
+ import sys
4
+ import warnings
5
+
6
+ import torch
7
+ from torch.distributed._shard.sharded_tensor import * # noqa: F403
8
+
9
+
10
+ with warnings.catch_warnings():
11
+ warnings.simplefilter("always")
12
+ warnings.warn(
13
+ "`torch.distributed._sharded_tensor` will be deprecated, "
14
+ "use `torch.distributed._shard.sharded_tensor` instead",
15
+ DeprecationWarning,
16
+ stacklevel=2,
17
+ )
18
+
19
+ sys.modules[
20
+ "torch.distributed._sharded_tensor"
21
+ ] = torch.distributed._shard.sharded_tensor
lib/python3.12/site-packages/torch/distributed/_sharded_tensor/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (972 Bytes). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .join import Join, Joinable, JoinHook
lib/python3.12/site-packages/torch/distributed/algorithms/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (284 Bytes). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/__pycache__/join.cpython-312.pyc ADDED
Binary file (15.5 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/_checkpoint/__init__.py ADDED
File without changes
lib/python3.12/site-packages/torch/distributed/algorithms/_checkpoint/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (219 Bytes). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/_checkpoint/__pycache__/checkpoint_wrapper.cpython-312.pyc ADDED
Binary file (14 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/_checkpoint/checkpoint_wrapper.py ADDED
@@ -0,0 +1,323 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import warnings
3
+ from abc import ABC, abstractmethod
4
+ from enum import auto, Enum
5
+ from functools import partial
6
+ from typing import Any, Callable, Dict, Iterator, Optional, Tuple
7
+
8
+ import torch
9
+ import torch.nn as nn
10
+ from torch.autograd.graph import save_on_cpu
11
+ from torch.distributed.utils import _pack_kwargs, _replace_by_prefix, _unpack_kwargs
12
+ from torch.utils.checkpoint import checkpoint as torch_utils_checkpoint
13
+
14
+
15
+ _CHECKPOINT_WRAPPED_MODULE = "_checkpoint_wrapped_module"
16
+ _CHECKPOINT_PREFIX = _CHECKPOINT_WRAPPED_MODULE + "."
17
+
18
+
19
+ class CheckpointImpl(Enum):
20
+ REENTRANT = auto()
21
+ NO_REENTRANT = auto()
22
+
23
+
24
+ class ActivationWrapper(torch.nn.Module, ABC):
25
+ """
26
+ Base class for Activation Checkpoint and Activation Offload.
27
+
28
+ Not meant to be instantiated directly.
29
+ """
30
+
31
+ def __init__(self, mod):
32
+ super().__init__()
33
+ self._checkpoint_wrapped_module = mod
34
+ # state_dict post hook to remove prefix to allow loading into a
35
+ # non-checkpoint wrapped module.
36
+ self._register_state_dict_hook(self._post_state_dict_hook)
37
+ # load_state_dict pre-hook to allow loading back into
38
+ # checkpoint-wrapped module.
39
+ self.register_load_state_dict_pre_hook(self._pre_load_state_dict_hook)
40
+
41
+ @abstractmethod
42
+ def forward(self, *args, **kwargs):
43
+ raise ValueError("Subclasses should implement forward().")
44
+
45
+ def __getattr__(self, name: str) -> Any:
46
+ """Forward missing attributes to wrapped module."""
47
+ try:
48
+ return super().__getattr__(name) # defer to nn.Module's logic
49
+ except AttributeError:
50
+ return getattr(self._checkpoint_wrapped_module, name)
51
+
52
+ def __getitem__(self, key: int) -> Any:
53
+ """Forward indexing calls in case the module is a nn.Sequential."""
54
+ return self._checkpoint_wrapped_module.__getitem__(key) # type: ignore[operator]
55
+
56
+ def named_parameters(
57
+ self,
58
+ *args,
59
+ **kwargs,
60
+ ) -> Iterator[Tuple[str, torch.nn.Parameter]]:
61
+ """
62
+ Override :meth:`named_parameters()` to intercept parameter names.
63
+
64
+ remove all occurrences of ``_CHECKPOINT_PREFIX``.
65
+ """
66
+ for param_name, param in super().named_parameters(*args, **kwargs):
67
+ yield param_name.replace(_CHECKPOINT_PREFIX, ""), param
68
+
69
+ @staticmethod
70
+ def _post_state_dict_hook(
71
+ module: nn.Module,
72
+ state_dict: Dict[str, Any],
73
+ prefix: str,
74
+ *args: Any,
75
+ ) -> Dict[str, Any]:
76
+ """
77
+ _post_state_dict_hook() is called after the state_dict() of this FSDP module is executed.
78
+
79
+ For ``checkpoint_wrapper``, it will strip checkpoint-wrapped module prefix,
80
+ so that this module can be loaded into non-checkpointed modules.
81
+ It would still be able to be loaded into checkpoint-wrapped modules as this class,
82
+ adds the prefix back before loading the state_dict.
83
+ """
84
+ _replace_by_prefix(state_dict, f"{prefix}{_CHECKPOINT_PREFIX}", prefix)
85
+ return state_dict
86
+
87
+ @staticmethod
88
+ def _pre_load_state_dict_hook(
89
+ module: nn.Module,
90
+ state_dict: Dict[str, Any],
91
+ prefix: str,
92
+ *args: Any,
93
+ ) -> None:
94
+ """
95
+ ``_pre_state_dict_hook` is called before ``self._load_from_state_dict()`` is called.
96
+
97
+ For ``checkpoint_wrapper``, it will add back the module
98
+ prefix so that non-checkpointed modules can be loaded into
99
+ checkpoint_wrapper modules properly.
100
+ """
101
+ _replace_by_prefix(state_dict, prefix, prefix + f"{_CHECKPOINT_PREFIX}")
102
+
103
+
104
+ class OffloadWrapper(ActivationWrapper):
105
+ def __init__(self, mod):
106
+ super().__init__(mod)
107
+
108
+ def forward(self, *args, **kwargs):
109
+ with save_on_cpu(pin_memory=True):
110
+ return self._checkpoint_wrapped_module(*args, **kwargs)
111
+
112
+
113
+ class CheckpointWrapper(ActivationWrapper):
114
+ """
115
+ An ``nn.Module`` that wraps another ``nn.Module`` with checkpointing.
116
+
117
+ Note that this module is not meant to be used directly but instead,
118
+ it is to be used through the ``checkpoint_wrapper`` function.
119
+ """
120
+
121
+ def __init__(
122
+ self,
123
+ mod: torch.nn.Module,
124
+ checkpoint_impl: CheckpointImpl = CheckpointImpl.NO_REENTRANT,
125
+ checkpoint_fn=None,
126
+ **checkpoint_fn_kwargs,
127
+ ):
128
+ super().__init__(mod)
129
+ self.checkpoint_impl = checkpoint_impl
130
+ if checkpoint_fn is None:
131
+ # use torch.utils.checkpoint
132
+ self.checkpoint_fn = partial(
133
+ torch_utils_checkpoint,
134
+ use_reentrant=(self.checkpoint_impl == CheckpointImpl.REENTRANT),
135
+ **checkpoint_fn_kwargs,
136
+ )
137
+ else:
138
+ # Construct user-specified checkpoint function.
139
+ self.checkpoint_fn = partial(
140
+ checkpoint_fn,
141
+ **checkpoint_fn_kwargs,
142
+ )
143
+
144
+ def forward(self, *args, **kwargs):
145
+ # Support keyword arguments for reentrant checkpoint. Note that this
146
+ # only works if user has specified self.checkpoint_impl and is not
147
+ # using their own custom checkpoint_fn.
148
+ if self.checkpoint_impl == CheckpointImpl.REENTRANT and kwargs != {}:
149
+ # Pack the args and kwargs
150
+ flat_args, kwarg_keys = _pack_kwargs(*args, **kwargs)
151
+
152
+ # Function that only takes (packed) args, but can unpack them
153
+ # into the original args and kwargs for the checkpointed
154
+ # function, and runs that function.
155
+ def my_function(*inputs):
156
+ # unpack back into args and kwargs
157
+ unpacked_args, unpacked_kwargs = _unpack_kwargs(inputs, kwarg_keys)
158
+ # run original module
159
+ return self._checkpoint_wrapped_module(
160
+ *unpacked_args, **unpacked_kwargs
161
+ )
162
+
163
+ # Pass the function that only takes packed args into reentrant
164
+ # checkpoint API.
165
+ return self.checkpoint_fn( # type: ignore[misc]
166
+ my_function,
167
+ *flat_args,
168
+ )
169
+ else:
170
+ return self.checkpoint_fn( # type: ignore[misc]
171
+ self._checkpoint_wrapped_module, *args, **kwargs
172
+ )
173
+
174
+
175
+ def offload_wrapper(module: torch.nn.Module) -> torch.nn.Module:
176
+ """
177
+ Wrap a module for activation offloading to CPU.
178
+
179
+ Offloads intermediate activations to the CPU for modules wrapped with this function.
180
+ Wrappers with activation offload can be composed with ones that do recomputation-based
181
+ checkpoint to trade off increased compute versus increased CPU
182
+ memory usage and additional H2D transfers.
183
+
184
+ Usage::
185
+ offloaded_module = offload_wrapper(module)
186
+ outputs = checkpointed_module(inputs)
187
+ Args:
188
+ module (nn.Module):
189
+ The module to be wrapped
190
+ Returns:
191
+ (nn.Module):
192
+ Wrapped module
193
+ """
194
+ return OffloadWrapper(module)
195
+
196
+
197
+ def checkpoint_wrapper(
198
+ module: torch.nn.Module,
199
+ checkpoint_impl: CheckpointImpl = CheckpointImpl.NO_REENTRANT,
200
+ checkpoint_fn=None,
201
+ **checkpoint_fn_kwargs,
202
+ ) -> torch.nn.Module:
203
+ """
204
+ Wrap a module for activation checkpointing.
205
+
206
+ If the module is wrapped with this function, all subsequent calls to the module will,
207
+ automatically perform checkpointing without the user having to explicitly call ``checkpoint`` function.
208
+
209
+ Usage::
210
+ checkpointed_module = checkpoint_wrapper(module)
211
+ outputs = checkpointed_module(inputs)
212
+ Args:
213
+ module (nn.Module):
214
+ The module to be wrapped
215
+ checkpoint_impl (Optional[CheckpointImpl]):
216
+ The checkpointing implementation to use. Note that this will only
217
+ be passed into the ``torch.utils.checkpoint.checkpoint``
218
+ implementation, and is ignored if a custom ``checkpoint_fn`` is
219
+ specified. Note that for implementations using reentrant checkpoint
220
+ from ``torch.utils.checkpoint``, keyword arguments will only be
221
+ supported if ``checkpoint_impl`` is passed as ``CheckpointImpl.REENTRANT`.
222
+ checkpoint_fn (Optional[Callable]):
223
+ Functional checkpoint implementation to use. If this is specified,
224
+ it will be used over the default ``torch.utils.checkpoint.checkpoint``
225
+ implementation and the `checkpoint_impl` argument will be ignored.
226
+ **checkpoint_fn_kwargs: (Dict[str, Any]): Keyword arguments to pass into `checkpoint_fn`.
227
+
228
+ Returns:
229
+ (nn.Module):
230
+ Wrapped module
231
+ """
232
+
233
+ if checkpoint_impl == CheckpointImpl.REENTRANT:
234
+ warnings.warn(
235
+ f"Please specify {CheckpointImpl.NO_REENTRANT} as "
236
+ f"{CheckpointImpl.REENTRANT} will soon be removed as "
237
+ "the default and eventually deprecated.",
238
+ FutureWarning,
239
+ stacklevel=2,
240
+ )
241
+ return CheckpointWrapper(
242
+ module,
243
+ checkpoint_impl,
244
+ checkpoint_fn,
245
+ **checkpoint_fn_kwargs,
246
+ )
247
+
248
+
249
+ def apply_activation_checkpointing(
250
+ model,
251
+ checkpoint_wrapper_fn=checkpoint_wrapper,
252
+ check_fn=lambda _: True,
253
+ auto_wrap_policy: Optional[Callable[[nn.Module, bool, int], bool]] = None,
254
+ ):
255
+ """
256
+ Apply :func:`checkpoint_wrapper` to modules within `model` based on a user-defined configuration.
257
+
258
+ For each module within `model`, the `check_fn` is used to decide
259
+ whether `module` should be wrapped with :func:`checkpoint_wrapper` or not.
260
+
261
+ Note::
262
+ This function modifies `model` in place and replaces appropriate layers with
263
+ their checkpoint-wrapped modules.
264
+ Note::
265
+ This function will not wrap the overall root module. If this is needed, please directly use
266
+ :func:`checkpoint_wrapper` or :func:`offload_wrapper`.
267
+ Usage::
268
+ model = nn.Sequential(
269
+ nn.Linear(10, 10), nn.Linear(10, 10), nn.Linear(10, 10)
270
+ )
271
+ check_fn = lambda l: isinstance(l, nn.Linear)
272
+ # checkpoint activations
273
+ apply_activation_checkpointing(model, checkpoint_wrapper_fn=checkpoint_wrapper, check_fn=check_fn)
274
+ # Or offload activations to CPU
275
+ apply_activation_checkpointing(model, checkpoint_wrapper_fn=offload_wrapper, check_fn=check_fn)
276
+ Args:
277
+ model (nn.Module):
278
+ The model whose submodules should be wrapped with activation checkpointing.
279
+ checkpoint_wrapper_fn (Optional[Callable[nn.Module]])
280
+ A ``Callable`` which will wrap modules
281
+ check_fn (Optional[Callable[nn.Module, nn.Module]])
282
+ A lambda function which will be passed each child submodule of ``model`` and returns
283
+ ``True`` or ``False`` depending on whether the submodule should be wrapped.
284
+ auto_wrap_policy (Optional[Callable[[nn.Module, bool, int], bool]]): A policy to wrap model's
285
+ submodules with AC. Note that if this is specified, it takes precedence over ``check_fn``.
286
+ Returns: None (`model` is modified inplace)
287
+ """
288
+ # TODO: Importing inside function to avoid circular import issue between FSDP and
289
+ # checkpoint_wrapper. This can be resolved once wrap() APIs are decoupled from FSDP code.
290
+ from torch.distributed.fsdp._wrap_utils import _construct_wrap_fn, _post_order_apply
291
+ from torch.distributed.fsdp.wrap import (
292
+ _Policy,
293
+ _recursive_wrap,
294
+ lambda_auto_wrap_policy,
295
+ )
296
+
297
+ policy = (
298
+ auto_wrap_policy
299
+ if auto_wrap_policy is not None
300
+ else partial(lambda_auto_wrap_policy, lambda_fn=check_fn)
301
+ )
302
+ if not callable(policy):
303
+ if not isinstance(policy, _Policy):
304
+ raise ValueError(
305
+ f"Expected {policy} to be callable or be a pre-defined wrap policy"
306
+ )
307
+ target_module_to_kwargs = policy._run_policy(
308
+ model, ignored_modules=set(), root_kwargs={}
309
+ )
310
+ wrap_fn = _construct_wrap_fn(
311
+ model, target_module_to_kwargs, checkpoint_wrapper_fn
312
+ )
313
+ _post_order_apply(model, wrap_fn)
314
+ return
315
+
316
+ _recursive_wrap(
317
+ module=model,
318
+ auto_wrap_policy=policy, # type: ignore[arg-type]
319
+ wrapper_cls=checkpoint_wrapper_fn,
320
+ ignored_modules=set(),
321
+ ignored_params=set(),
322
+ only_wrap_children=True,
323
+ )
lib/python3.12/site-packages/torch/distributed/algorithms/_comm_hooks/__init__.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from . import default_hooks as default
2
+
3
+
4
+ LOW_PRECISION_HOOKS = [
5
+ default.fp16_compress_hook,
6
+ default.bf16_compress_hook,
7
+ ]
lib/python3.12/site-packages/torch/distributed/algorithms/_comm_hooks/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (406 Bytes). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/_comm_hooks/__pycache__/default_hooks.cpython-312.pyc ADDED
Binary file (9.49 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/_comm_hooks/default_hooks.py ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import functools
3
+ from typing import Optional
4
+
5
+ import torch
6
+ import torch.distributed as dist
7
+
8
+
9
+ class DefaultState:
10
+ r"""
11
+ Stores state needed to perform the default communication algorithm within a communication hook.
12
+
13
+ Args:
14
+ process_group (ProcessGroup): The process group to be used.
15
+ """
16
+
17
+ __slots__ = [
18
+ "process_group",
19
+ "world_size",
20
+ "gradient_predivide_factor",
21
+ "gradient_postdivide_factor",
22
+ ]
23
+
24
+ def __init__(self, process_group: dist.ProcessGroup):
25
+ if process_group is None:
26
+ raise ValueError(f"Expected to pass in an explicit ProcessGroup to {self}.")
27
+ self.process_group = process_group
28
+ self.world_size = dist.get_world_size(process_group)
29
+ # Setting two factors `self.gradient_predivide_factor`
30
+ # and `self.gradient_postdivide_factor` to avoid underflow and overflow
31
+ self.gradient_predivide_factor = self._get_gradient_predivide_factor(
32
+ self.world_size
33
+ )
34
+ self.gradient_postdivide_factor = (
35
+ self.world_size / self.gradient_predivide_factor
36
+ )
37
+
38
+ @staticmethod
39
+ def _get_gradient_predivide_factor(world_size: int) -> float:
40
+ factor: int = 1
41
+ while world_size % factor == 0 and world_size / factor > factor:
42
+ factor *= 2
43
+ return float(factor)
44
+
45
+
46
+ class LowPrecisionState(DefaultState):
47
+ r"""
48
+ Stores state needed to perform gradient communication in a lower precision within a communication hook.
49
+
50
+ Communication hook will cast gradients back to the original
51
+ parameter precision specified by ``parameter_type`` (default: torch.float32).
52
+ Builds on top of the :class:`DefaultState`.
53
+
54
+ Args:
55
+ parameter_type (torch.dtype): The precision of model's parameters.
56
+ Required for a hook to cast gradients back to a parameter's precision.
57
+ """
58
+
59
+ __slots__ = [
60
+ "parameter_type",
61
+ ]
62
+
63
+ def __init__(
64
+ self,
65
+ process_group,
66
+ parameter_type=torch.float32,
67
+ ):
68
+ super().__init__(process_group)
69
+ self.parameter_type = parameter_type
70
+
71
+
72
+ def _decompress(state: LowPrecisionState, grad: torch.Tensor):
73
+ """
74
+ Casts gradients back to full parameter precision so that further computation happens in full precision.
75
+ """
76
+ orig_grad_data = grad.data
77
+ grad.data = grad.data.to(state.parameter_type)
78
+ device_type = ""
79
+ try:
80
+ if grad.device.type == "privateuse1":
81
+ device_type = torch._C._get_privateuse1_backend_name()
82
+ else:
83
+ device_type = grad.device.type
84
+ backend = getattr(torch, device_type)
85
+ except AttributeError as e:
86
+ raise AttributeError(
87
+ f"Device {grad.device} does not have a \
88
+ corresponding backend registered as 'torch.device_type'."
89
+ ) from e
90
+
91
+ # Don't let this memory get reused until after the transfer.
92
+ orig_grad_data.record_stream(backend.current_stream()) # type: ignore[arg-type]
93
+
94
+
95
+ def allreduce_hook(state: DefaultState, grad: torch.Tensor):
96
+ r"""
97
+ Implement the FSDP communication hook for ``all_reduce`` algorithm and a necessary pre- and post-division of gradients.
98
+
99
+ Args:
100
+ state (DefaultState): State information, configures pre- and post-division factors.
101
+ grad (torch.Tensor): A gradient for the local batch that needs to be communicated across ranks.
102
+ """
103
+ # Average grad by pre-division factor. Together pre- and post-division factors
104
+ # lead to an overall averaging by world_size, required for consistency with PyTorch DDP.
105
+ # This is a two-step process to avoid potential underflow and overflow.
106
+ if state.gradient_predivide_factor > 1:
107
+ grad.div_(state.gradient_predivide_factor)
108
+ dist.all_reduce(grad, group=state.process_group)
109
+ # Average grad by post-division factor.
110
+ if state.gradient_postdivide_factor > 1:
111
+ grad.div_(state.gradient_postdivide_factor)
112
+
113
+
114
+ def reduce_scatter_hook(state: DefaultState, grad: torch.Tensor, output: torch.Tensor):
115
+ r"""
116
+ Implement the FSDP communication hook for ``reduce_scatter`` algorithm.
117
+
118
+ For sharded FSDP strategies and a necessary pre- and post-division of gradients.
119
+
120
+ Args:
121
+ state (DefaultState): State information, configures pre- and post-division factors.
122
+ grad (torch.Tensor): An unsharded gradient for the local batch that needs to be
123
+ communicated across ranks.
124
+ output (torch.Tensor): Stores a single shard of the gradient after ``reduce_scatter``.
125
+ """
126
+ # Average grad by pre-division factor.
127
+ if state.gradient_predivide_factor > 1:
128
+ grad.div_(state.gradient_predivide_factor)
129
+ dist.reduce_scatter_tensor(output, grad, group=state.process_group)
130
+ # Average grad's shard by post-division factor.
131
+ if state.gradient_postdivide_factor > 1:
132
+ output.div_(state.gradient_postdivide_factor)
133
+
134
+
135
+ def _low_precision_hook(
136
+ prec: torch.dtype,
137
+ state: LowPrecisionState,
138
+ grad: torch.Tensor,
139
+ output: Optional[torch.Tensor],
140
+ ):
141
+ if grad.dtype != prec:
142
+ grad.data = grad.data.to(prec)
143
+ if output is not None:
144
+ if output.dtype != prec:
145
+ output.data = output.data.to(prec)
146
+ reduce_scatter_hook(state, grad, output)
147
+ _decompress(state, output)
148
+ else:
149
+ allreduce_hook(state, grad)
150
+ _decompress(state, grad)
151
+
152
+
153
+ def fp16_compress_hook(
154
+ state: LowPrecisionState, grad: torch.Tensor, output: Optional[torch.Tensor] = None
155
+ ):
156
+ r"""
157
+ Implement FSDP communication hook for a simple gradient compression approach.
158
+ Casts ``grad`` to half-precision floating-point format (``torch.float16``).
159
+
160
+ It also averages gradients by ``world_size`` in two steps: first it pre-divides gradients by a
161
+ ``state.gradient_predivide_factor``, and after a communication step (``all_reduce`` or ``reduce_scatter``)
162
+ gradients are averaged by a ``state.gradient_postdivide_factor``.
163
+ Once post-division is done, compressed gradients are casted back to parameters' precision.
164
+
165
+ Args:
166
+ state (LowPrecisionState): State information, configures pre- and post-division factors, parameters' precision.
167
+ grad (torch.Tensor): A gradient for the local batch that needs to be communicated across ranks in a lower precision.
168
+ output (torch.Tensor): Stores a single shard of the gradient after ``reduce_scatter``.
169
+ """
170
+ fp16_hook = functools.partial(_low_precision_hook, torch.float16)
171
+ return fp16_hook(state, grad, output)
172
+
173
+
174
+ def bf16_compress_hook(
175
+ state: LowPrecisionState, grad: torch.Tensor, output: Optional[torch.Tensor] = None
176
+ ):
177
+ r"""
178
+ Implement FSDP communication hook for a simple gradient compression approach .
179
+ Casts ``grad`` to half-precision floating-point format.
180
+
181
+ It also averages gradients by ``world_size`` in two steps: first it pre-divides gradients by a
182
+ ``state.gradient_predivide_factor``, and after a communication step (``all_reduce`` or ``reduce_scatter``)
183
+ gradients are averaged by a ``state.gradient_postdivide_factor``.
184
+ Once post-division is done, compressed gradients are casted back to parameters' precision.
185
+
186
+ Args:
187
+ state (LowPrecisionState): State information, configures pre- and post-division factors, parameters' precision.
188
+ grad (torch.Tensor): A gradient for the local batch that needs to be communicated across ranks in a lower precision.
189
+ output (torch.Tensor): Stores a single shard of the gradient after ``reduce_scatter``.
190
+ """
191
+ bf16_hook = functools.partial(_low_precision_hook, torch.bfloat16)
192
+ return bf16_hook(state, grad, output)
lib/python3.12/site-packages/torch/distributed/algorithms/_optimizer_overlap/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .optimizer_overlap import _as_overlapped_optim
lib/python3.12/site-packages/torch/distributed/algorithms/_optimizer_overlap/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (291 Bytes). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/_optimizer_overlap/__pycache__/optimizer_overlap.cpython-312.pyc ADDED
Binary file (4.91 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/_optimizer_overlap/optimizer_overlap.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import inspect
3
+ from abc import ABC, abstractmethod
4
+ from typing import Dict, Type
5
+
6
+ from torch.distributed.algorithms.ddp_comm_hooks.default_hooks import allreduce_hook
7
+ from torch.distributed.algorithms.ddp_comm_hooks.optimizer_overlap_hooks import (
8
+ _hook_then_optimizer,
9
+ _OptimizerHookState,
10
+ )
11
+ from torch.distributed.fsdp import FullyShardedDataParallel
12
+ from torch.distributed.optim import as_functional_optim
13
+ from torch.nn.parallel import DistributedDataParallel
14
+ from torch.optim import Optimizer
15
+
16
+
17
+ # Contains the mappings between the regular and overlapped optimizer types.
18
+ _registered_overlapped_optims: Dict[Type, Type] = {}
19
+
20
+
21
+ def register_overlapped(optim_cls):
22
+ def decorator(target_overlapped_optim_cls):
23
+ if target_overlapped_optim_cls in _registered_overlapped_optims:
24
+ raise ValueError(
25
+ f"{target_overlapped_optim_cls} already registered with optim_cls "
26
+ f"{_registered_overlapped_optims[optim_cls]} {optim_cls}, trying to"
27
+ f"re-register it for {optim_cls} is not supported."
28
+ )
29
+ _registered_overlapped_optims[optim_cls] = target_overlapped_optim_cls
30
+ return target_overlapped_optim_cls
31
+
32
+ return decorator
33
+
34
+
35
+ class OverlappedOptimizer(ABC):
36
+ def __init__(self, optim_cls: Type) -> None:
37
+ """
38
+ Initialize the OverlappedOptimizer.
39
+
40
+ Overlappedoptimizer is a base class that child classes can implement to
41
+ specify how different optimizers will register themselves with DDP.
42
+ """
43
+ self.optim_cls = optim_cls
44
+
45
+ @abstractmethod
46
+ def register_ddp(self, ddp: DistributedDataParallel) -> None:
47
+ """Registers the overlapped optimizer with DDP."""
48
+ raise NotImplementedError(
49
+ f"{self.__class__.__name__} does not support overlapped DDP."
50
+ )
51
+
52
+ @abstractmethod
53
+ def register_fsdp(self, fsdp: FullyShardedDataParallel) -> None:
54
+ """Registers the overlapped optimizer with FSDP."""
55
+ raise NotImplementedError(
56
+ f"{self.__class__.__name__} does not support overlapped FSDP."
57
+ )
58
+
59
+
60
+ @register_overlapped(Optimizer)
61
+ class _OverlappedStandardOptimizer(OverlappedOptimizer):
62
+ """Overlaps a regular ``Optimizer``."""
63
+
64
+ def __init__(self, optim_cls: Type, params, *optim_args, **optim_kwargs) -> None:
65
+ super().__init__(optim_cls)
66
+ f_optim = as_functional_optim(self.optim_cls, *optim_args, **optim_kwargs)
67
+ self._opt_hook_state = _OptimizerHookState(f_optim, params)
68
+
69
+ def register_ddp(self, ddp_inst: DistributedDataParallel):
70
+ # NOTE: using a custom communication hook and fused optimizer is not
71
+ # yet supported.
72
+ ddp_inst.register_comm_hook( # type: ignore[operator]
73
+ None, # wrapped hook state
74
+ _hook_then_optimizer(allreduce_hook, self._opt_hook_state),
75
+ )
76
+
77
+ # TODO: register_fsdp once FSDP supports communication hook.
78
+ def register_fsdp(self, fsdp: FullyShardedDataParallel) -> None:
79
+ """Register the overlapped optimizer with FSDP."""
80
+ raise NotImplementedError(
81
+ f"{self.__class__.__name__} does not support overlapped FSDP."
82
+ )
83
+
84
+
85
+ def _as_overlapped_optim(optim_cls: Type, params, *args, **kwargs):
86
+ """Return a new ``OverlappedOptimizer`` instance that supports ``optim_cls``."""
87
+ for clz in inspect.getmro(optim_cls):
88
+ try:
89
+ return _registered_overlapped_optims[clz](
90
+ optim_cls, params, *args, **kwargs
91
+ )
92
+ except KeyError:
93
+ pass
94
+
95
+ # Fallback to standard overlapped optimizer, which will raise errors if user
96
+ # is attempting to use an unsupported optimizer.
97
+ return _OverlappedStandardOptimizer(optim_cls, params, *args, **kwargs)
lib/python3.12/site-packages/torch/distributed/algorithms/_quantization/__init__.py ADDED
File without changes
lib/python3.12/site-packages/torch/distributed/algorithms/_quantization/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (221 Bytes). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/_quantization/__pycache__/quantization.cpython-312.pyc ADDED
Binary file (7.84 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/_quantization/quantization.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import functools
3
+ from enum import Enum
4
+
5
+ import torch
6
+ import torch.distributed as dist
7
+
8
+
9
+ TORCH_HALF_MIN = torch.finfo(torch.float16).min
10
+ TORCH_HALF_MAX = torch.finfo(torch.float16).max
11
+
12
+
13
+ class DQuantType(Enum):
14
+ """
15
+ Different quantization methods for auto_quantize API are identified here.
16
+
17
+ auto_quantize API currently supports fp16 and bfp16 methods.
18
+ """
19
+
20
+ FP16 = ("fp16",)
21
+ BFP16 = "bfp16"
22
+
23
+ def __str__(self) -> str:
24
+ return self.value
25
+
26
+
27
+ def _fp32_to_fp16_with_clamp(tensor: torch.Tensor) -> torch.Tensor:
28
+ return torch.clamp(tensor, TORCH_HALF_MIN, TORCH_HALF_MAX).half()
29
+
30
+
31
+ def _quantize_tensor(tensor, qtype):
32
+ if not isinstance(tensor, torch.Tensor):
33
+ raise RuntimeError(
34
+ f"_quantize_tensor expecting torch.Tensor as input but found {type(tensor)}"
35
+ )
36
+ if qtype == DQuantType.FP16:
37
+ return _fp32_to_fp16_with_clamp(tensor)
38
+ elif qtype == DQuantType.BFP16:
39
+ return torch.ops.quantization._FloatToBfloat16Quantized(tensor)
40
+ else:
41
+ raise RuntimeError(f"Quantization type {qtype} is not supported")
42
+
43
+
44
+ def _quantize_tensor_list(tensor_list, qtype):
45
+ if not isinstance(tensor_list, list) or not all(
46
+ isinstance(p, torch.Tensor) for p in tensor_list
47
+ ):
48
+ raise RuntimeError(
49
+ f"_quantize_tensor_list expecting list of torch.Tensor as input but found {type(tensor_list)}"
50
+ )
51
+ quantized_tensor_list = [_quantize_tensor(t, qtype) for t in tensor_list]
52
+ return quantized_tensor_list
53
+
54
+
55
+ def _dequantize_tensor(tensor, qtype, quant_loss=None):
56
+ if not isinstance(tensor, torch.Tensor):
57
+ raise RuntimeError(
58
+ f"_dequantize_tensor expecting torch.Tensor as input but found {type(tensor)}"
59
+ )
60
+ if qtype == DQuantType.FP16:
61
+ if tensor.dtype != torch.float16:
62
+ raise RuntimeError(
63
+ f"tensor dtype is {tensor.dtype} while expected to be FP16."
64
+ )
65
+ elif tensor.dtype == torch.float16 and quant_loss is None:
66
+ return tensor.float()
67
+ else:
68
+ return tensor.float() / quant_loss
69
+ elif qtype == DQuantType.BFP16:
70
+ if tensor.dtype != torch.float16:
71
+ raise RuntimeError(
72
+ f"tensor dtype is {tensor.dtype} while expected to be FP16."
73
+ )
74
+ else:
75
+ return torch.ops.quantization._Bfloat16QuantizedToFloat(tensor)
76
+ else:
77
+ raise RuntimeError(f"Quantization type {qtype} is not supported")
78
+
79
+
80
+ def _dequantize_tensor_list(tensor_list, qtype, quant_loss=None):
81
+ if not isinstance(tensor_list, list) or not all(
82
+ isinstance(p, torch.Tensor) for p in tensor_list
83
+ ):
84
+ raise RuntimeError(
85
+ f"_dequantize_tensor_list expecting list of torch.Tensor as input but found {type(tensor_list)}"
86
+ )
87
+ dequantized_tensor_list = [_dequantize_tensor(t, qtype) for t in tensor_list]
88
+ return dequantized_tensor_list
89
+
90
+
91
+ def auto_quantize(func, qtype, quant_loss=None):
92
+ """
93
+ Quantize the input tensors, choose the precision types, and pass other necessary arguments and then dequantizes the output.
94
+
95
+ Currently it only supports:
96
+ . FP16 and BFP16 quantization method supported for gloo and nccl backends
97
+ . all_gather, all_to_all collective ops
98
+ Note: BFP16 only supports 2D tensors.
99
+ Args:
100
+ func (Callable): A function representing collective operations.
101
+ qtype (QuantType): Quantization method
102
+ quant_loss (float, optional): This can be used to improve accuracy in the dequantization.
103
+ Returns:
104
+ (Callable): the same collective as func but enables automatic quantization/dequantization.
105
+ """
106
+
107
+ @functools.wraps(func)
108
+ def wrapper(*args, **kwargs):
109
+ group = kwargs.get("group", None)
110
+ async_op = kwargs.get("async_op", False)
111
+ if async_op is True:
112
+ raise RuntimeError("The async_op=True mode is not supported yet.")
113
+ if func == dist.all_gather:
114
+ tensors = args[0]
115
+ input_tensors = _quantize_tensor(args[1], qtype)
116
+ out_tensors = _quantize_tensor_list(tensors, qtype)
117
+ dist.all_gather(out_tensors, input_tensors, group=group, async_op=async_op)
118
+ for i, t in enumerate(
119
+ _dequantize_tensor_list(out_tensors, qtype, quant_loss=quant_loss)
120
+ ):
121
+ tensors[i] = t
122
+
123
+ elif func == dist.all_to_all:
124
+ tensors = args[0]
125
+ input_tensors = _quantize_tensor_list(args[1], qtype)
126
+ out_tensors = _quantize_tensor_list(tensors, qtype)
127
+ dist.all_to_all(out_tensors, input_tensors, group=group, async_op=async_op)
128
+ for i, t in enumerate(
129
+ _dequantize_tensor_list(out_tensors, qtype, quant_loss=quant_loss)
130
+ ):
131
+ tensors[i] = t
132
+
133
+ elif func == dist.all_to_all_single:
134
+ tensors = args[0]
135
+ out_splits = kwargs.get("out_splits", None)
136
+ in_splits = kwargs.get("in_splits", None)
137
+ # Quantizing the input/output tensor
138
+ input_tensors = _quantize_tensor(args[1], qtype)
139
+ out_tensors = _quantize_tensor(tensors, qtype)
140
+ dist.all_to_all_single(
141
+ out_tensors, input_tensors, out_splits, in_splits, group=group
142
+ )
143
+ for i, t in enumerate(
144
+ _dequantize_tensor(out_tensors, qtype, quant_loss=quant_loss)
145
+ ):
146
+ tensors[i] = t
147
+ else:
148
+ raise RuntimeError(f"The collective op {func} is not supported yet")
149
+
150
+ return wrapper
lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__init__.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ from enum import Enum
3
+ from functools import partial
4
+
5
+ import torch.distributed as dist
6
+
7
+ from . import (
8
+ debugging_hooks as debugging,
9
+ default_hooks as default,
10
+ optimizer_overlap_hooks as optimizer_overlap,
11
+ powerSGD_hook as powerSGD,
12
+ quantization_hooks as quantization,
13
+ )
14
+
15
+
16
+ __all__ = ["DDPCommHookType", "register_ddp_comm_hook"]
17
+
18
+
19
+ def _ddp_comm_hook_wrapper(comm_hook, model, state):
20
+ model.register_comm_hook(state, comm_hook)
21
+
22
+
23
+ def _powerSGD_comm_hook_wrapper(
24
+ comm_hook,
25
+ model,
26
+ state,
27
+ matrix_approximation_rank,
28
+ start_powerSGD_iter=1_000,
29
+ ):
30
+ """
31
+ Wrap PowerSGD communication hook.
32
+
33
+ To be consistent with the wrappers of other DDP comm hooks, the input state only needs to be a process group,
34
+ which will be wrapped up with other state info.
35
+ """
36
+ powerSGD_state = powerSGD.PowerSGDState(
37
+ process_group=state,
38
+ matrix_approximation_rank=matrix_approximation_rank,
39
+ start_powerSGD_iter=start_powerSGD_iter,
40
+ )
41
+ model.register_comm_hook(powerSGD_state, comm_hook)
42
+
43
+
44
+ class DDPCommHookType(Enum):
45
+ """
46
+ Enumerate ``ddp_comm_hooks`` and ``ddp_comm_hook_wrapper`` communucation hook types.
47
+
48
+ DDPCommHookType enumerates the hooks of ``torch.distributed.algorithms.ddp_comm_hooks``
49
+ as names and ``ddp_comm_hook_wrapper`` partials with hook specified. As an example,
50
+ you can register allreduce hook by
51
+ ``DDPCommHookType.ALLREDUCE.value(model=model, state=process_group)``.
52
+ """
53
+
54
+ ALLREDUCE = partial(_ddp_comm_hook_wrapper, comm_hook=default.allreduce_hook)
55
+ FP16_COMPRESS = partial(
56
+ _ddp_comm_hook_wrapper, comm_hook=default.fp16_compress_hook
57
+ )
58
+ BF16_COMPRESS = partial(
59
+ _ddp_comm_hook_wrapper, comm_hook=default.bf16_compress_hook
60
+ )
61
+ QUANTIZE_PER_TENSOR = partial(
62
+ _ddp_comm_hook_wrapper, comm_hook=quantization.quantization_pertensor_hook
63
+ )
64
+ QUANTIZE_PER_CHANNEL = partial(
65
+ _ddp_comm_hook_wrapper, comm_hook=quantization.quantization_perchannel_hook
66
+ )
67
+ POWER_SGD = partial(
68
+ _powerSGD_comm_hook_wrapper,
69
+ comm_hook=powerSGD.powerSGD_hook,
70
+ matrix_approximation_rank=1,
71
+ )
72
+ # Rank-2 PowerSGD can give a higher accuracy than the default rank-1 version,
73
+ # but it runs slower and consumes more memory.
74
+ POWER_SGD_RANK2 = partial(
75
+ _powerSGD_comm_hook_wrapper,
76
+ comm_hook=powerSGD.powerSGD_hook,
77
+ matrix_approximation_rank=2,
78
+ )
79
+ # Batching can lead to a faster training at the cost of accuracy.
80
+ BATCHED_POWER_SGD = partial(
81
+ _powerSGD_comm_hook_wrapper,
82
+ comm_hook=powerSGD.batched_powerSGD_hook,
83
+ matrix_approximation_rank=1,
84
+ )
85
+ BATCHED_POWER_SGD_RANK2 = partial(
86
+ _powerSGD_comm_hook_wrapper,
87
+ comm_hook=powerSGD.batched_powerSGD_hook,
88
+ matrix_approximation_rank=2,
89
+ )
90
+ NOOP = partial(
91
+ _ddp_comm_hook_wrapper,
92
+ comm_hook=debugging.noop_hook,
93
+ )
94
+
95
+
96
+ def register_ddp_comm_hook(comm_hook_type: DDPCommHookType, model, state=None):
97
+ """
98
+ Register ``ddp_comm_hooks`` to DDP model.
99
+
100
+ Registers the hooks of ``torch.distributed.algorithms.ddp_comm_hooks``
101
+ to the DDP model. User can specify the type of hook as an enum
102
+ ``DDPCommHookType`` type using ``comm_hook_type`` input. State input will
103
+ be passed to the model.
104
+ Uses Python comm hook implementations.
105
+
106
+ Example::
107
+ >>> # xdoctest: +SKIP
108
+ >>> register_ddp_comm_hook(DDPCommHookType.FP16_COMPRESS, model, state)
109
+ """
110
+ comm_hook_type.value(model=model, state=state)
lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (3.77 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/ddp_zero_hook.cpython-312.pyc ADDED
Binary file (20.1 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/debugging_hooks.cpython-312.pyc ADDED
Binary file (1.65 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/default_hooks.cpython-312.pyc ADDED
Binary file (10.6 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/mixed_precision_hooks.cpython-312.pyc ADDED
Binary file (4.57 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/optimizer_overlap_hooks.cpython-312.pyc ADDED
Binary file (7.87 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/post_localSGD_hook.cpython-312.pyc ADDED
Binary file (5 kB). View file
 
lib/python3.12/site-packages/torch/distributed/algorithms/ddp_comm_hooks/__pycache__/powerSGD_hook.cpython-312.pyc ADDED
Binary file (35.2 kB). View file