2323from transformers import AutoConfig , AutoTokenizer
2424from transformers .tokenization_utils_base import PreTrainedTokenizerBase
2525
26- from nemo_rl .algorithms .grpo import _should_use_async_rollouts , refit_policy_generation
26+ from nemo_rl .algorithms .grpo import _should_use_async_rollouts
27+ from nemo_rl .weight_sync import WeightSynchronizer , create_weight_synchronizer
2728from nemo_rl .algorithms .loss import (
2829 DistillationLossConfig ,
2930 DistillationLossDataDict ,
@@ -165,6 +166,7 @@ def setup(
165166 ColocatablePolicyInterface , # student_policy
166167 ColocatablePolicyInterface , # teacher_policy
167168 Optional [GenerationInterface ], # student_generation
169+ Optional [WeightSynchronizer ], # weight_sync
168170 StatefulDataLoader ,
169171 Optional [StatefulDataLoader ],
170172 DistillationLossFn ,
@@ -176,7 +178,7 @@ def setup(
176178 """Main entry point for distillation algorithm.
177179
178180 Returns:
179- tuple of student_policy, teacher_policy, student_generation,
181+ tuple of student_policy, teacher_policy, student_generation, weight_sync,
180182 train_dataloader, val_dataloader,
181183 loss_fn, logger, checkpointer, distillation_save_state, master_config
182184 """
@@ -455,26 +457,18 @@ def setup(
455457 init_reference_model = False ,
456458 )
457459
460+ # Create weight synchronizer and initialize communication channels
461+ weight_sync : Optional [WeightSynchronizer ] = None
458462 if student_generation is not None :
459- state_dict_info = student_policy .prepare_refit_info ()
460- student_generation .prepare_refit_info (state_dict_info )
461-
462- # if it is not colocated inference, initialize collective communication for update weights
463- if not colocated_inference :
464- ip , port = train_cluster .get_master_address_and_port ()
465- print (f"Using ip: { ip } , port: { port } for collective communication" , flush = True )
466- train_world_size = train_cluster .world_size ()
467- # inference cluster + head node of the train cluster
468- world_size = train_world_size + inference_nodes * inference_gpus_per_node
469- # init collective
470- futures_train = student_policy .init_collective (
471- ip , port , world_size , train_world_size = train_world_size
463+ weight_sync = create_weight_synchronizer (
464+ policy = student_policy ,
465+ generation = student_generation ,
466+ generation_backend = backend ,
467+ colocated = colocated_inference ,
468+ train_cluster = train_cluster if not colocated_inference else None ,
469+ inference_cluster = inference_cluster if not colocated_inference else None ,
472470 )
473- futures_inference = student_generation .init_collective (
474- ip , port , world_size , train_world_size = train_world_size
475- ) # type: ignore
476- # wait for all futures to complete
477- ray .get (futures_train + futures_inference )
471+ weight_sync .init_communicator ()
478472
479473 loss_fn = DistillationLossFn (loss_config )
480474
@@ -486,6 +480,7 @@ def setup(
486480 student_policy ,
487481 teacher_policy ,
488482 student_generation ,
483+ weight_sync ,
489484 dataloader ,
490485 val_dataloader ,
491486 loss_fn ,
@@ -515,6 +510,7 @@ def distillation_train(
515510 checkpointer : CheckpointManager ,
516511 distillation_save_state : DistillationSaveState ,
517512 master_config : MasterConfig ,
513+ weight_sync : Optional [WeightSynchronizer ] = None ,
518514) -> None :
519515 """Run Distillation training algorithm."""
520516 timer = Timer ()
@@ -524,13 +520,10 @@ def distillation_train(
524520 )
525521 timeout .start_iterations ()
526522
527- NEED_REFIT = True
528523 # If student_generation is None, use the student_policy as the generation interface (megatron framework backend)
529524 if student_generation is None :
530525 student_generation = student_policy # type: ignore
531- NEED_REFIT = False
532- POLICY_GENERATION_STALE = True # tracks if generation needs a refit before running
533- assert student_generation is not None
526+ assert student_generation is not None # for mypy type check
534527
535528 # common config/state items
536529 current_epoch = distillation_save_state ["current_epoch" ] # current epoch
@@ -556,11 +549,8 @@ def distillation_train(
556549 # Run validation at the start if configured
557550 if val_at_start and total_steps == 0 :
558551 print ("\n 🔍 Running initial validation..." , flush = True )
559- if NEED_REFIT and POLICY_GENERATION_STALE :
560- refit_policy_generation (
561- student_policy , student_generation , colocated_inference
562- )
563- POLICY_GENERATION_STALE = False
552+ if weight_sync is not None and weight_sync .is_stale :
553+ weight_sync .sync_weights ()
564554 else :
565555 student_generation .prepare_for_generation ()
566556 val_metrics , validation_timings = validate (
@@ -611,14 +601,8 @@ def distillation_train(
611601 flush = True ,
612602 )
613603 with timer .time ("prepare_for_generation" ):
614- if NEED_REFIT and POLICY_GENERATION_STALE :
615- refit_policy_generation (
616- student_policy ,
617- student_generation ,
618- colocated_inference ,
619- timer = timer ,
620- )
621- POLICY_GENERATION_STALE = False
604+ if weight_sync is not None and weight_sync .is_stale :
605+ weight_sync .sync_weights (timer = timer )
622606 else :
623607 student_generation .prepare_for_generation ()
624608
@@ -712,7 +696,8 @@ def distillation_train(
712696 with timer .time ("training_prep" ):
713697 teacher_policy .offload_after_refit ()
714698 student_policy .prepare_for_training () # set model train and reload optim to GPU
715- POLICY_GENERATION_STALE = True
699+ if weight_sync is not None :
700+ weight_sync .mark_stale ()
716701
717702 print ("▶ Training policy..." , flush = True )
718703 with timer .time ("policy_training" ):
@@ -731,11 +716,8 @@ def distillation_train(
731716 if (val_period > 0 and (total_steps + 1 ) % val_period == 0 ) or (
732717 val_at_end and is_last_step
733718 ):
734- if NEED_REFIT and POLICY_GENERATION_STALE :
735- refit_policy_generation (
736- student_policy , student_generation , colocated_inference
737- )
738- POLICY_GENERATION_STALE = False
719+ if weight_sync is not None and weight_sync .is_stale :
720+ weight_sync .sync_weights ()
739721 else :
740722 student_generation .prepare_for_generation ()
741723 val_metrics , validation_timings = validate (
0 commit comments