pathwaysutils 0.1.13__tar.gz → 0.1.14__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.
- pathwaysutils-0.1.14/PKG-INFO +90 -0
- pathwaysutils-0.1.14/README.md +50 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/__init__.py +1 -1
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/_initialize.py +3 -1
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/elastic/elastic.py +4 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/elastic/manager.py +11 -16
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/concatenate_by_mesh_axis.py +25 -1
- pathwaysutils-0.1.14/pathwaysutils/experimental/gke/README.md +142 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/gke/jobset.py +394 -117
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/profiling.py +11 -10
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/reshard.py +1 -1
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/README.md +2 -2
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/deploy_pathways_service.py +8 -2
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/dockerfiles/sample_sidecar.dockerfile +2 -2
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/gke_utils.py +236 -32
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/isc_pathways.py +17 -4
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/split_by_mesh_axis.py +2 -2
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/persistence/helper.py +7 -2
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/profiling.py +20 -7
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/proxy_backend.py +13 -1
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/reshard.py +3 -3
- pathwaysutils-0.1.14/pathwaysutils/test/elastic_simulated_fault_integration_test.py +128 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/experimental/gke/jobset_test.py +611 -61
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/experimental/gke/testdata/model_lite_tpuv5e_4x8.yaml +4 -4
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/experimental/shared_pathways_service/deploy_pathways_service_test.py +36 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/experimental/shared_pathways_service/gke_utils_test.py +486 -69
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/experimental/shared_pathways_service/isc_pathways_test.py +188 -34
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/initialize_test.py +4 -2
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/mock_fault_injection.py +51 -8
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/mock_fault_injection_test.py +47 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/persistence_test.py +20 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/profiling_test.py +59 -3
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/proxy_backend_test.py +12 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/reshard_test.py +13 -0
- pathwaysutils-0.1.14/pathwaysutils/test/tpu_utils_test.py +44 -0
- pathwaysutils-0.1.14/pathwaysutils/tpu_utils.py +32 -0
- pathwaysutils-0.1.13/PKG-INFO +0 -61
- pathwaysutils-0.1.13/README.md +0 -21
- pathwaysutils-0.1.13/pathwaysutils/extras/elastic/model_comparison.html +0 -2052
- pathwaysutils-0.1.13/pathwaysutils/extras/simple_model/__init__.py +0 -48
- pathwaysutils-0.1.13/pathwaysutils/extras/simple_model/compile.py +0 -142
- pathwaysutils-0.1.13/pathwaysutils/extras/simple_model/config.py +0 -58
- pathwaysutils-0.1.13/pathwaysutils/extras/simple_model/data.py +0 -63
- pathwaysutils-0.1.13/pathwaysutils/extras/simple_model/model.py +0 -101
- pathwaysutils-0.1.13/pathwaysutils/extras/simple_model/simple_model.py +0 -78
- pathwaysutils-0.1.13/pathwaysutils/extras/simple_model/simple_model_test.py +0 -356
- pathwaysutils-0.1.13/pathwaysutils/extras/simple_model/workload.py +0 -219
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/LICENSE +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/collect_profile.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/debug/__init__.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/debug/timing.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/debug/watchdog.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/elastic/__init__.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/__init__.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/gke/__init__.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/__init__.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/metrics_collector.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/run_connect_example.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/run_workload.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/start_vscode_on_cpu_np.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/tpu_specs.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/validators.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/yamls/code-server.yaml +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/shared_pathways_service/yamls/pw-proxy.yaml +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/jax/__init__.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/lru_cache.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/persistence/__init__.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/plugin_executable.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/__init__.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/debug/__init__.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/debug/timing_test.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/debug/watchdog_test.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/experimental/reshard_test.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/experimental/shared_pathways_service/metrics_collector_test.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/experimental/shared_pathways_service/run_workload_test.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/experimental/shared_pathways_service/start_vscode_on_cpu_np_test.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/experimental/shared_pathways_service/tpu_specs_test.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/experimental/shared_pathways_service/validators_test.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/lru_cache_test.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/test/plugin_executable_test.py +0 -0
- {pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pyproject.toml +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pathwaysutils
|
|
3
|
+
Version: 0.1.14
|
|
4
|
+
Summary: Package of Pathways-on-Cloud utilities.
|
|
5
|
+
Keywords:
|
|
6
|
+
Author-email: Pathways-on-Cloud Utilities Developers <pathwaysutils-dev@google.com>
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: absl-py
|
|
12
|
+
Requires-Dist: fastapi
|
|
13
|
+
Requires-Dist: jax>=0.10.0
|
|
14
|
+
Requires-Dist: orbax-checkpoint>=0.12.3
|
|
15
|
+
Requires-Dist: uvicorn
|
|
16
|
+
Requires-Dist: requests
|
|
17
|
+
Requires-Dist: packaging
|
|
18
|
+
Requires-Dist: pylint>=2.6.0 ; extra == "dev"
|
|
19
|
+
Requires-Dist: pyink ; extra == "dev"
|
|
20
|
+
Requires-Dist: kubernetes ; extra == "gke"
|
|
21
|
+
Requires-Dist: pyyaml ; extra == "gke"
|
|
22
|
+
Requires-Dist: portpicker ; extra == "sps"
|
|
23
|
+
Requires-Dist: google-cloud-monitoring ; extra == "sps"
|
|
24
|
+
Requires-Dist: portpicker ; extra == "sps-without-monitoring"
|
|
25
|
+
Requires-Dist: google-cloud-monitoring ; extra == "test"
|
|
26
|
+
Requires-Dist: httpx ; extra == "test"
|
|
27
|
+
Requires-Dist: kubernetes ; extra == "test"
|
|
28
|
+
Requires-Dist: portpicker ; extra == "test"
|
|
29
|
+
Requires-Dist: pyyaml ; extra == "test"
|
|
30
|
+
Requires-Dist: pytest ; extra == "test"
|
|
31
|
+
Project-URL: changelog, https://github.com/AI-Hypercomputer/pathways-utils/blob/main/CHANGELOG.md
|
|
32
|
+
Project-URL: homepage, https://github.com/AI-Hypercomputer/pathways-utils
|
|
33
|
+
Project-URL: repository, https://github.com/AI-Hypercomputer/pathways-utils
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Provides-Extra: gke
|
|
36
|
+
Provides-Extra: sps
|
|
37
|
+
Provides-Extra: sps-without-monitoring
|
|
38
|
+
Provides-Extra: test
|
|
39
|
+
|
|
40
|
+
# APIs to get started with using Pathways on Cloud
|
|
41
|
+
|
|
42
|
+
Pathways is a compute orchestration runtime for single-controller ML workloads
|
|
43
|
+
across multiple Cloud TPU slices. A single Python controller orchestrates
|
|
44
|
+
computation across hundreds or thousands of TPU chips, unlocking slice-level
|
|
45
|
+
training resiliency, fast cross-slice data movement, and interactive
|
|
46
|
+
multi-slice development.
|
|
47
|
+
|
|
48
|
+
This package bundles the Python client integrations, resharding and elasticity
|
|
49
|
+
helpers, and GKE deployment builders for running JAX workloads on Pathways on
|
|
50
|
+
Cloud.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install pathwaysutils
|
|
56
|
+
# Optional GKE JobSet generator and kubectl/Kubernetes client dependencies:
|
|
57
|
+
pip install 'pathwaysutils[gke]'
|
|
58
|
+
# Optional experimental Shared Pathways Service (SPS) dependencies:
|
|
59
|
+
pip install 'pathwaysutils[sps]'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Core Modules
|
|
63
|
+
|
|
64
|
+
- `pathwaysutils.initialize()` registers the Pathways IFRT proxy backend,
|
|
65
|
+
configures the compilation cache and XProf trace hooks, and registers Orbax
|
|
66
|
+
checkpoint handlers.
|
|
67
|
+
- `pathwaysutils.reshard.reshard` reshards arrays and PyTrees across device
|
|
68
|
+
meshes directly on Pathways workers via the IFRT `RemapArray` API without
|
|
69
|
+
routing tensors through controller memory.
|
|
70
|
+
- `pathwaysutils.elastic.manager.Manager` monitors slice health in the
|
|
71
|
+
background and provides `@elastic_retry` and `ScaleUpSignalError` for
|
|
72
|
+
step-level fault recovery and dynamic slice scaling.
|
|
73
|
+
- [`PathwaysJobSet`][gke-readme] (`pathwaysutils.experimental.gke.jobset`)
|
|
74
|
+
builds, customizes, exports, and deploys Kubernetes `JobSet` manifests for
|
|
75
|
+
Pathways workloads on GKE.
|
|
76
|
+
- [Shared Pathways Service][sps-readme]
|
|
77
|
+
(`pathwaysutils.experimental.shared_pathways_service`) deploys a persistent
|
|
78
|
+
multi-tenant Pathways service on GKE for interactive JAX sessions.
|
|
79
|
+
|
|
80
|
+
## Further Reading
|
|
81
|
+
|
|
82
|
+
- [Get started with Pathways on Google Cloud][cloud-docs]
|
|
83
|
+
- [Pathways Research Paper](https://arxiv.org/abs/2203.12533)
|
|
84
|
+
|
|
85
|
+
[gke-readme]: https://github.com/AI-Hypercomputer/pathways-utils/tree/main/pathwaysutils/experimental/gke
|
|
86
|
+
[sps-readme]: https://github.com/AI-Hypercomputer/pathways-utils/tree/main/pathwaysutils/experimental/shared_pathways_service
|
|
87
|
+
[cloud-docs]: https://docs.cloud.google.com/ai-hypercomputer/docs/workloads/pathways-on-cloud/pathways-intro
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# APIs to get started with using Pathways on Cloud
|
|
2
|
+
|
|
3
|
+
Pathways is a compute orchestration runtime for single-controller ML workloads
|
|
4
|
+
across multiple Cloud TPU slices. A single Python controller orchestrates
|
|
5
|
+
computation across hundreds or thousands of TPU chips, unlocking slice-level
|
|
6
|
+
training resiliency, fast cross-slice data movement, and interactive
|
|
7
|
+
multi-slice development.
|
|
8
|
+
|
|
9
|
+
This package bundles the Python client integrations, resharding and elasticity
|
|
10
|
+
helpers, and GKE deployment builders for running JAX workloads on Pathways on
|
|
11
|
+
Cloud.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install pathwaysutils
|
|
17
|
+
# Optional GKE JobSet generator and kubectl/Kubernetes client dependencies:
|
|
18
|
+
pip install 'pathwaysutils[gke]'
|
|
19
|
+
# Optional experimental Shared Pathways Service (SPS) dependencies:
|
|
20
|
+
pip install 'pathwaysutils[sps]'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Core Modules
|
|
24
|
+
|
|
25
|
+
- `pathwaysutils.initialize()` registers the Pathways IFRT proxy backend,
|
|
26
|
+
configures the compilation cache and XProf trace hooks, and registers Orbax
|
|
27
|
+
checkpoint handlers.
|
|
28
|
+
- `pathwaysutils.reshard.reshard` reshards arrays and PyTrees across device
|
|
29
|
+
meshes directly on Pathways workers via the IFRT `RemapArray` API without
|
|
30
|
+
routing tensors through controller memory.
|
|
31
|
+
- `pathwaysutils.elastic.manager.Manager` monitors slice health in the
|
|
32
|
+
background and provides `@elastic_retry` and `ScaleUpSignalError` for
|
|
33
|
+
step-level fault recovery and dynamic slice scaling.
|
|
34
|
+
- [`PathwaysJobSet`][gke-readme] (`pathwaysutils.experimental.gke.jobset`)
|
|
35
|
+
builds, customizes, exports, and deploys Kubernetes `JobSet` manifests for
|
|
36
|
+
Pathways workloads on GKE.
|
|
37
|
+
- [Shared Pathways Service][sps-readme]
|
|
38
|
+
(`pathwaysutils.experimental.shared_pathways_service`) deploys a persistent
|
|
39
|
+
multi-tenant Pathways service on GKE for interactive JAX sessions.
|
|
40
|
+
|
|
41
|
+
## Further Reading
|
|
42
|
+
|
|
43
|
+
- [Get started with Pathways on Google Cloud][cloud-docs]
|
|
44
|
+
- [Pathways Research Paper](https://arxiv.org/abs/2203.12533)
|
|
45
|
+
|
|
46
|
+
[gke-readme]: https://github.com/AI-Hypercomputer/pathways-utils/tree/main/pathwaysutils/experimental/gke
|
|
47
|
+
[sps-readme]: https://github.com/AI-Hypercomputer/pathways-utils/tree/main/pathwaysutils/experimental/shared_pathways_service
|
|
48
|
+
[cloud-docs]: https://docs.cloud.google.com/ai-hypercomputer/docs/workloads/pathways-on-cloud/pathways-intro
|
|
49
|
+
|
|
50
|
+
|
|
@@ -40,7 +40,9 @@ def is_pathways_backend_used() -> bool:
|
|
|
40
40
|
is not necessarily which backend is ultimately selected or there may be more
|
|
41
41
|
than one platform specified and another may have higher priority.
|
|
42
42
|
"""
|
|
43
|
-
return
|
|
43
|
+
return bool(
|
|
44
|
+
jax.config.jax_platforms and "proxy" in jax.config.jax_platforms
|
|
45
|
+
)
|
|
44
46
|
|
|
45
47
|
|
|
46
48
|
def _is_persistence_enabled() -> bool:
|
|
@@ -198,6 +198,10 @@ def wait_for_slices(
|
|
|
198
198
|
TimeoutError: If the timeout is reached before the slices become
|
|
199
199
|
active.
|
|
200
200
|
"""
|
|
201
|
+
if poll_interval < 0:
|
|
202
|
+
raise ValueError(f"poll_interval must be non-negative, got {poll_interval}")
|
|
203
|
+
if timeout is not None and timeout < 0:
|
|
204
|
+
raise ValueError(f"timeout must be non-negative, got {timeout}")
|
|
201
205
|
if slice_to_devices is None:
|
|
202
206
|
_logger.debug("slice_to_devices is None. Getting from jax.devices().")
|
|
203
207
|
slice_to_devices = get_slice_to_devices(jax.devices())
|
|
@@ -158,8 +158,9 @@ class Manager:
|
|
|
158
158
|
pass
|
|
159
159
|
else:
|
|
160
160
|
raise
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
finally:
|
|
162
|
+
self._monitor_thread = None
|
|
163
|
+
self._stop_event = None
|
|
163
164
|
|
|
164
165
|
@functools.cached_property
|
|
165
166
|
def total_slice_count(self) -> int:
|
|
@@ -197,6 +198,14 @@ class Manager:
|
|
|
197
198
|
"""The number of active slices."""
|
|
198
199
|
return len(self.active_slice_indices)
|
|
199
200
|
|
|
201
|
+
@property
|
|
202
|
+
def active_devices(self) -> list[jax.Device]:
|
|
203
|
+
"""The devices belonging to the active slices, ordered by slice index."""
|
|
204
|
+
devices = []
|
|
205
|
+
for slice_index in sorted(self.active_slice_indices):
|
|
206
|
+
devices.extend(self.slice_to_devices[slice_index])
|
|
207
|
+
return devices
|
|
208
|
+
|
|
200
209
|
def scale_by_active_slices(self, x: int | float) -> int | float:
|
|
201
210
|
"""Scale x by the number of active slices."""
|
|
202
211
|
if isinstance(x, int):
|
|
@@ -214,20 +223,6 @@ class Manager:
|
|
|
214
223
|
else:
|
|
215
224
|
raise ValueError(f"Unsupported type: {type(x)=}")
|
|
216
225
|
|
|
217
|
-
def _cleanup_on_retry(self):
|
|
218
|
-
"""Cleans up JAX caches and traces on retry."""
|
|
219
|
-
try:
|
|
220
|
-
_logger.debug("Cleaning up any ongoing traces")
|
|
221
|
-
jax.profiler.stop_trace()
|
|
222
|
-
except (RuntimeError, ValueError):
|
|
223
|
-
_logger.debug("No ongoing traces to clean up")
|
|
224
|
-
except Exception: # pylint: disable=broad-exception-caught
|
|
225
|
-
_logger.exception("Error cleaning up ongoing traces")
|
|
226
|
-
|
|
227
|
-
jax.clear_caches()
|
|
228
|
-
for array in jax.live_arrays():
|
|
229
|
-
array.delete()
|
|
230
|
-
|
|
231
226
|
def _check_inactive_slices(self) -> None:
|
|
232
227
|
"""Checks inactive slices and updates available_inactive_slices."""
|
|
233
228
|
if not self.inactive_slice_indices:
|
{pathwaysutils-0.1.13 → pathwaysutils-0.1.14}/pathwaysutils/experimental/concatenate_by_mesh_axis.py
RENAMED
|
@@ -68,10 +68,21 @@ def concatenate_by_mesh_axis(
|
|
|
68
68
|
if not flattened_arrays[0]:
|
|
69
69
|
return array_trees[0]
|
|
70
70
|
|
|
71
|
-
# Extract the shared mesh from each PyTree
|
|
71
|
+
# Extract the shared mesh from each PyTree and verify all leaves in a PyTree
|
|
72
|
+
# share that mesh.
|
|
72
73
|
meshes_to_concatenate = [
|
|
73
74
|
_get_named_sharding(array).mesh for array in input_flat_arrays[0]
|
|
74
75
|
]
|
|
76
|
+
for tree_arrays, expected_mesh in zip(
|
|
77
|
+
flattened_arrays, meshes_to_concatenate
|
|
78
|
+
):
|
|
79
|
+
for array in tree_arrays:
|
|
80
|
+
sharding = _get_named_sharding(array)
|
|
81
|
+
if sharding.mesh != expected_mesh:
|
|
82
|
+
raise ValueError(
|
|
83
|
+
"All arrays in each PyTree must have the same mesh. Got"
|
|
84
|
+
f" {sharding.mesh} vs. {expected_mesh}."
|
|
85
|
+
)
|
|
75
86
|
|
|
76
87
|
# Validate that the meshes are compatible.
|
|
77
88
|
reference_mesh = meshes_to_concatenate[0]
|
|
@@ -117,6 +128,19 @@ def concatenate_by_mesh_axis(
|
|
|
117
128
|
) -> jax.sharding.NamedSharding:
|
|
118
129
|
reference_sharding = _get_named_sharding(arrays[0])
|
|
119
130
|
reference_spec = reference_sharding.spec
|
|
131
|
+
for array in arrays[1:]:
|
|
132
|
+
sharding = _get_named_sharding(array)
|
|
133
|
+
if sharding.spec != reference_spec:
|
|
134
|
+
raise ValueError(
|
|
135
|
+
"Corresponding arrays across PyTrees must have the same"
|
|
136
|
+
f" PartitionSpec. Got {sharding.spec} vs. {reference_spec}."
|
|
137
|
+
)
|
|
138
|
+
if sharding.memory_kind != reference_sharding.memory_kind:
|
|
139
|
+
raise ValueError(
|
|
140
|
+
"Corresponding arrays across PyTrees must have the same"
|
|
141
|
+
f" memory_kind. Got {sharding.memory_kind} vs."
|
|
142
|
+
f" {reference_sharding.memory_kind}."
|
|
143
|
+
)
|
|
120
144
|
return jax.sharding.NamedSharding(
|
|
121
145
|
concatenated_mesh,
|
|
122
146
|
reference_spec,
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# PathwaysJobSet Builder
|
|
2
|
+
|
|
3
|
+
`PathwaysJobSet` generates and deploys Kubernetes `JobSet` resources (`jobset.x-k8s.io`) for running distributed Pathways workloads on Google Kubernetes Engine (GKE) without requiring custom controllers.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install 'pathwaysutils[gke]'
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quickstart
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from pathwaysutils.experimental.gke import jobset
|
|
15
|
+
|
|
16
|
+
pw_jobset = jobset.PathwaysJobSet(
|
|
17
|
+
name="my-workload",
|
|
18
|
+
namespace="default",
|
|
19
|
+
pathways_dir="gs://my-bucket/pathways-scratch",
|
|
20
|
+
tpu_type="v5e",
|
|
21
|
+
topology="2x4",
|
|
22
|
+
num_slices=1,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Export to YAML or deploy directly to the active cluster
|
|
26
|
+
pw_jobset.export_yaml("jobset.yaml")
|
|
27
|
+
pw_jobset.apply(recreate=True)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
### Elasticity & Multislice
|
|
33
|
+
Scale across multiple TPU slices with dynamic resilience:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
pw_jobset = jobset.PathwaysJobSet(
|
|
37
|
+
name="elastic-v6e",
|
|
38
|
+
namespace="default",
|
|
39
|
+
pathways_dir="gs://my-bucket/scratch",
|
|
40
|
+
tpu_type="v6e",
|
|
41
|
+
topology="4x4",
|
|
42
|
+
num_slices=4,
|
|
43
|
+
elastic_slices=2, # Configures Pathways Proxy for dynamic slice recovery
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Heterogeneous Multi-Topology Slices
|
|
48
|
+
Combine multiple TPU slice topologies as separate worker `replicatedJobs`
|
|
49
|
+
within a single `JobSet`. Call `add_worker_topology` before worker mutators
|
|
50
|
+
(`add_colocated_python`, `add_gcsfuse`, or `with_custom_libtpu`) so they apply
|
|
51
|
+
across all worker templates:
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
pw_jobset = (
|
|
55
|
+
jobset.PathwaysJobSet(
|
|
56
|
+
name="heterogeneous-v5e",
|
|
57
|
+
namespace="default",
|
|
58
|
+
pathways_dir="gs://my-bucket/scratch",
|
|
59
|
+
tpu_type="v5e",
|
|
60
|
+
topology="4x8",
|
|
61
|
+
num_slices=1,
|
|
62
|
+
)
|
|
63
|
+
.add_worker_topology(
|
|
64
|
+
tpu_type="ct5lp-hightpu-8t",
|
|
65
|
+
topology="2x4",
|
|
66
|
+
num_slices=1,
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### In-Pod User Workload
|
|
72
|
+
Run training or inference directly in the head pod alongside the Resource Manager and Proxy sidecars:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
pw_jobset.add_user_workload(
|
|
76
|
+
image="us-docker.pkg.dev/my-project/images/my-trainer:latest",
|
|
77
|
+
command="python3 train.py --batch_size=32",
|
|
78
|
+
env={"LOG_LEVEL": "INFO"},
|
|
79
|
+
)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Colocated Python Sidecar
|
|
83
|
+
Inject a sidecar container onto worker pods sharing memory with
|
|
84
|
+
`pathways-worker` for zero-copy tensor transfers:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
pw_jobset.add_colocated_python(
|
|
88
|
+
image="us-docker.pkg.dev/my-project/images/worker-sidecar:latest",
|
|
89
|
+
shm_mount_path="/tmp/shared-memory",
|
|
90
|
+
shm_size_limit="16Gi",
|
|
91
|
+
)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### GCSFuse Cloud Storage Mounts
|
|
95
|
+
Mount GCS buckets to head, worker, or all containers:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
pw_jobset.add_gcsfuse(
|
|
99
|
+
containers="all",
|
|
100
|
+
mount_path="/data",
|
|
101
|
+
bucket="my-data-bucket",
|
|
102
|
+
read_only=True,
|
|
103
|
+
)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Custom `libtpu.so` Runtime Override
|
|
107
|
+
Set `TPU_LIBRARY_PATH` across the Pathways containers (`pathways-rm`,
|
|
108
|
+
`pathways-proxy`, and `pathways-worker` when `containers="all"`) without
|
|
109
|
+
injecting it into user or sidecar containers:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
pw_jobset.with_custom_libtpu(
|
|
113
|
+
libtpu_path="/data/libtpu/libtpu.so",
|
|
114
|
+
containers="all",
|
|
115
|
+
)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Container & Pod Spec Overrides
|
|
119
|
+
Customize arguments, environment variables, resources, or volumes on any container or pod:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
pw_jobset = jobset.PathwaysJobSet(
|
|
123
|
+
...,
|
|
124
|
+
rm_container_kwargs={"args": ["--v=1"]},
|
|
125
|
+
proxy_container_kwargs={"env": {"XLA_FLAGS": "--xla_dump_to=/tmp"}},
|
|
126
|
+
worker_container_kwargs={"args": ["--stderrthreshold=0"]},
|
|
127
|
+
worker_pod_spec_kwargs={"priority_class_name": "high-priority"},
|
|
128
|
+
)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Serialization & Round-Tripping
|
|
132
|
+
|
|
133
|
+
Convert between Python objects, YAML files, and dictionaries:
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
# Save and load JobSet configurations
|
|
137
|
+
pw_jobset.export_yaml("jobset.yaml")
|
|
138
|
+
loaded_jobset = jobset.PathwaysJobSet.import_yaml("jobset.yaml")
|
|
139
|
+
|
|
140
|
+
# Inspect raw Kubernetes resource dictionary
|
|
141
|
+
config_dict = pw_jobset.to_dict()
|
|
142
|
+
```
|