Skip to content

Commit 21f76b3

Browse files
committed
Return was_restored flag from setup_training_state to fix standalone checkpointer restoration
1 parent 131fbf5 commit 21f76b3

7 files changed

Lines changed: 31 additions & 41 deletions

File tree

src/maxtext/checkpoint_conversion/standalone_scripts/convert_gpt3_ckpt_from_paxml.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def init_state_fn():
117117
cfg.checkpoint_period,
118118
)
119119

120-
state, _, _, _ = maxtext_utils.setup_training_state(None, cfg, mesh, checkpoint_manager, init_state_fn)
120+
state, _, _, _, _ = maxtext_utils.setup_training_state(None, cfg, mesh, checkpoint_manager, init_state_fn)
121121
max_logging.log("start")
122122
max_utils.print_mem_stats("After params initialized")
123123

src/maxtext/experimental/rl/grpo_trainer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,7 @@ def init_state_fn():
864864

865865
with maybe_record_goodput(recorder, GoodputEvent.TRAINING_PREPARATION):
866866
data_iterator = grpo_input_pipeline.create_data_iterator(config_inference, inference_mesh)
867-
state, _, state_mesh_shardings, data_iterator = maxtext_utils.setup_training_state(
867+
state, _, state_mesh_shardings, data_iterator, _ = maxtext_utils.setup_training_state(
868868
data_iterator, config, mesh, checkpoint_manager, init_state_fn
869869
)
870870

src/maxtext/utils/generate_param_only_checkpoint.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ def init_state_fn():
167167
tx = optimizers.get_optimizer(config, learning_rate_schedule)
168168
init_state_fn = functools.partial(maxtext_utils.init_initial_state, model, tx, config, True, rng)
169169

170-
state, state_mesh_notations, state_mesh_shardings, _ = maxtext_utils.setup_training_state(
170+
state, state_mesh_notations, state_mesh_shardings, _, _ = maxtext_utils.setup_training_state(
171171
None, config, mesh, checkpoint_manager, init_state_fn
172172
)
173173
if config.pure_nnx:
@@ -400,13 +400,9 @@ def generate_decode_checkpoint(config):
400400
training_state, training_state_annotations = _read_train_checkpoint(config, checkpoint_manager, mesh)
401401
if config.pure_nnx:
402402
# NNX state is a flat nnx.State; opt_state lives under the optimizer sub-state.
403-
assert (
404-
training_state.optimizer.opt_state
405-
), "missing opt_state in training checkpoint"
403+
assert training_state.optimizer.opt_state, "missing opt_state in training checkpoint"
406404
else:
407-
assert (
408-
training_state.opt_state != {}
409-
), "missing opt_state in training checkpoint"
405+
assert training_state.opt_state != {}, "missing opt_state in training checkpoint"
410406

411407
_possibly_unroll_params(config, training_state, training_state_annotations, mesh)
412408

src/maxtext/utils/maxtext_utils.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,7 +1392,9 @@ def get_abstract_param(model, config):
13921392
{"params": key, "dropout": key, "aqt": key},
13931393
np.ones(input_shape, dtype=jnp.int32),
13941394
np.ones(input_shape, dtype=jnp.int32),
1395-
encoder_images=np.ones(image_shape, dtype=jnp.int32) if config.use_multimodal else None, # pyrefly: ignore[no-matching-overload]
1395+
encoder_images=np.ones(image_shape, dtype=jnp.int32)
1396+
if config.use_multimodal
1397+
else None, # pyrefly: ignore[no-matching-overload]
13961398
encoder_audios=np.ones(audio_shape, dtype=jnp.float32) if config.use_audio else None,
13971399
)
13981400
return abstract_vars
@@ -1413,7 +1415,7 @@ def setup_decode_state(config, mesh, checkpoint_manager, init_state_fn):
14131415
if not config.load_parameters_path:
14141416
# generate random params
14151417
max_logging.log("No decode checkpoint specified - generating random weights.")
1416-
state, state_mesh_annotations, _, _ = setup_initial_state(
1418+
state, state_mesh_annotations, _, _, _ = setup_initial_state(
14171419
None, config, mesh, checkpoint_manager, init_state_fn, False
14181420
)
14191421
else:
@@ -1468,6 +1470,9 @@ def setup_initial_state(
14681470
Returns:
14691471
train_state: the initialized train state. For NNX, this is a TrainStateNNX instance
14701472
state_mesh_annotations: the mesh annotations for the train state
1473+
state_mesh_shardings: the mesh shardings for the train state
1474+
data_iterator: the updated data iterator
1475+
was_restored: True if state or params were restored from checkpoint, False if freshly initialized
14711476
"""
14721477

14731478
unboxed_abstract_state, state_mesh_annotations, state_mesh_shardings = get_abstract_state(
@@ -1493,6 +1498,8 @@ def setup_initial_state(
14931498
expansion_factor_real_data=config.expansion_factor_real_data,
14941499
maxtext_config=config,
14951500
)
1501+
# Partial or fully restored
1502+
was_restored = bool(restored is not None or raw_params is not None)
14961503

14971504
if restored:
14981505
if isinstance(
@@ -1548,7 +1555,7 @@ def _merge_params(p_raw, p_init):
15481555
state = state.replace(params=raw_params)
15491556
if not config.pure_nnx:
15501557
state = max_utils.unbox_logicallypartioned(state)
1551-
return state, state_mesh_annotations, state_mesh_shardings, data_iterator
1558+
return state, state_mesh_annotations, state_mesh_shardings, data_iterator, was_restored
15521559

15531560

15541561
def get_logical_annotations(config, mesh, init_state_fn):

src/maxtext/utils/standalone_checkpointer.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
from absl import app
2727
from flax import nnx
28-
from flax.linen import partitioning as nn_partitioning
2928
import jax
3029
from jax import numpy as jnp
3130
from maxtext.configs import pyconfig
@@ -69,44 +68,34 @@ def init_state_fn():
6968
mesh = model.mesh
7069
_, tx = train_utils.create_training_optimizer(config, model)
7170
init_state_fn = partial(maxtext_utils.init_initial_state, model, tx, config, True, init_rng)
71+
7272
checkpoint_manager = train_utils.create_checkpoint_manager(config, mesh, init_state_fn)
7373

74-
unboxed_abstract_state, _, _ = maxtext_utils.get_abstract_state(config, mesh, init_state_fn, is_training=True)
7574
# A barrier to sync all hosts before starting to restore checkpoint
7675
jax.experimental.multihost_utils.sync_global_devices("Barrier before load")
77-
checkpoint_load_start = datetime.datetime.now()
78-
with nn_partitioning.axis_rules(config.logical_axis_rules):
79-
state, _ = checkpointing.load_state_if_possible(
80-
checkpoint_manager,
81-
None,
82-
config.load_parameters_path,
83-
config.load_full_state_path,
84-
config.checkpoint_storage_concurrent_gb,
85-
unboxed_abstract_state,
86-
use_ocdbt=config.checkpoint_storage_use_ocdbt,
87-
use_zarr3=config.checkpoint_storage_use_zarr3,
88-
)
89-
if state:
90-
state = state["items"]
9176

77+
checkpoint_load_start = datetime.datetime.now()
78+
# Delegate checkpoint restoration or state initialization to setup_training_state
79+
state, _, _, _, was_restored = maxtext_utils.setup_training_state(None, config, mesh, checkpoint_manager, init_state_fn)
9280
jax.block_until_ready(state)
9381
checkpoint_load_end = datetime.datetime.now()
94-
if state is not None: # Checkpoint was available for restore
82+
83+
if was_restored:
9584
if jax.process_index() == 0:
9685
max_logging.log(
9786
"STANDALONE CHECKPOINTER : Checkpoint restored in :" f" {checkpoint_load_end - checkpoint_load_start}"
9887
)
99-
else: # Checkpoint was unavailable, state needs to be initialized
100-
state, _, _, _ = maxtext_utils.setup_training_state(None, config, mesh, checkpoint_manager, init_state_fn)
101-
state = add_entropy_to_checkpoint(state)
88+
else: # Checkpoint was unavailable, fresh state needs to be perturbed with entropy
89+
state = add_entropy_to_checkpoint(state)
10290

10391
start_step = get_first_step(model, state) # this is the start_step for training
10492
for step in np.arange(start_step, config.steps):
10593
if checkpoint_manager is not None:
10694
start_time = datetime.datetime.now()
10795
# A barrier to sync all hosts before starting to save checkpoint
10896
jax.experimental.multihost_utils.sync_global_devices("Barrier before save")
109-
if checkpointing.save_checkpoint(checkpoint_manager, int(step), state):
97+
state_to_save = train_state_nnx.to_linen_checkpoint_dict(state.to_pure_dict()) if config.pure_nnx else state
98+
if checkpointing.save_checkpoint(checkpoint_manager, int(step), state_to_save):
11099
checkpoint_manager.wait_until_finished()
111100
end_time = datetime.datetime.now()
112101
if jax.process_index() == 0:

src/maxtext/utils/train_utils.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ def create_train_state_fn():
299299
# Create data_loader AFTER reordering wrapper is applied
300300
data_loader = create_dataloader(config, mesh, data_iterator, recorder, rampup_manager)
301301

302-
state, _, state_mesh_shardings, data_iterator = maxtext_utils.setup_training_state(
302+
state, _, state_mesh_shardings, data_iterator, _ = maxtext_utils.setup_training_state(
303303
data_iterator, config, mesh, checkpoint_manager, init_state_fn
304304
)
305305
if config.pure_nnx:
@@ -321,11 +321,7 @@ def create_train_state_fn():
321321
state, outer_opt_state_sharding = diloco.build_diloco_state(config, lambda: state, mesh=mesh)
322322

323323
# create state_mesh_shardings for the DilocoState
324-
step_mesh = (
325-
state_mesh_shardings.optimizer.step.mesh
326-
if config.pure_nnx
327-
else state_mesh_shardings.step.mesh
328-
)
324+
step_mesh = state_mesh_shardings.optimizer.step.mesh if config.pure_nnx else state_mesh_shardings.step.mesh
329325
inner_state_shardings = diloco.add_diloco_to_sharding(state_mesh_shardings)
330326
state_mesh_shardings = diloco.DiLoCoTrainState(
331327
inner_state_shardings,

tests/unit/maxtext_utils_test.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,8 @@ def create_train_state_fn():
387387
init_state_fn = create_train_state_fn
388388
else:
389389
init_state_fn = functools.partial(maxtext_utils.init_initial_state, self.model, tx, self.config, True, rng)
390-
state, _, _, _ = maxtext_utils.setup_initial_state(None, self.config, self.mesh, None, init_state_fn)
390+
state, _, _, _, was_restored = maxtext_utils.setup_initial_state(None, self.config, self.mesh, None, init_state_fn)
391+
self.assertFalse(was_restored)
391392
if self.config.pure_nnx:
392393
self.assertIsNotNone(state.optimizer)
393394
else:
@@ -1413,7 +1414,8 @@ def create_train_state_fn():
14131414
True,
14141415
rng,
14151416
)
1416-
state, _, _, _ = maxtext_utils.setup_training_state(None, self.config, self.mesh, None, init_state_fn)
1417+
state, _, _, _, was_restored = maxtext_utils.setup_training_state(None, self.config, self.mesh, None, init_state_fn)
1418+
self.assertFalse(was_restored)
14171419
if self.config.pure_nnx:
14181420
self.assertIsNotNone(state.optimizer)
14191421
else:

0 commit comments

Comments
 (0)