spmd_types 0.3.0__tar.gz → 0.3.2__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.
Files changed (42) hide show
  1. {spmd_types-0.3.0/spmd_types.egg-info → spmd_types-0.3.2}/PKG-INFO +1 -1
  2. spmd_types-0.3.2/pyproject.toml +110 -0
  3. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/__init__.py +2 -0
  4. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_checker/__init__.py +56 -8
  5. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_collectives.py +178 -25
  6. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_dtype_utils.py +22 -4
  7. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_local.py +41 -3
  8. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_state.py +18 -1
  9. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/rules.py +60 -6
  10. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/runtime.py +186 -44
  11. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/types.py +15 -2
  12. {spmd_types-0.3.0 → spmd_types-0.3.2/spmd_types.egg-info}/PKG-INFO +1 -1
  13. spmd_types-0.3.0/pyproject.toml +0 -69
  14. {spmd_types-0.3.0 → spmd_types-0.3.2}/LICENSE +0 -0
  15. {spmd_types-0.3.0 → spmd_types-0.3.2}/README.md +0 -0
  16. {spmd_types-0.3.0 → spmd_types-0.3.2}/setup.cfg +0 -0
  17. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_backward_hooks.py +0 -0
  18. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_coverage.py +0 -0
  19. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_dist.py +0 -0
  20. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_dtensor.py +0 -0
  21. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_dtensor_checker.py +0 -0
  22. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_frame.py +0 -0
  23. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_local_registration.py +0 -0
  24. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_mesh.py +0 -0
  25. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_mesh_axis.py +0 -0
  26. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_mesh_region.py +0 -0
  27. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_raw_dist.py +0 -0
  28. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_reinterpret_mesh.py +0 -0
  29. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_scalar.py +0 -0
  30. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_scalar_sentinel.py +0 -0
  31. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_test_utils.py +0 -0
  32. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_testing.py +0 -0
  33. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_traceback.py +0 -0
  34. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_type_attr.py +0 -0
  35. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/_vmap.py +0 -0
  36. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/checker.py +0 -0
  37. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/py.typed +0 -0
  38. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types/rulecheck.py +0 -0
  39. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types.egg-info/SOURCES.txt +0 -0
  40. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types.egg-info/dependency_links.txt +0 -0
  41. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types.egg-info/requires.txt +0 -0
  42. {spmd_types-0.3.0 → spmd_types-0.3.2}/spmd_types.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spmd_types
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: A type system for distributed (SPMD) tensor computations in PyTorch
5
5
  Author: Meta Platforms, Inc.
6
6
  License: BSD 3-Clause License
