-
Notifications
You must be signed in to change notification settings - Fork 602
Register LazyTensor with the Orbax v1 leaf-handler registry #5148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -50,6 +50,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| import argparse | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import dataclasses | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| from functools import partial | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import json | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -76,6 +77,10 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||
| from maxtext.utils.globals import HF_IDS | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import numpy as np | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| from orbax.checkpoint import type_handlers | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| from orbax.checkpoint import v1 as ocp_v1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| from orbax.checkpoint.experimental.v1._src.handlers import pytree_handler | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| from orbax.checkpoint.experimental.v1._src.serialization import numpy_leaf_handler | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| from orbax.checkpoint.experimental.v1._src.serialization import registry as leaf_handler_registry | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| from safetensors import safe_open | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -297,6 +302,51 @@ async def serialize(self, value, *args, **kwargs): | |||||||||||||||||||||||||||||||||||||||||||||||||||
| type_handlers.register_type_handler(LazyTensor, LazyTensorHandler(), override=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| class LazyTensorLeafHandler(numpy_leaf_handler.NumpyLeafHandler): | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Orbax v1 leaf handler for LazyTensor. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| The v0 registration above cannot serve the v1 save path. A v1 ``PyTreeHandler`` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| resolves leaves through a per-instance ``LeafHandlerRegistry`` and *derives* its | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| v0 registry from itself, so the compatibility bridge only runs v1 -> v0; a v0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| global registration is unreachable from v1. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| Like its v0 counterpart this masquerades as the standard numpy handler -- | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``secondary_typestrs`` below writes ``np.ndarray`` as the leaf's typestr -- so | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| the checkpoint is indistinguishable from one a plain ``NumpyLeafHandler`` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| produced and restores in a standard MaxText instance. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def serialize(self, params, serialization_context): | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| # MATERIALIZE: trigger the lazy load (__array__) explicitly before saving. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| # This ensures the parent NumpyLeafHandler receives real np.ndarrays. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| params = [dataclasses.replace(param, value=np.asarray(param.value)) for param in params] | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Explicitly pass the expected dtype (
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| return await super().serialize(params, serialization_context) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| class LazyTensorPyTreeHandler(pytree_handler.PyTreeHandler): | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
| """``PyTreeHandler`` whose leaf registry additionally accepts ``LazyTensor``.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, **kwargs): | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if "leaf_handler_registry" not in kwargs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| registry = leaf_handler_registry.StandardLeafHandlerRegistry() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| registry.add( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| LazyTensor, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| numpy_leaf_handler.NumpyShapeDtype, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| LazyTensorLeafHandler, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| override=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| secondary_typestrs=["np.ndarray"], | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| kwargs["leaf_handler_registry"] = registry | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| super().__init__(**kwargs) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+329
to
+340
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To make
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| def build_lazy_tensor_checkpointables_registry(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Registry that saves MaxText's "items" checkpointable with LazyTensor support.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| registry = ocp_v1.handlers.local_registry(include_global_registry=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| registry.add(LazyTensorPyTreeHandler, checkpointable_name="items") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return registry | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_maxtext_model_info(config): | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Initializes the abstract MaxText model and returns parameter mapping information. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1093,6 +1143,7 @@ def _eager_getter(key): | |||||||||||||||||||||||||||||||||||||||||||||||||||
| config.checkpoint_storage_use_ocdbt, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| config.checkpoint_storage_use_zarr3, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| config=config, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkpointables_registry=build_lazy_tensor_checkpointables_registry(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| print_ram_usage("Program Ends") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since
PyTreeHandleris publicly exposed in the Orbax v1 API, we can import and inherit fromocp_v1.PyTreeHandlerdirectly instead of reaching into the private_srcmodule. This reduces reliance on internal implementation details.