spmd_types 0.2.3__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {spmd_types-0.2.3/spmd_types.egg-info → spmd_types-0.2.4}/PKG-INFO +1 -1
- {spmd_types-0.2.3 → spmd_types-0.2.4}/pyproject.toml +1 -1
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/__init__.py +4 -4
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_backward_hooks.py +4 -16
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_checker/__init__.py +26 -20
- spmd_types-0.2.4/spmd_types/_local_registration.py +50 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/runtime.py +50 -42
- {spmd_types-0.2.3 → spmd_types-0.2.4/spmd_types.egg-info}/PKG-INFO +1 -1
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types.egg-info/SOURCES.txt +1 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/LICENSE +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/README.md +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/setup.cfg +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_collectives.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_dist.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_dtensor.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_dtensor_checker.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_dtype_utils.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_frame.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_local.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_mesh.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_mesh_axis.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_mesh_region.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_raw_dist.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_reinterpret_mesh.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_scalar.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_scalar_sentinel.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_state.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_test_utils.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_testing.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_traceback.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_type_attr.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/_vmap.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/checker.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types/types.py +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types.egg-info/dependency_links.txt +0 -0
- {spmd_types-0.2.3 → spmd_types-0.2.4}/spmd_types.egg-info/top_level.txt +0 -0
|
@@ -7,9 +7,6 @@
|
|
|
7
7
|
# spmd_types package
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
from spmd_types._backward_hooks import ( # noqa: F401
|
|
11
|
-
register_local_backward_hook,
|
|
12
|
-
)
|
|
13
10
|
from spmd_types._collectives import ( # noqa: F401
|
|
14
11
|
all_gather,
|
|
15
12
|
all_reduce,
|
|
@@ -30,6 +27,10 @@ from spmd_types._local import ( # noqa: F401
|
|
|
30
27
|
reinterpret,
|
|
31
28
|
shard,
|
|
32
29
|
)
|
|
30
|
+
from spmd_types._local_registration import ( # noqa: F401
|
|
31
|
+
register_local_autograd_function,
|
|
32
|
+
register_local_backward_hook,
|
|
33
|
+
)
|
|
33
34
|
from spmd_types._mesh import set_current_mesh # noqa: F401
|
|
34
35
|
from spmd_types._mesh_axis import MeshAxis # noqa: F401
|
|
35
36
|
|
|
@@ -64,7 +65,6 @@ from spmd_types.runtime import ( # noqa: F401
|
|
|
64
65
|
no_typecheck,
|
|
65
66
|
register_autograd_function,
|
|
66
67
|
register_decomposition,
|
|
67
|
-
register_local_autograd_function,
|
|
68
68
|
trace,
|
|
69
69
|
)
|
|
70
70
|
|
|
@@ -18,10 +18,12 @@ motivates the exact shape.
|
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
|
-
from collections.abc import Callable
|
|
22
|
-
|
|
23
21
|
import torch
|
|
24
22
|
import torch.utils.hooks as _torch_hooks
|
|
23
|
+
from spmd_types._local_registration import ( # noqa: F401
|
|
24
|
+
_LOCAL_BACKWARD_HOOKS,
|
|
25
|
+
register_local_backward_hook,
|
|
26
|
+
)
|
|
25
27
|
from spmd_types._state import is_type_checking
|
|
26
28
|
from spmd_types.runtime import (
|
|
27
29
|
_set_partition_spec,
|
|
@@ -31,20 +33,6 @@ from spmd_types.runtime import (
|
|
|
31
33
|
from spmd_types.types import SpmdTypeError
|
|
32
34
|
from torch.nn.modules._functions import BackwardHookFunction
|
|
33
35
|
|
|
34
|
-
_LOCAL_BACKWARD_HOOKS: set[Callable] = set()
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def register_local_backward_hook(fn: Callable) -> Callable:
|
|
38
|
-
"""Declare that ``fn`` does not alter SPMD types when it runs in backward.
|
|
39
|
-
|
|
40
|
-
Analogous to :func:`register_local_autograd_function`: the hook's backward
|
|
41
|
-
is treated as local (no collectives, no type-changing effects on grads).
|
|
42
|
-
Side-agnostic: covers both ``register_full_backward_hook`` (post) and
|
|
43
|
-
``register_full_backward_pre_hook`` (pre) use. Usable as a decorator.
|
|
44
|
-
"""
|
|
45
|
-
_LOCAL_BACKWARD_HOOKS.add(fn)
|
|
46
|
-
return fn
|
|
47
|
-
|
|
48
36
|
|
|
49
37
|
def _validate(hooks):
|
|
50
38
|
if not is_type_checking():
|
|
@@ -36,6 +36,10 @@ from spmd_types._collectives import (
|
|
|
36
36
|
reduce_scatter,
|
|
37
37
|
)
|
|
38
38
|
from spmd_types._local import convert, invariant_to_replicate, reinterpret
|
|
39
|
+
from spmd_types._local_registration import ( # noqa: F401
|
|
40
|
+
_LOCAL_AUTOGRAD_FUNCTIONS,
|
|
41
|
+
register_local_autograd_function,
|
|
42
|
+
)
|
|
39
43
|
from spmd_types._mesh_axis import MeshAxis
|
|
40
44
|
from spmd_types._reinterpret_mesh import ( # noqa: F401
|
|
41
45
|
_format_arg_for_context,
|
|
@@ -53,8 +57,9 @@ from spmd_types._state import _current_mode, _set_current_mode, current_mesh
|
|
|
53
57
|
from spmd_types._traceback import _filter_and_reraise
|
|
54
58
|
from spmd_types._type_attr import get_local_type
|
|
55
59
|
from spmd_types.runtime import ( # noqa: F401
|
|
56
|
-
|
|
60
|
+
_get_autograd_spmd_typecheck,
|
|
57
61
|
_PARTITION_SPEC_ATTR,
|
|
62
|
+
_run_autograd_spmd_typecheck,
|
|
58
63
|
_set_local_type,
|
|
59
64
|
_set_partition_spec,
|
|
60
65
|
_TRACE,
|
|
@@ -71,7 +76,6 @@ from spmd_types.runtime import ( # noqa: F401
|
|
|
71
76
|
no_typecheck,
|
|
72
77
|
register_autograd_function,
|
|
73
78
|
register_decomposition,
|
|
74
|
-
register_local_autograd_function,
|
|
75
79
|
trace,
|
|
76
80
|
)
|
|
77
81
|
from spmd_types.types import (
|
|
@@ -2455,10 +2459,9 @@ from spmd_types._state import is_type_checking # noqa: E402, F401
|
|
|
2455
2459
|
# Set of autograd.Function subclasses whose apply is known to be local-only
|
|
2456
2460
|
# (i.e., each output element depends only on the corresponding input elements
|
|
2457
2461
|
# so the standard element-wise type propagation rule is safe).
|
|
2458
|
-
# Set of autograd.Function subclasses registered with
|
|
2459
|
-
#
|
|
2460
|
-
#
|
|
2461
|
-
# on inputs, call .apply() to execute, and assert_type() on the output.
|
|
2462
|
+
# Set of autograd.Function subclasses registered with custom typechecking.
|
|
2463
|
+
# Legacy typecheck_forward wrappers execute the function themselves, while
|
|
2464
|
+
# spmd_typecheck runs after the real apply call managed by the checker.
|
|
2462
2465
|
|
|
2463
2466
|
|
|
2464
2467
|
# The original C++ descriptor for autograd.Function.apply, saved when the
|
|
@@ -2707,18 +2710,22 @@ class _SpmdTypeMode(torch.overrides.TorchFunctionMode):
|
|
|
2707
2710
|
is_global_axis=self._is_global_axis,
|
|
2708
2711
|
)
|
|
2709
2712
|
|
|
2710
|
-
# Typecheck-registered autograd function
|
|
2711
|
-
# INSTEAD of executing func. The mode is popped off the
|
|
2713
|
+
# Typecheck-registered autograd function. The mode is popped off the
|
|
2712
2714
|
# TorchFunctionMode stack during __torch_function__ dispatch (via
|
|
2713
|
-
# _pop_mode_temporarily in torch/overrides.py), so
|
|
2714
|
-
#
|
|
2715
|
-
# this method.
|
|
2715
|
+
# _pop_mode_temporarily in torch/overrides.py), so the real apply
|
|
2716
|
+
# executes normally without re-entering this method.
|
|
2716
2717
|
autograd_cls = _get_autograd_function_class(func)
|
|
2717
|
-
if
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2718
|
+
if autograd_cls is not None:
|
|
2719
|
+
spmd_typecheck = _get_autograd_spmd_typecheck(autograd_cls)
|
|
2720
|
+
if spmd_typecheck is not None:
|
|
2721
|
+
if kwargs:
|
|
2722
|
+
raise TypeError(
|
|
2723
|
+
f"{autograd_cls.__name__}.apply() accepts positional "
|
|
2724
|
+
"arguments only"
|
|
2725
|
+
)
|
|
2726
|
+
return _run_autograd_spmd_typecheck(autograd_cls, func, args)
|
|
2727
|
+
if autograd_cls in _TYPECHECK_AUTOGRAD_FUNCTIONS:
|
|
2728
|
+
return autograd_cls.typecheck_forward(*args, **kwargs)
|
|
2722
2729
|
|
|
2723
2730
|
# DTensor tracks its own placement metadata; the SPMD type checker
|
|
2724
2731
|
# should not interfere with DTensor operations. This covers
|
|
@@ -2908,10 +2915,9 @@ class _SpmdTypeMode(torch.overrides.TorchFunctionMode):
|
|
|
2908
2915
|
f"checking. Use "
|
|
2909
2916
|
f"{register_local_autograd_function.__name__}("
|
|
2910
2917
|
f"{autograd_cls.__name__}) to mark it as safe "
|
|
2911
|
-
f"for type propagation,
|
|
2912
|
-
f"
|
|
2913
|
-
f"
|
|
2914
|
-
f"typecheck_forward."
|
|
2918
|
+
f"for type propagation, or define "
|
|
2919
|
+
f"{autograd_cls.__name__}.spmd_typecheck for a custom "
|
|
2920
|
+
f"typecheck rule."
|
|
2915
2921
|
)
|
|
2916
2922
|
return result
|
|
2917
2923
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# This source code is licensed under the BSD-style license found in the
|
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
|
6
|
+
|
|
7
|
+
"""Lightweight registries for local SPMD type propagation."""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from collections.abc import Callable
|
|
12
|
+
|
|
13
|
+
_LOCAL_AUTOGRAD_FUNCTIONS: set[type] = set()
|
|
14
|
+
_LOCAL_BACKWARD_HOOKS: set[Callable] = set()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def register_local_autograd_function(cls: type) -> type:
|
|
18
|
+
"""Register an autograd.Function subclass as local-only for SPMD type checking.
|
|
19
|
+
|
|
20
|
+
Local-only means the function's forward operates element-wise (or more
|
|
21
|
+
generally, does not rearrange data across the tensor in a way that would
|
|
22
|
+
change its sharding type). It must not perform collectives or cross-device
|
|
23
|
+
communication. For functions that do, use ``register_autograd_function``
|
|
24
|
+
with custom typechecking instead.
|
|
25
|
+
|
|
26
|
+
Registered functions get the standard local type propagation rule when
|
|
27
|
+
type checking is active:
|
|
28
|
+
|
|
29
|
+
- Inputs may freely mix R and V types; the output is R unless any input
|
|
30
|
+
is V, in which case it is V.
|
|
31
|
+
- All-I inputs produce I outputs.
|
|
32
|
+
- R/V and I cannot be mixed.
|
|
33
|
+
- P is forbidden.
|
|
34
|
+
|
|
35
|
+
Unregistered autograd functions that reach the type checker leave their
|
|
36
|
+
outputs untyped or raise in strict mode.
|
|
37
|
+
"""
|
|
38
|
+
_LOCAL_AUTOGRAD_FUNCTIONS.add(cls)
|
|
39
|
+
return cls
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def register_local_backward_hook(fn: Callable) -> Callable:
|
|
43
|
+
"""Declare that ``fn`` does not alter SPMD types when it runs in backward.
|
|
44
|
+
|
|
45
|
+
Analogous to ``register_local_autograd_function``, the hook's backward is
|
|
46
|
+
treated as local with no collectives or type-changing effects on gradients.
|
|
47
|
+
This covers both full backward post-hooks and pre-hooks.
|
|
48
|
+
"""
|
|
49
|
+
_LOCAL_BACKWARD_HOOKS.add(fn)
|
|
50
|
+
return fn
|
|
@@ -25,6 +25,7 @@ need the annotation APIs.
|
|
|
25
25
|
from __future__ import annotations
|
|
26
26
|
|
|
27
27
|
import builtins
|
|
28
|
+
import inspect
|
|
28
29
|
import logging
|
|
29
30
|
import os
|
|
30
31
|
from contextlib import AbstractContextManager, contextmanager
|
|
@@ -32,6 +33,9 @@ from typing import Any, Callable, overload, TypeAlias
|
|
|
32
33
|
|
|
33
34
|
import torch
|
|
34
35
|
from spmd_types._frame import _get_user_frame
|
|
36
|
+
from spmd_types._local_registration import ( # noqa: F401
|
|
37
|
+
register_local_autograd_function,
|
|
38
|
+
)
|
|
35
39
|
from spmd_types._mesh_axis import MeshAxis
|
|
36
40
|
from spmd_types._scalar_sentinel import _Scalar
|
|
37
41
|
from spmd_types._state import _no_typecheck_context, current_mesh, is_type_checking
|
|
@@ -731,43 +735,37 @@ def mutate_type(
|
|
|
731
735
|
# Autograd function registration
|
|
732
736
|
# =============================================================================
|
|
733
737
|
|
|
734
|
-
#
|
|
735
|
-
# _LOCAL_AUTOGRAD_FUNCTIONS: element-wise / local-only functions.
|
|
736
|
-
# _TYPECHECK_AUTOGRAD_FUNCTIONS: functions with custom typecheck_forward.
|
|
737
|
-
_LOCAL_AUTOGRAD_FUNCTIONS: set[type] = set()
|
|
738
|
+
# Autograd.Function subclasses with custom typechecking.
|
|
738
739
|
_TYPECHECK_AUTOGRAD_FUNCTIONS: set[type] = set()
|
|
739
740
|
|
|
740
741
|
|
|
741
|
-
def
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
742
|
+
def _run_autograd_spmd_typecheck(
|
|
743
|
+
cls: type,
|
|
744
|
+
func: Callable[..., object],
|
|
745
|
+
args: tuple[object, ...],
|
|
746
|
+
) -> object:
|
|
747
|
+
signature = inspect.signature(cls.forward)
|
|
748
|
+
has_ctx = cls.setup_context is torch.autograd.Function.setup_context
|
|
749
|
+
bound = signature.bind(*(args if not has_ctx else (None, *args)))
|
|
750
|
+
bound.apply_defaults()
|
|
751
|
+
forward_args = dict(bound.arguments)
|
|
752
|
+
if has_ctx:
|
|
753
|
+
forward_args.pop(next(iter(signature.parameters)))
|
|
752
754
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
- P is forbidden.
|
|
755
|
+
outputs = func(*args)
|
|
756
|
+
hook = cls.spmd_typecheck
|
|
757
|
+
names = tuple(inspect.signature(hook).parameters)[1:]
|
|
758
|
+
hook(outputs, **{name: forward_args[name] for name in names})
|
|
758
759
|
|
|
759
|
-
|
|
760
|
-
their outputs untyped (or raise in strict mode), since the checker
|
|
761
|
-
cannot know whether the function is safe for automatic type propagation.
|
|
760
|
+
return outputs
|
|
762
761
|
|
|
763
|
-
Can be used as a decorator::
|
|
764
762
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
return
|
|
763
|
+
def _get_autograd_spmd_typecheck(cls: type) -> Callable[..., object] | None:
|
|
764
|
+
"""Return and validate an autograd.Function's SPMD typecheck hook."""
|
|
765
|
+
hook = getattr(cls, "spmd_typecheck", None)
|
|
766
|
+
if hook is not None and not callable(hook):
|
|
767
|
+
raise TypeError(f"{cls.__name__}.spmd_typecheck must be callable")
|
|
768
|
+
return hook
|
|
771
769
|
|
|
772
770
|
|
|
773
771
|
def register_autograd_function(cls: type) -> type:
|
|
@@ -777,34 +775,44 @@ def register_autograd_function(cls: type) -> type:
|
|
|
777
775
|
non-trivial type transformations where the default local-only rule
|
|
778
776
|
would produce incorrect output types.
|
|
779
777
|
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
``typecheck_forward`` on ``nn.Module`` subclasses in llama4x::
|
|
778
|
+
A class may define an ``spmd_typecheck`` staticmethod. Its presence is
|
|
779
|
+
detected automatically, so new classes do not need this decorator. The
|
|
780
|
+
hook runs after the function, receives its exact return value as the first
|
|
781
|
+
argument, and names only the forward arguments it needs::
|
|
785
782
|
|
|
786
|
-
@register_autograd_function
|
|
787
783
|
class MyCollectiveOp(torch.autograd.Function):
|
|
788
784
|
@staticmethod
|
|
789
785
|
def forward(ctx, x, y):
|
|
790
786
|
return x + y
|
|
791
787
|
|
|
792
788
|
@staticmethod
|
|
793
|
-
def
|
|
789
|
+
def spmd_typecheck(outputs, *, x):
|
|
794
790
|
assert_type(x, {pg: S(-1)})
|
|
795
|
-
|
|
796
|
-
assert_type(out, {pg: R})
|
|
797
|
-
return out
|
|
791
|
+
assert_type_like(outputs, x, {pg: R})
|
|
798
792
|
|
|
799
793
|
@staticmethod
|
|
800
794
|
def backward(ctx, g):
|
|
801
795
|
return g, g
|
|
796
|
+
|
|
797
|
+
The legacy ``typecheck_forward`` wrapper remains supported for existing
|
|
798
|
+
registrations, but cannot be combined with ``spmd_typecheck``.
|
|
802
799
|
"""
|
|
803
|
-
|
|
800
|
+
legacy_hook = getattr(cls, "typecheck_forward", None)
|
|
801
|
+
spmd_typecheck = _get_autograd_spmd_typecheck(cls)
|
|
802
|
+
|
|
803
|
+
if legacy_hook is not None and spmd_typecheck is not None:
|
|
804
804
|
raise TypeError(
|
|
805
|
-
f"{cls.__name__}
|
|
805
|
+
f"{cls.__name__} cannot define typecheck_forward together with "
|
|
806
|
+
"spmd_typecheck"
|
|
807
|
+
)
|
|
808
|
+
if legacy_hook is None and spmd_typecheck is None:
|
|
809
|
+
raise TypeError(
|
|
810
|
+
f"{cls.__name__} must define typecheck_forward or spmd_typecheck "
|
|
806
811
|
f"when using @register_autograd_function"
|
|
807
812
|
)
|
|
813
|
+
if legacy_hook is not None and not callable(legacy_hook):
|
|
814
|
+
raise TypeError(f"{cls.__name__}.typecheck_forward must be callable")
|
|
815
|
+
|
|
808
816
|
_TYPECHECK_AUTOGRAD_FUNCTIONS.add(cls)
|
|
809
817
|
return cls
|
|
810
818
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|