@@ -0,0 +1,110 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "spmd_types"
7
+ version = "0.3.2"
8
+ description = "A type system for distributed (SPMD) tensor computations in PyTorch"
9
+ readme = "README.md"
10
+ license = {file = "LICENSE"}
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ {name = "Meta Platforms, Inc."},
14
+ ]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "Intended Audience :: Science/Research",
19
+ "License :: OSI Approved :: BSD License",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
25
+ ]
26
+ dependencies = [
27
+ ]
28
+
29
+ [project.optional-dependencies]
30
+ docs = [
31
+ "myst-parser==2.0.0",
32
+ "pytorch-sphinx-theme2==0.4.13",
33
+ "sphinx==7.2.6",
34
+ ]
35
+
36
+ [project.urls]
37
+ Homepage = "https://github.com/meta-pytorch/spmd_types"
38
+ Documentation = "https://meta-pytorch.org/spmd_types/"
39
+ Repository = "https://github.com/meta-pytorch/spmd_types"
40
+ Issues = "https://github.com/meta-pytorch/spmd_types/issues"
41
+
42
+ [tool.setuptools.packages.find]
43
+ include = ["spmd_types*"]
44
+
45
+ [tool.setuptools.package-data]
46
+ spmd_types = ["py.typed"]
47
+
48
+
49
+ [tool.ruff]
50
+ line-length = 88
51
+ target-version = "py310"
52
+
53
+ [tool.ruff.lint]
54
+ select = ["E4", "E7", "E9", "F"]
55
+
56
+ [tool.ruff.format]
57
+ exclude = ["*.md"]
58
+ quote-style = "double"
59
+
60
+ [tool.pytest.ini_options]
61
+ testpaths = ["tests"]
62
+ python_files = ["*_test.py"]
63
+
64
+ # ops imports spmd_types from most of its interfaces and farm from its
65
+ # gradient code, so an unscoped import graph selects their suites, GPU plans
66
+ # included, for every change here. Import-graph selection stays inside this
67
+ # tree; the tests below opt back in.
68
+ [tool.test-selector.graph-dependents]
69
+ "**" = ["**"]
70
+
71
+ [tool.test-selector.extra-deps]
72
+
73
+ # The farm tests that import spmd_types directly.
74
+ "**" = [
75
+ "../farm/farm/model/tests/test_input_side_fsdp_order.py",
76
+ "../farm/farm/optimize/tests/test_grad_clipping_shared_tensor.py",
77
+ "../farm/farm/optimize/tests/test_replication_metadata.py",
78
+ ]
79
+
80
+ # BEGIN GENERATED buck-manual-deps -- do not edit by hand
81
+ # Regenerate: export_buck_manual_deps.py
82
+ "spmd_types/__init__.py" = [
83
+ "../../llama4x/projects/experimental/rtai_avatar/pumpkin/sythetic_data/t2av/conversation_audio_artifacts.py",
84
+ "../../llama4x/projects/experimental/rtai_avatar/pumpkin/sythetic_data/t2av/conversation_audio_artifacts_v22.py",
85
+ "../../llama4x/projects/experimental/rtai_avatar/pumpkin/sythetic_data/t2av/conversation_audio_encoder_r6_i11_v22.py",
86
+ "../../llama4x/projects/experimental/rtai_avatar/pumpkin/sythetic_data/t2av/conversation_conditioner_calibration_v21.py",
87
+ "../../llama4x/projects/experimental/rtai_avatar/pumpkin/sythetic_data/t2av/conversation_ctts_pipeline_r6_i11_v22.py",
88
+ "../../llama4x/projects/experimental/rtai_avatar/pumpkin/sythetic_data/t2av/conversation_landscape_recipe_r5_v21.py",
89
+ "../../llama4x/projects/experimental/rtai_avatar/pumpkin/sythetic_data/t2av/conversation_landscape_sampling_r5.py",
90
+ "../../llama4x/projects/experimental/rtai_avatar/pumpkin/sythetic_data/t2av/conversation_landscape_sampling_r6_i11_v22.py",
91
+ "../../llama4x/projects/experimental/rtai_avatar/pumpkin/sythetic_data/t2av/conversation_landscape_sampling_r6_i11_v22_gb300.py",
92
+ "../../llama4x/projects/experimental/rtai_avatar/pumpkin/sythetic_data/t2av/conversation_landscape_style_r5_v21.py",
93
+ "../ops/interfaces/attn/triton_attention_fp32.py",
94
+ "../ops/interfaces/gemm/gemm.py",
95
+ "../rl/projects/rvg/data/data_pipeline/kimi_labeling.py",
96
+ ]
97
+ # END GENERATED buck-manual-deps
98
+
99
+ [dependency-groups]
100
+ # Build backend of this package, locked: in the mslsrc/tbd_training export the
101
+ # members build against the venv (the root's `no-build-isolation-package`), so
102
+ # the backend has to be in a default group for `uv sync` to install it first.
103
+ build = ["setuptools", "wheel"]
104
+ # What the tests import beyond the package itself; the export runs them in
105
+ # this project's uv env.
106
+ # @tbd-training-enable: dev = ["expecttest", "pytest", "torch"]
107
+
108
+ [tool.uv]
109
+ default-groups = ["build"] # @tbd-training-disable
110
+ # @tbd-training-enable: default-groups = ["build", "dev"]
@@ -62,10 +62,12 @@ from spmd_types.runtime import ( # noqa: F401
62
62
  Infer,
63
63
  local,
64
64
  local_map,
65
+ merge_types,
65
66
  mutate_type,
66
67
  no_typecheck,
67
68
  register_autograd_function,
68
69
  register_decomposition,
70
+ register_no_typecheck,
69
71
  reinterpret_no_grad,
70
72
  trace,
71
73
  )
