Skip to content

Commit 4688708

Browse files
committed
add ckpt loading for dist trainer
1 parent d281324 commit 4688708

1 file changed

Lines changed: 32 additions & 12 deletions

File tree

alf/algorithms/distributed_off_policy_algorithm.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -503,27 +503,42 @@ def _wait_unroller_registration():
503503
thread.daemon = True
504504
thread.start()
505505

506-
def _create_data_receiver_subprocess(self):
507-
"""Create a process to receive experience data from unrollers.
506+
def _create_replay_buffer_sample_experience(self):
507+
"""
508+
Create a sample experience used to initialize the replay buffer.
508509
"""
509-
# First create the replay buffer in the main process. For this, we need
510-
# to create a dummy experience to set up the replay buffer.
511510
time_step = self._env.current_time_step()
512511
rollout_state = self.get_initial_rollout_state(self._env.batch_size)
513512
alg_step = self.rollout_step(time_step, rollout_state)
514513
exp = make_experience(time_step, alg_step, rollout_state)
515-
exp = alf.utils.common.prune_exp_replay_state(exp,
516-
self._use_rollout_state,
517-
self.rollout_state_spec,
518-
self.train_state_spec)
514+
return alf.utils.common.prune_exp_replay_state(exp,
515+
self._use_rollout_state,
516+
self.rollout_state_spec,
517+
self.train_state_spec)
519518

520-
# enable multi_processing in replay_buffer here, because we need to
521-
# receive data in a subprocess and process the data in the main process.
519+
def _create_multiprocessing_replay_buffer(self):
520+
"""
521+
Create the replay buffer in shared memory.
522+
"""
522523
ctx = mp.get_context('spawn')
523-
self._set_replay_buffer(exp, mp_context=ctx)
524+
assert self._replay_buffer is None
525+
self._set_replay_buffer(self._create_replay_buffer_sample_experience(),
526+
mp_context=ctx)
524527
assert self._replay_buffer._allow_multiprocess, (
525528
"The replay buffer must allow multi-processing.")
526529

530+
def _create_data_receiver_subprocess(self):
531+
"""
532+
Create a process to receive experience data from unrollers.
533+
534+
The warm-up train_iter() creates the normal trainer replay buffer in
535+
multiprocessing form before checkpoint restore, so restored shards
536+
load directly into the buffer that the receiver subprocess will use.
537+
"""
538+
assert self._replay_buffer is not None
539+
assert self._replay_buffer._allow_multiprocess
540+
ctx = mp.get_context('spawn')
541+
527542
# start the data receiver subprocess
528543
# Need to create the subprocess with 'spawn' so that we can pass a Module
529544
# object to subprocess with tensors in shared memory.
@@ -545,8 +560,13 @@ def _train_iter_off_policy(self):
545560
if self._num_train_iters == 0:
546561
# First time will be called by ``Trainer._restore_checkpoint()``
547562
# where the ckpt (if any) will be loaded after this function.
563+
# Create the normal trainer replay buffer in multiprocessing form
564+
# before checkpoint load so replay data is restored directly into
565+
# it. Do not start the receiver subprocess yet; it should only
566+
# consume unroller data after checkpoint restore has completed.
567+
self._create_multiprocessing_replay_buffer()
548568
self._num_train_iters += 1
549-
return super()._train_iter_off_policy()
569+
return 0
550570

551571
if self._num_train_iters == 1:
552572
# Only open the unroller registration after we are sure that

0 commit comments

Comments
 (0)