haliax 1.4.dev413__tar.gz → 1.4.dev419__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.
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.agents/projects/api_parity.md +12 -12
- {haliax-1.4.dev413 → haliax-1.4.dev419}/AUTHORS.md +1 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/PKG-INFO +2 -1
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/api.md +15 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/pyproject.toml +1 -2
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/__about__.py +1 -1
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/__init__.py +51 -12
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/_src/state_dict.py +1 -1
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/core.py +24 -4
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/fft.py +4 -1
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/__init__.py +18 -7
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/linear.py +1 -1
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/ops.py +2 -4
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/partitioning.py +101 -62
- haliax-1.4.dev419/src/haliax/poly.py +304 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/core_test.py +46 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_bitwise_ops.py +4 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_fft.py +5 -3
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_moe_linear.py +3 -2
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_nan_reductions.py +4 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_nn.py +18 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_partitioning.py +15 -27
- haliax-1.4.dev419/tests/test_poly_ops.py +134 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_utils.py +5 -2
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_visualize_sharding.py +5 -2
- haliax-1.4.dev419/uv.lock +1951 -0
- haliax-1.4.dev413/uv.lock +0 -1711
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.coveragerc +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.flake8 +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.github/workflows/publish_dev.yaml +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.github/workflows/run_pre_commit.yaml +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.github/workflows/run_quick_levanter_tests.yaml +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.github/workflows/run_tests.yaml +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.gitignore +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.playbooks/add-types.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.playbooks/wrap-non-named.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.pre-commit-config.yaml +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/.readthedocs.yaml +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/AGENTS.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/CONTRIBUTING.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/CONTRIBUTORS.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/LICENSE +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/README.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/broadcasting.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/cheatsheet.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/css/material.css +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/css/mkdocstrings.css +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/faq.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/figures/data_parallel_mesh.png +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/figures/data_parallel_mesh_replicated.png +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/figures/device_mesh_1d.png +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/figures/device_mesh_1d_zero.png +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/figures/device_mesh_2d.png +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/figures/device_mesh_2d_batch_partitioned.png +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/figures/device_mesh_2d_data_replicated.png +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/figures/device_mesh_2d_data_replicated_mlp_partitioned.png +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/figures/device_mesh_2d_intermediate_fully_partitioned.png +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/figures/device_mesh_2d_zero.png +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/fp8.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/index.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/indexing.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/matmul.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/nn.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/partitioning.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/primer.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/rearrange.ipynb +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/rearrange.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/requirements.txt +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/scan.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/state-dict.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/tutorial.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/typing.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/docs/vmap.md +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/etc/license_header.txt +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/mkdocs.yml +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/_src/__init__.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/_src/compile_utils.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/_src/dot.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/_src/einsum.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/_src/fp8.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/_src/parsing.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/_src/rearrange.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/_src/scan.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/_src/util.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/axis.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/debug.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/field.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/haxtyping.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/hof.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/jax_utils.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/activations.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/attention.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/conv.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/dropout.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/embedding.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/loss.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/mlp.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/normalization.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/pool.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/nn/scan.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/quantization.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/random.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/specialized_fns.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/state_dict.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/tree_util.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/types.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/util.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/src/haliax/wrap.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_attention.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_axis.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_conv.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_debug.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_dot.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_dtype_typing.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_einsum.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_field.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_fp8.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_hof.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_int8.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_namedarray_typing.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_ops.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_parsing.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_pool.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_random.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_rearrange.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_scan.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_scatter_gather.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_specialized_fns.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_state_dict.py +0 -0
- {haliax-1.4.dev413 → haliax-1.4.dev419}/tests/test_tree_util.py +0 -0
|
@@ -115,15 +115,15 @@ APIs that don't translate well to named tensors are intentionally omitted here.
|
|
|
115
115
|
- [ ] `permute_dims`
|
|
116
116
|
- [ ] `piecewise`
|
|
117
117
|
- [ ] `place`
|
|
118
|
-
- [
|
|
119
|
-
- [
|
|
120
|
-
- [
|
|
121
|
-
- [
|
|
122
|
-
- [
|
|
123
|
-
- [
|
|
124
|
-
- [
|
|
125
|
-
- [
|
|
126
|
-
- [
|
|
118
|
+
- [x] `poly`
|
|
119
|
+
- [x] `polyadd`
|
|
120
|
+
- [x] `polyder`
|
|
121
|
+
- [x] `polydiv`
|
|
122
|
+
- [x] `polyfit`
|
|
123
|
+
- [x] `polyint`
|
|
124
|
+
- [x] `polymul`
|
|
125
|
+
- [x] `polysub`
|
|
126
|
+
- [x] `polyval`
|
|
127
127
|
- [ ] `pow`
|
|
128
128
|
- [ ] `promote_types`
|
|
129
129
|
- [ ] `put`
|
|
@@ -134,7 +134,7 @@ APIs that don't translate well to named tensors are intentionally omitted here.
|
|
|
134
134
|
- [ ] `resize`
|
|
135
135
|
- [ ] `result_type`
|
|
136
136
|
- [ ] `rollaxis`
|
|
137
|
-
- [
|
|
137
|
+
- [x] `roots`
|
|
138
138
|
- [ ] `rot90`
|
|
139
139
|
- [ ] `select`
|
|
140
140
|
- [ ] `setdiff1d`
|
|
@@ -148,7 +148,7 @@ APIs that don't translate well to named tensors are intentionally omitted here.
|
|
|
148
148
|
- [ ] `tri`
|
|
149
149
|
- [ ] `tril_indices`
|
|
150
150
|
- [ ] `tril_indices_from`
|
|
151
|
-
- [
|
|
151
|
+
- [x] `trim_zeros`
|
|
152
152
|
- [ ] `triu_indices`
|
|
153
153
|
- [ ] `triu_indices_from`
|
|
154
154
|
- [ ] `union1d`
|
|
@@ -156,7 +156,7 @@ APIs that don't translate well to named tensors are intentionally omitted here.
|
|
|
156
156
|
- [ ] `unravel_index`
|
|
157
157
|
- [ ] `unstack`
|
|
158
158
|
- [ ] `unwrap`
|
|
159
|
-
- [
|
|
159
|
+
- [x] `vander`
|
|
160
160
|
- [ ] `vsplit`
|
|
161
161
|
- [ ] `vstack`
|
|
162
162
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: haliax
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.dev419
|
|
4
4
|
Summary: Named Tensors for Legible Deep Learning in JAX
|
|
5
5
|
Project-URL: Homepage, https://github.com/stanford-crfm/haliax
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/stanford-crfm/haliax/issues/
|
|
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
17
17
|
Requires-Python: >=3.10
|
|
18
18
|
Requires-Dist: aqtp>=0.8.2
|
|
19
19
|
Requires-Dist: equinox>=0.10.6
|
|
20
|
+
Requires-Dist: jax>=0.6.2
|
|
20
21
|
Requires-Dist: jaxtyping>=0.2.20
|
|
21
22
|
Requires-Dist: jmp>=0.0.4
|
|
22
23
|
Requires-Dist: safetensors>=0.4.3
|
|
@@ -340,6 +340,21 @@ These are all more or less directly from JAX's NumPy API.
|
|
|
340
340
|
::: haliax.subtract
|
|
341
341
|
::: haliax.true_divide
|
|
342
342
|
|
|
343
|
+
### Polynomial Operations
|
|
344
|
+
|
|
345
|
+
::: haliax.poly
|
|
346
|
+
::: haliax.polyadd
|
|
347
|
+
::: haliax.polysub
|
|
348
|
+
::: haliax.polymul
|
|
349
|
+
::: haliax.polydiv
|
|
350
|
+
::: haliax.polyint
|
|
351
|
+
::: haliax.polyder
|
|
352
|
+
::: haliax.polyval
|
|
353
|
+
::: haliax.polyfit
|
|
354
|
+
::: haliax.roots
|
|
355
|
+
::: haliax.trim_zeros
|
|
356
|
+
::: haliax.vander
|
|
357
|
+
|
|
343
358
|
### Other Operations
|
|
344
359
|
|
|
345
360
|
::: haliax.bincount
|
|
@@ -21,8 +21,7 @@ classifiers = [
|
|
|
21
21
|
"Intended Audience :: Science/Research",
|
|
22
22
|
]
|
|
23
23
|
dependencies = [
|
|
24
|
-
|
|
25
|
-
# jax = {version = ">=0.4.19,<0.5.0"}
|
|
24
|
+
"jax >= 0.6.2",
|
|
26
25
|
"equinox>=0.10.6",
|
|
27
26
|
"jaxtyping>=0.2.20",
|
|
28
27
|
"jmp>=0.0.4",
|
|
@@ -8,11 +8,8 @@ from typing import Optional, Sequence
|
|
|
8
8
|
|
|
9
9
|
import jax
|
|
10
10
|
import jax.numpy as jnp
|
|
11
|
+
from jax.typing import DTypeLike
|
|
11
12
|
|
|
12
|
-
try:
|
|
13
|
-
from jax.typing import DTypeLike
|
|
14
|
-
except ImportError:
|
|
15
|
-
from jax._src.typing import DTypeLike
|
|
16
13
|
|
|
17
14
|
import haliax.debug as debug
|
|
18
15
|
import haliax.nn as nn
|
|
@@ -96,6 +93,22 @@ from .ops import (
|
|
|
96
93
|
bincount,
|
|
97
94
|
where,
|
|
98
95
|
)
|
|
96
|
+
|
|
97
|
+
from .poly import (
|
|
98
|
+
poly,
|
|
99
|
+
polyadd,
|
|
100
|
+
polysub,
|
|
101
|
+
polymul,
|
|
102
|
+
polydiv,
|
|
103
|
+
polyint,
|
|
104
|
+
polyder,
|
|
105
|
+
polyval,
|
|
106
|
+
polyfit,
|
|
107
|
+
roots,
|
|
108
|
+
trim_zeros,
|
|
109
|
+
vander,
|
|
110
|
+
)
|
|
111
|
+
|
|
99
112
|
from .fft import (
|
|
100
113
|
fft,
|
|
101
114
|
fftfreq,
|
|
@@ -108,7 +121,7 @@ from .fft import (
|
|
|
108
121
|
rfft,
|
|
109
122
|
rfftfreq,
|
|
110
123
|
)
|
|
111
|
-
from .partitioning import auto_sharded, axis_mapping, fsdp, named_jit, shard, shard_with_axis_mapping
|
|
124
|
+
from .partitioning import auto_sharded, axis_mapping, fsdp, named_jit, set_mesh, shard, shard_with_axis_mapping
|
|
112
125
|
from .specialized_fns import top_k
|
|
113
126
|
from .types import Scalar
|
|
114
127
|
from .util import is_named_array
|
|
@@ -715,7 +728,9 @@ def nanmean(
|
|
|
715
728
|
where: Optional[NamedArray] = None,
|
|
716
729
|
dtype: Optional[DTypeLike] = None,
|
|
717
730
|
) -> NamedArray:
|
|
718
|
-
return wrap_reduction_call(
|
|
731
|
+
return wrap_reduction_call(
|
|
732
|
+
jnp.nanmean, array, axis, where, single_axis_only=False, supports_where=True, dtype=dtype
|
|
733
|
+
)
|
|
719
734
|
|
|
720
735
|
|
|
721
736
|
def nanmin(
|
|
@@ -734,7 +749,9 @@ def nanprod(
|
|
|
734
749
|
where: Optional[NamedArray] = None,
|
|
735
750
|
dtype: Optional[DTypeLike] = None,
|
|
736
751
|
) -> NamedArray:
|
|
737
|
-
return wrap_reduction_call(
|
|
752
|
+
return wrap_reduction_call(
|
|
753
|
+
jnp.nanprod, array, axis, where, single_axis_only=False, supports_where=True, dtype=dtype
|
|
754
|
+
)
|
|
738
755
|
|
|
739
756
|
|
|
740
757
|
def nanstd(
|
|
@@ -745,7 +762,9 @@ def nanstd(
|
|
|
745
762
|
ddof: int = 0,
|
|
746
763
|
dtype: Optional[DTypeLike] = None,
|
|
747
764
|
) -> NamedArray:
|
|
748
|
-
return wrap_reduction_call(
|
|
765
|
+
return wrap_reduction_call(
|
|
766
|
+
jnp.nanstd, array, axis, where, single_axis_only=False, supports_where=True, dtype=dtype, ddof=ddof
|
|
767
|
+
)
|
|
749
768
|
|
|
750
769
|
|
|
751
770
|
def nansum(
|
|
@@ -755,7 +774,9 @@ def nansum(
|
|
|
755
774
|
where: Optional[NamedArray] = None,
|
|
756
775
|
dtype: Optional[DTypeLike] = None,
|
|
757
776
|
) -> NamedArray:
|
|
758
|
-
return wrap_reduction_call(
|
|
777
|
+
return wrap_reduction_call(
|
|
778
|
+
jnp.nansum, array, axis, where, single_axis_only=False, supports_where=True, dtype=dtype
|
|
779
|
+
)
|
|
759
780
|
|
|
760
781
|
|
|
761
782
|
def nanvar(
|
|
@@ -766,7 +787,9 @@ def nanvar(
|
|
|
766
787
|
ddof: int = 0,
|
|
767
788
|
dtype: Optional[DTypeLike] = None,
|
|
768
789
|
) -> NamedArray:
|
|
769
|
-
return wrap_reduction_call(
|
|
790
|
+
return wrap_reduction_call(
|
|
791
|
+
jnp.nanvar, array, axis, where, single_axis_only=False, supports_where=True, dtype=dtype, ddof=ddof
|
|
792
|
+
)
|
|
770
793
|
|
|
771
794
|
|
|
772
795
|
# "Normalization" functions that use an axis but don't change the shape
|
|
@@ -807,14 +830,17 @@ def sort(a: NamedArray, axis: AxisSelector) -> NamedArray:
|
|
|
807
830
|
return wrap_axiswise_call(jnp.sort, a, axis, single_axis_only=True)
|
|
808
831
|
|
|
809
832
|
|
|
810
|
-
def argsort(a: NamedArray, axis: AxisSelector) -> NamedArray:
|
|
833
|
+
def argsort(a: NamedArray, axis: AxisSelector | None, *, stable: bool = False) -> NamedArray:
|
|
811
834
|
"""
|
|
812
835
|
Named version of [jax.numpy.argsort](https://jax.readthedocs.io/en/latest/_autosummary/jax.numpy.argsort.html).
|
|
813
836
|
|
|
814
837
|
If `axis` is None, the returned array will be a 1D array of indices that would sort the flattened array,
|
|
815
838
|
identical to `jax.numpy.argsort(a.array)`.
|
|
839
|
+
|
|
840
|
+
Args:
|
|
841
|
+
stable: If ``True``, ensures that the indices of equal elements preserve their relative order.
|
|
816
842
|
"""
|
|
817
|
-
return wrap_axiswise_call(jnp.argsort, a, axis, single_axis_only=True)
|
|
843
|
+
return wrap_axiswise_call(jnp.argsort, a, axis, single_axis_only=True, stable=stable)
|
|
818
844
|
|
|
819
845
|
|
|
820
846
|
# elemwise binary ops
|
|
@@ -1226,6 +1252,18 @@ __all__ = [
|
|
|
1226
1252
|
"clip",
|
|
1227
1253
|
"tril",
|
|
1228
1254
|
"triu",
|
|
1255
|
+
"poly",
|
|
1256
|
+
"polyadd",
|
|
1257
|
+
"polysub",
|
|
1258
|
+
"polymul",
|
|
1259
|
+
"polydiv",
|
|
1260
|
+
"polyint",
|
|
1261
|
+
"polyder",
|
|
1262
|
+
"polyval",
|
|
1263
|
+
"polyfit",
|
|
1264
|
+
"roots",
|
|
1265
|
+
"trim_zeros",
|
|
1266
|
+
"vander",
|
|
1229
1267
|
"fft",
|
|
1230
1268
|
"ifft",
|
|
1231
1269
|
"hfft",
|
|
@@ -1311,4 +1349,5 @@ __all__ = [
|
|
|
1311
1349
|
"NamedArrayAxes",
|
|
1312
1350
|
"NamedArrayAxesSpec",
|
|
1313
1351
|
"Named",
|
|
1352
|
+
"set_mesh",
|
|
1314
1353
|
]
|
|
@@ -197,7 +197,7 @@ def from_state_dict(tree: T, state_dict: StateDict, prefix: Optional[str] = None
|
|
|
197
197
|
array = state_dict[prefix]
|
|
198
198
|
|
|
199
199
|
if isinstance(array, np.ndarray):
|
|
200
|
-
mesh =
|
|
200
|
+
mesh = jax.sharding.get_abstract_mesh()
|
|
201
201
|
# TODO: modernize this
|
|
202
202
|
if jax.device_count() > 1: # this happens with the default mesh
|
|
203
203
|
pspec = partitioning.pspec_for_axis(tree.axes)
|
|
@@ -623,8 +623,8 @@ class NamedArray(metaclass=NamedArrayMeta):
|
|
|
623
623
|
def argmin(self, axis: Optional[AxisSelector]) -> "NamedArray": # pragma: no cover
|
|
624
624
|
return haliax.argmin(self, axis=axis)
|
|
625
625
|
|
|
626
|
-
def argsort(self, axis: AxisSelector) -> "NamedArray": # pragma: no cover
|
|
627
|
-
return haliax.argsort(self, axis=axis)
|
|
626
|
+
def argsort(self, axis: AxisSelector | None, *, stable: bool = False) -> "NamedArray": # pragma: no cover
|
|
627
|
+
return haliax.argsort(self, axis=axis, stable=stable)
|
|
628
628
|
|
|
629
629
|
def astype(self, dtype) -> "NamedArray": # pragma: no cover
|
|
630
630
|
return NamedArray(self.array.astype(dtype), self.axes)
|
|
@@ -1183,6 +1183,26 @@ def index(array: NamedArray, slices: Mapping[AxisSelector, NamedIndex]) -> Named
|
|
|
1183
1183
|
def _compute_new_axes_and_slices_for_index(
|
|
1184
1184
|
array, slices
|
|
1185
1185
|
) -> tuple[AxisSpec, list[py_slice | dslice | jnp.ndarray | int | list[int]]]:
|
|
1186
|
+
def _is_integer_like_scalar_index(value: Any) -> bool:
|
|
1187
|
+
if isinstance(value, (int, np.integer)):
|
|
1188
|
+
return True
|
|
1189
|
+
if not is_jax_array_like(value):
|
|
1190
|
+
return False
|
|
1191
|
+
shape = getattr(value, "shape", None)
|
|
1192
|
+
if shape != ():
|
|
1193
|
+
return False
|
|
1194
|
+
dtype = getattr(value, "dtype", None)
|
|
1195
|
+
if dtype is None:
|
|
1196
|
+
return False
|
|
1197
|
+
return jnp.issubdtype(dtype, jnp.integer)
|
|
1198
|
+
|
|
1199
|
+
def _coerce_integer_like_index(value: Any):
|
|
1200
|
+
if isinstance(value, np.integer):
|
|
1201
|
+
return int(value)
|
|
1202
|
+
if type(value) is np.ndarray and value.shape == () and jnp.issubdtype(value.dtype, jnp.integer):
|
|
1203
|
+
return int(value.item())
|
|
1204
|
+
return value
|
|
1205
|
+
|
|
1186
1206
|
ordered_slices: list = [py_slice(None, None, None)] * len(array.axes) # type: ignore
|
|
1187
1207
|
kept_axes = [True] * len(array.axes)
|
|
1188
1208
|
array_slice_indices = []
|
|
@@ -1205,8 +1225,8 @@ def _compute_new_axes_and_slices_for_index(
|
|
|
1205
1225
|
kept_axes[axis_index] = False
|
|
1206
1226
|
array_slice_indices.append(axis_index)
|
|
1207
1227
|
index_axis_names.add(orig_axis.name)
|
|
1208
|
-
elif
|
|
1209
|
-
ordered_slices[axis_index] = slice_
|
|
1228
|
+
elif _is_integer_like_scalar_index(slice_):
|
|
1229
|
+
ordered_slices[axis_index] = _coerce_integer_like_index(slice_)
|
|
1210
1230
|
kept_axes[axis_index] = False
|
|
1211
1231
|
elif isinstance(slice_, NamedArray):
|
|
1212
1232
|
ordered_slices[axis_index] = slice_
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# Copyright 2025 The Levanter Authors
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
1
5
|
"""Named wrappers around :mod:`jax.numpy.fft`.
|
|
2
6
|
|
|
3
7
|
These functions mirror the behaviour of their :mod:`jax.numpy.fft` counterparts
|
|
@@ -43,7 +47,6 @@ import jax.numpy.fft as jfft
|
|
|
43
47
|
from .axis import Axis, AxisSelector, AxisSelection
|
|
44
48
|
from .core import NamedArray
|
|
45
49
|
|
|
46
|
-
|
|
47
50
|
AxisSizeLike = int | Axis | None
|
|
48
51
|
AxisMapping = Mapping[AxisSelector, AxisSizeLike]
|
|
49
52
|
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
import numbers
|
|
7
|
+
|
|
6
8
|
import jax.nn as jnn
|
|
7
9
|
import jax.numpy as jnp
|
|
8
10
|
|
|
@@ -64,16 +66,25 @@ def one_hot(x: NamedArray | int, class_axis: Axis, *, dtype=None) -> NamedArray:
|
|
|
64
66
|
# Disabling this to prevent a crash in XLA on GPU
|
|
65
67
|
# return hax.auto_sharded(hax.named(array, x.axes + (class_axis,)))
|
|
66
68
|
return hax.named(array, x.axes + (class_axis,))
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
|
|
70
|
+
x_array = jnp.asarray(x)
|
|
71
|
+
if x_array.ndim != 0:
|
|
72
|
+
raise TypeError("one_hot expects a scalar integer or NamedArray, " f"but got array with shape {x_array.shape}")
|
|
73
|
+
|
|
74
|
+
if isinstance(x, numbers.Integral):
|
|
69
75
|
assert class_axis.size > x >= -class_axis.size
|
|
76
|
+
else:
|
|
77
|
+
if not (jnp.issubdtype(x_array.dtype, jnp.integer) or jnp.issubdtype(x_array.dtype, jnp.bool_)):
|
|
78
|
+
raise TypeError(
|
|
79
|
+
"one_hot expects an integer scalar or NamedArray, " f"but got value with dtype {x_array.dtype}"
|
|
80
|
+
)
|
|
70
81
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
82
|
+
one = 1
|
|
83
|
+
if dtype is not None:
|
|
84
|
+
one = dtype(one)
|
|
74
85
|
|
|
75
|
-
|
|
76
|
-
|
|
86
|
+
array = jnp.zeros(class_axis.size, dtype=dtype).at[x_array].set(one)
|
|
87
|
+
return hax.auto_sharded(haliax.named(array, class_axis))
|
|
77
88
|
|
|
78
89
|
|
|
79
90
|
__all__ = [
|
|
@@ -251,7 +251,7 @@ def _gmm(lhs, rhs, group_sizes, out_axes, sharded=False, ar=False):
|
|
|
251
251
|
else:
|
|
252
252
|
gmm_fn = shard_map(
|
|
253
253
|
partial(gmm_sharded, ar=ar),
|
|
254
|
-
mesh=
|
|
254
|
+
mesh=jax.sharding.get_abstract_mesh(),
|
|
255
255
|
in_specs=(
|
|
256
256
|
hax.partitioning.pspec_for_axis(lhs.axes),
|
|
257
257
|
hax.partitioning.pspec_for_axis(rhs.axes),
|
|
@@ -127,9 +127,7 @@ def nonzero(array: NamedArray, *, size: Axis, fill_value: int = 0) -> tuple[Name
|
|
|
127
127
|
if not isinstance(array, NamedArray):
|
|
128
128
|
raise ValueError("array must be a NamedArray")
|
|
129
129
|
|
|
130
|
-
return tuple(
|
|
131
|
-
NamedArray(idx, (size,)) for idx in jnp.nonzero(array.array, size=size.size, fill_value=fill_value)
|
|
132
|
-
)
|
|
130
|
+
return tuple(NamedArray(idx, (size,)) for idx in jnp.nonzero(array.array, size=size.size, fill_value=fill_value))
|
|
133
131
|
|
|
134
132
|
|
|
135
133
|
def clip(array: NamedOrNumeric, a_min: NamedOrNumeric, a_max: NamedOrNumeric) -> NamedArray:
|
|
@@ -335,7 +333,7 @@ def unique(
|
|
|
335
333
|
)
|
|
336
334
|
|
|
337
335
|
if axis is not None:
|
|
338
|
-
axis_index = array.
|
|
336
|
+
axis_index = array.axis_indices(axis)
|
|
339
337
|
if axis_index is None:
|
|
340
338
|
raise ValueError(f"Axis {axis} not found in array. Available axes: {array.axes}")
|
|
341
339
|
out = jnp.unique(array.array, axis=axis_index, **kwargs)
|
|
@@ -10,31 +10,13 @@ import threading
|
|
|
10
10
|
import typing
|
|
11
11
|
import warnings
|
|
12
12
|
from math import prod
|
|
13
|
-
from typing import Callable, ContextManager, Mapping, Optional, ParamSpec, Sequence, TypeVar, Union
|
|
13
|
+
from typing import Callable, ContextManager, Mapping, Optional, ParamSpec, Sequence, TypeVar, Union, cast
|
|
14
14
|
|
|
15
15
|
import equinox as eqx
|
|
16
16
|
import jax
|
|
17
17
|
from equinox import is_array, module_update_wrapper
|
|
18
18
|
from jax.lax import with_sharding_constraint
|
|
19
|
-
from jax.sharding import
|
|
20
|
-
Mesh,
|
|
21
|
-
NamedSharding,
|
|
22
|
-
PartitionSpec,
|
|
23
|
-
SingleDeviceSharding,
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
try: # jax>=0.4.26
|
|
27
|
-
from jax.sharding import AbstractMesh, get_abstract_mesh
|
|
28
|
-
except Exception: # pragma: no cover - older JAX versions
|
|
29
|
-
AbstractMesh = Mesh # type: ignore[misc,assignment]
|
|
30
|
-
|
|
31
|
-
def get_abstract_mesh(): # type: ignore[dead-code]
|
|
32
|
-
try:
|
|
33
|
-
from jax.interpreters.pxla import thread_resources
|
|
34
|
-
except Exception:
|
|
35
|
-
from jax.experimental.maps import thread_resources
|
|
36
|
-
|
|
37
|
-
return thread_resources.env.physical_mesh
|
|
19
|
+
from jax.sharding import AbstractMesh, NamedSharding, Mesh, PartitionSpec, SingleDeviceSharding, get_abstract_mesh
|
|
38
20
|
|
|
39
21
|
|
|
40
22
|
from jaxtyping import PyTree
|
|
@@ -50,6 +32,7 @@ from .util import StringHolderEnum
|
|
|
50
32
|
|
|
51
33
|
PhysicalAxisSpec = Union[(str), Sequence[str]]
|
|
52
34
|
ResourceMapping = Mapping[(str), PhysicalAxisSpec]
|
|
35
|
+
MeshLike = Union[Mesh, AbstractMesh]
|
|
53
36
|
"""Mapping from logical axis names to physical axis names"""
|
|
54
37
|
|
|
55
38
|
F = typing.TypeVar("F", bound=typing.Callable)
|
|
@@ -109,6 +92,71 @@ def current_thread_local_mapping():
|
|
|
109
92
|
return _mapping_holder.thread_data.resource_mapping
|
|
110
93
|
|
|
111
94
|
|
|
95
|
+
def _resolve_mesh(mesh: Optional[MeshLike] = None) -> Optional[MeshLike]:
|
|
96
|
+
"""Inside jit, prefer an abstract mesh, outside jit prefer a concrete mesh."""
|
|
97
|
+
|
|
98
|
+
from jax._src.mesh import get_concrete_mesh
|
|
99
|
+
|
|
100
|
+
if mesh is not None:
|
|
101
|
+
if is_in_jit() and isinstance(mesh, Mesh):
|
|
102
|
+
return mesh.abstract_mesh
|
|
103
|
+
return mesh
|
|
104
|
+
|
|
105
|
+
if is_in_jit():
|
|
106
|
+
abstract = get_abstract_mesh()
|
|
107
|
+
if not abstract or abstract.empty:
|
|
108
|
+
concrete = get_concrete_mesh()
|
|
109
|
+
if concrete is not None and not concrete.empty:
|
|
110
|
+
return concrete.abstract_mesh
|
|
111
|
+
|
|
112
|
+
from jax.interpreters.pxla import thread_resources
|
|
113
|
+
|
|
114
|
+
old_mesh = thread_resources.env.physical_mesh
|
|
115
|
+
if old_mesh is not None and not old_mesh.empty:
|
|
116
|
+
return old_mesh.abstract_mesh
|
|
117
|
+
|
|
118
|
+
return abstract
|
|
119
|
+
else:
|
|
120
|
+
mesh = get_concrete_mesh() or get_abstract_mesh()
|
|
121
|
+
if mesh is not None and not mesh.empty:
|
|
122
|
+
return mesh
|
|
123
|
+
|
|
124
|
+
from jax.interpreters.pxla import thread_resources
|
|
125
|
+
|
|
126
|
+
old_mesh = thread_resources.env.physical_mesh
|
|
127
|
+
if old_mesh is not None and not old_mesh.empty:
|
|
128
|
+
return old_mesh
|
|
129
|
+
|
|
130
|
+
return None
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def mesh_context(mesh: MeshLike) -> ContextManager[None]:
|
|
134
|
+
"""Context manager that normalizes mesh handling across JAX versions."""
|
|
135
|
+
|
|
136
|
+
set_mesh_fn = getattr(jax, "set_mesh", None)
|
|
137
|
+
use_mesh_fn = getattr(jax.sharding, "use_mesh", None)
|
|
138
|
+
|
|
139
|
+
manager_factory: Optional[Callable[[MeshLike], ContextManager[None]]] = None
|
|
140
|
+
if set_mesh_fn is not None:
|
|
141
|
+
manager_factory = cast(Callable[[MeshLike], ContextManager[None]], set_mesh_fn)
|
|
142
|
+
elif use_mesh_fn is not None:
|
|
143
|
+
manager_factory = cast(Callable[[MeshLike], ContextManager[None]], use_mesh_fn)
|
|
144
|
+
|
|
145
|
+
if manager_factory is None:
|
|
146
|
+
msg = "Haliax requires a version of JAX that provides either `jax.set_mesh` or `jax.sharding.use_mesh`."
|
|
147
|
+
raise RuntimeError(msg)
|
|
148
|
+
|
|
149
|
+
context_manager = manager_factory(mesh)
|
|
150
|
+
|
|
151
|
+
return context_manager
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def set_mesh(mesh: MeshLike) -> ContextManager[None]:
|
|
155
|
+
"""Compatibility wrapper around `mesh_context` matching the JAX 0.7 API."""
|
|
156
|
+
|
|
157
|
+
return mesh_context(mesh)
|
|
158
|
+
|
|
159
|
+
|
|
112
160
|
def auto_sharded(x: T, mesh: Optional[Mesh] = None) -> T:
|
|
113
161
|
"""
|
|
114
162
|
Shard a PyTree using the global axis mapping. NamedArrays in the PyTree are sharded using the axis mapping
|
|
@@ -143,11 +191,15 @@ def shard(x: T, mapping: Optional[ResourceMapping] = None, mesh: Optional[Mesh]
|
|
|
143
191
|
|
|
144
192
|
assert not isinstance(mesh, dict)
|
|
145
193
|
|
|
146
|
-
|
|
147
|
-
mesh = _get_mesh()
|
|
194
|
+
resolved_mesh = _resolve_mesh(mesh)
|
|
148
195
|
|
|
149
|
-
|
|
150
|
-
|
|
196
|
+
if resolved_mesh is None:
|
|
197
|
+
if not is_in_jit():
|
|
198
|
+
warnings.warn("No mesh found. Not sharding.", RuntimeWarning)
|
|
199
|
+
return x
|
|
200
|
+
|
|
201
|
+
if isinstance(resolved_mesh, AbstractMesh) and resolved_mesh.empty:
|
|
202
|
+
return x
|
|
151
203
|
|
|
152
204
|
if is_in_jit() and is_on_mac_metal():
|
|
153
205
|
warnings.warn("Sharding constraints are not supported in jit on metal", RuntimeWarning)
|
|
@@ -162,16 +214,11 @@ def shard(x: T, mapping: Optional[ResourceMapping] = None, mesh: Optional[Mesh]
|
|
|
162
214
|
# could use eqx.partition to avoid this, but eh
|
|
163
215
|
return named
|
|
164
216
|
|
|
165
|
-
|
|
166
|
-
assert isinstance(
|
|
167
|
-
|
|
217
|
+
pspec = pspec_for(named, mapping, preserve_existing_shardings=False)
|
|
218
|
+
assert isinstance(pspec, PartitionSpec)
|
|
219
|
+
sharding = NamedSharding(resolved_mesh, pspec)
|
|
168
220
|
if is_in_jit():
|
|
169
221
|
return with_sharding_constraint(named, sharding)
|
|
170
|
-
# as a special case, SingleDeviceShardings are routed through jit
|
|
171
|
-
elif isinstance(in_sharding, SingleDeviceSharding) and in_sharding._device in sharding.device_set:
|
|
172
|
-
# TODO(dlwh): this should be unnecessary in JAX soon. Check after 2024-08-01
|
|
173
|
-
sharded_array = jax.jit(lambda x: x, out_shardings=sharding)(named)
|
|
174
|
-
return sharded_array
|
|
175
222
|
else:
|
|
176
223
|
ret = jax.device_put(named, sharding)
|
|
177
224
|
return ret
|
|
@@ -189,7 +236,6 @@ def pspec_for(
|
|
|
189
236
|
tree: PyTree,
|
|
190
237
|
resource_mapping: Optional[ResourceMapping] = None,
|
|
191
238
|
preserve_existing_shardings: bool = True,
|
|
192
|
-
use_auto_sharding: bool = True,
|
|
193
239
|
) -> PyTree:
|
|
194
240
|
"""Infer the :class:`PartitionSpec` for a module.
|
|
195
241
|
|
|
@@ -276,7 +322,6 @@ def infer_resource_partitions(
|
|
|
276
322
|
tree: PyTree,
|
|
277
323
|
resource_mapping: Optional[ResourceMapping] = None,
|
|
278
324
|
preserve_existing_shardings: bool = True,
|
|
279
|
-
use_auto_sharding: bool = True,
|
|
280
325
|
mesh: Optional[Mesh] = None,
|
|
281
326
|
) -> PyTree:
|
|
282
327
|
"""
|
|
@@ -291,11 +336,12 @@ def infer_resource_partitions(
|
|
|
291
336
|
tree,
|
|
292
337
|
resource_mapping=resource_mapping,
|
|
293
338
|
preserve_existing_shardings=preserve_existing_shardings,
|
|
294
|
-
use_auto_sharding=use_auto_sharding,
|
|
295
339
|
)
|
|
296
340
|
|
|
297
|
-
|
|
298
|
-
|
|
341
|
+
resolved_mesh = _resolve_mesh(mesh)
|
|
342
|
+
if resolved_mesh is None:
|
|
343
|
+
raise ValueError("No mesh found")
|
|
344
|
+
assert not isinstance(resolved_mesh, dict)
|
|
299
345
|
|
|
300
346
|
def to_sharding(node: typing.Any, spec: typing.Any):
|
|
301
347
|
if spec is None:
|
|
@@ -306,7 +352,7 @@ def infer_resource_partitions(
|
|
|
306
352
|
else:
|
|
307
353
|
return None
|
|
308
354
|
else:
|
|
309
|
-
return NamedSharding(
|
|
355
|
+
return NamedSharding(resolved_mesh, spec)
|
|
310
356
|
|
|
311
357
|
return htu.tree_map(to_sharding, tree, pspecs)
|
|
312
358
|
|
|
@@ -407,7 +453,7 @@ class _NamedJitWrapper(eqx.Module):
|
|
|
407
453
|
if out_axis_resources is not None:
|
|
408
454
|
# TODO: when AUTO is fixed (or eval_shape can give shardings), use it here
|
|
409
455
|
out_resources = infer_resource_partitions(
|
|
410
|
-
output_shape, out_axis_resources, preserve_existing_shardings=False
|
|
456
|
+
output_shape, out_axis_resources, preserve_existing_shardings=False
|
|
411
457
|
)
|
|
412
458
|
my_pjit_args["out_shardings"] = out_resources
|
|
413
459
|
|
|
@@ -642,7 +688,7 @@ def physical_axis_name(axis: AxisSelector, mapping: Optional[ResourceMapping] =
|
|
|
642
688
|
def physical_axis_size(axis: AxisSelector, mapping: Optional[ResourceMapping] = None) -> Optional[int]:
|
|
643
689
|
"""Get the physical axis size for a logical axis. This is the product of the size of all physical axes
|
|
644
690
|
that this logical axis is mapped to."""
|
|
645
|
-
mesh =
|
|
691
|
+
mesh = _resolve_mesh()
|
|
646
692
|
|
|
647
693
|
if mesh is None:
|
|
648
694
|
raise ValueError("No mesh found")
|
|
@@ -659,10 +705,14 @@ def physical_axis_size(axis: AxisSelector, mapping: Optional[ResourceMapping] =
|
|
|
659
705
|
|
|
660
706
|
|
|
661
707
|
def sharding_for_axis(
|
|
662
|
-
axis: AxisSelection, mapping: Optional[ResourceMapping] = None, mesh: Optional[
|
|
708
|
+
axis: AxisSelection, mapping: Optional[ResourceMapping] = None, mesh: Optional[MeshLike] = None
|
|
663
709
|
) -> NamedSharding:
|
|
664
710
|
"""Get the sharding for a single axis"""
|
|
665
|
-
|
|
711
|
+
resolved_mesh = _resolve_mesh(mesh)
|
|
712
|
+
if resolved_mesh is None:
|
|
713
|
+
raise ValueError("No mesh found")
|
|
714
|
+
|
|
715
|
+
return NamedSharding(resolved_mesh, pspec_for_axis(axis, mapping))
|
|
666
716
|
|
|
667
717
|
|
|
668
718
|
def pspec_for_axis(axis: AxisSelection, mapping: Optional[ResourceMapping] = None) -> PartitionSpec:
|
|
@@ -681,28 +731,17 @@ def round_axis_for_partitioning(axis: Axis, mapping: Optional[ResourceMapping] =
|
|
|
681
731
|
return Axis(axis.name, new_size)
|
|
682
732
|
|
|
683
733
|
|
|
684
|
-
def _get_mesh() -> Mesh |
|
|
685
|
-
"""
|
|
686
|
-
|
|
687
|
-
On newer versions of JAX this prefers ``get_abstract_mesh`` which does not
|
|
688
|
-
capture concrete devices. If no abstract mesh is currently active we fall
|
|
689
|
-
back to the concrete mesh used by ``Mesh``'s context manager so existing
|
|
690
|
-
code continues to work.
|
|
691
|
-
"""
|
|
734
|
+
def _get_mesh() -> Mesh | None:
|
|
735
|
+
"""Deprecated helper that simply proxies to :func:`get_abstract_mesh`."""
|
|
692
736
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
pass
|
|
699
|
-
|
|
700
|
-
try:
|
|
701
|
-
from jax.interpreters.pxla import thread_resources
|
|
702
|
-
except Exception: # pragma: no cover - jax<0.4
|
|
703
|
-
from jax.experimental.maps import thread_resources
|
|
737
|
+
warnings.warn(
|
|
738
|
+
"`_get_mesh` is deprecated; use `jax's get_abstract_mesh or get_concrete_mesh` instead",
|
|
739
|
+
DeprecationWarning,
|
|
740
|
+
stacklevel=2,
|
|
741
|
+
)
|
|
704
742
|
|
|
705
|
-
|
|
743
|
+
mesh = _resolve_mesh()
|
|
744
|
+
return mesh
|
|
706
745
|
|
|
707
746
|
|
|
708
747
|
def _is_jit_tracer(x) -> bool:
|