@@ -1885,6 +1885,12 @@ def dtensor_placement_to_spmd_type(
1885
1885
  if isinstance(placement, dtensor_type.Replicate):
1886
1886
  return R
1887
1887
  if isinstance(placement, dtensor_type.Partial):
1888
+ if type(placement) is not dtensor_type.Partial:
1889
+ raise DTensorPropagationError(
1890
+ f"Only sum-Partial is supported, got {placement!r}; for a p-norm "
1891
+ f"over a sharded dim, all_reduce torch.sum(x.abs() ** p) and take "
1892
+ f"the p-th root"
1893
+ )
1888
1894
  if placement.reduce_op != "sum":
1889
1895
  raise ValueError(
1890
1896
  f"Only sum-Partial is supported, got reduce_op={placement.reduce_op!r}"
@@ -2474,22 +2480,33 @@ def _check_backward_loss_type(args: tuple, kwargs: dict) -> None:
2474
2480
  # collectives) are caught rather than silently bypassing the checker.
2475
2481
  #
2476
2482
  # Note: property accesses like .shape/.ndim are handled by the __get__
2477
- # check in __torch_function__, and .stride() is in PyTorch's
2478
- # get_ignored_functions() so it never reaches __torch_function__ at all.
2483
+ # check in __torch_function__. Methods must be listed here even when PyTorch's
2484
+ # get_ignored_functions() names them: .stride() is listed there but still
2485
+ # reaches torch function modes.
2479
2486
  _PASSTHROUGH = {
2480
2487
  # Autograd bookkeeping
2481
2488
  torch.Tensor.requires_grad_,
2482
2489
  torch.Tensor.retain_grad,
2483
2490
  # Metadata queries (return non-tensor values)
2491
+ torch.Tensor.__len__,
2492
+ torch.Tensor._is_view,
2484
2493
  torch.Tensor.dim,
2494
+ torch.Tensor.dim_order,
2485
2495
  torch.Tensor.element_size,
2486
2496
  torch.Tensor.get_device,
2487
2497
  torch.Tensor.is_complex,
2488
2498
  torch.Tensor.is_contiguous,
2489
2499
  torch.Tensor.is_floating_point,
2500
+ torch.Tensor.is_inference,
2501
+ torch.Tensor.is_pinned,
2502
+ torch.Tensor.is_shared,
2503
+ torch.Tensor.is_signed,
2504
+ torch.Tensor.ndimension,
2490
2505
  torch.Tensor.nelement,
2491
2506
  torch.Tensor.numel,
2492
2507
  torch.Tensor.size,
2508
+ torch.Tensor.storage_offset,
2509
+ torch.Tensor.stride,
2493
2510
  torch.Tensor.untyped_storage,
2494
2511
  torch.numel,
2495
2512
  }
@@ -2698,8 +2715,9 @@ class _SpmdTypeMode(torch.overrides.TorchFunctionMode):
2698
2715
 
2699
2716
  def __torch_function__(self, func, types, args=(), kwargs=None): # noqa: C901
2700
2717
  kwargs = kwargs or {}
2701
- # Paused via no_typecheck(): run without type checking.
2702
- if self._disabled:
2718
+ # Paused via no_typecheck() or register_no_typecheck(): run without
2719
+ # type checking.
2720
+ if self._disabled or _state._in_no_typecheck_frame():
2703
2721
  return func(*args, **kwargs)
2704
2722
 
2705
2723
  # Property access (e.g. .grad, .data, .shape): pass through unless registered
@@ -2854,11 +2872,19 @@ class _SpmdTypeMode(torch.overrides.TorchFunctionMode):
2854
2872
  # V when src=P, implicitly reinterpreting V as P. The runtime
2855
2873
  # in _collectives.py already handles this conversion.
2856
2874
  local_type = get_local_type(x)
2875
+ input_spec = get_partition_spec(x)
2857
2876
 
2858
2877
  # Resolve axis to a list of matching axes on the tensor.
2859
2878
  # Direct match: [axis]. Flattened decomposition: [sub1, sub2, ...].
2860
2879
  resolved_axes = _resolve_collective_axes(axis, local_type)
2861
- collective_axes = resolved_axes or [axis]
2880
+ if resolved_axes is None:
2881
+ # An axis already on x names x's own mesh presentation; only
2882
+ # otherwise retag x onto the current mesh.
2883
+ (local_type,), (input_spec,) = _auto_reinterpret_cross_mesh(
2884
+ [local_type], [input_spec]
2885
+ )
2886
+ resolved_axes = _resolve_collective_axes(axis, local_type)
2887
+ collective_axes = resolved_axes or []
2862
2888
  global_collective_axes = [
2863
2889
  ax for ax in collective_axes if self._is_global_axis(ax)
2864
2890
  ]
@@ -2880,11 +2906,16 @@ class _SpmdTypeMode(torch.overrides.TorchFunctionMode):
2880
2906
 
2881
2907
  if resolved_axes is not None:
2882
2908
  # Validate input types on all resolved axes
2909
+ no_grad = not (torch.is_grad_enabled() and x.requires_grad)
2883
2910
  for ax in resolved_axes:
2884
2911
  input_type = local_type[ax]
2885
2912
  if local_src is not None and input_type != local_src:
2886
- # Allow V -> P implicit cast for reductions
2887
- if not (local_src is P and input_type is V):
2913
+ # Allow V -> P implicit cast for reductions, and R <-> I
2914
+ # when x cannot receive a gradient (they differ only in
2915
+ # backward).
2916
+ if not (local_src is P and input_type is V) and not (
2917
+ no_grad and {input_type, local_src} == {R, I}
2918
+ ):
2888
2919
  raise SpmdTypeError(
2889
2920
  f"{func.__name__}: expected input type {local_src} on axis "
2890
2921
  f"{format_axis(ax)}, got {input_type}"
@@ -2908,7 +2939,6 @@ class _SpmdTypeMode(torch.overrides.TorchFunctionMode):
2908
2939
  _set_local_type(result, output_type)
2909
2940
 
2910
2941
  if global_collective_axes:
2911
- input_spec = get_partition_spec(x)
2912
2942
  # Find S(dim) for this axis in the input spec, validating
2913
2943
  # it is innermost in its multi-axis group.
2914
2944
  input_shard = None
@@ -2961,6 +2991,24 @@ class _SpmdTypeMode(torch.overrides.TorchFunctionMode):
2961
2991
  result.ndim,
2962
2992
  )
2963
2993
  _set_partition_spec(result, new_output_spec)
2994
+ elif resolved_axes is None and not self._local:
2995
+ # all_to_all(V, V) unbinds split_dim and stacks on concat_dim.
2996
+ moves_dims = result.ndim != x.ndim or (
2997
+ src is V
2998
+ and dst is V
2999
+ and (kwargs.get("split_dim") or 0) != (kwargs.get("concat_dim") or 0)
3000
+ )
3001
+ if not moves_dims:
3002
+ _set_partition_spec(result, input_spec)
3003
+ elif input_spec is not None and self._global_axes_for(
3004
+ input_spec.axes_with_partition_spec()
3005
+ ):
3006
+ raise SpmdTypeError(
3007
+ f"{func.__name__}: stack semantics on axis "
3008
+ f"{format_axis(axis)} move tensor dims, so the "
3009
+ f"input PartitionSpec no longer lines up with the "
3010
+ f"result. Use S(i) instead of V."
3011
+ )
2964
3012
 
2965
3013
  if _TRACE:
2966
3014
  _trace_op(