7272 run_async_nemo_gym_rollout ,
7373 run_multi_turn_rollout ,
7474)
75+ from nemo_rl .models .generation .constants import SGLANG_BACKEND , VLLM_BACKEND
7576from nemo_rl .models .generation .interfaces import GenerationInterface
7677from nemo_rl .models .generation .sglang import SGLangConfig , SGLangGeneration
7778from nemo_rl .models .generation .vllm import VllmConfig , VllmGeneration
8889from nemo_rl .utils .nsys import maybe_gpu_profile_step
8990from nemo_rl .utils .timer import TimeoutChecker , Timer
9091from nemo_rl .utils .venvs import create_local_venv_on_each_node
92+ from nemo_rl .weight_sync import create_weight_synchronizer
9193
9294# ===============================================================================
9395# Configuration
@@ -1188,16 +1190,6 @@ def _create_advantage_estimator(master_config: MasterConfig):
11881190 return adv_estimator
11891191
11901192
1191- def _flatten_checkpoint_engine_metadata (metadata_results : list [Any ]) -> list [Any ]:
1192- metadata = []
1193- for worker_metadata in metadata_results :
1194- if isinstance (worker_metadata , list ):
1195- metadata .extend (worker_metadata )
1196- else :
1197- metadata .append (worker_metadata )
1198- return metadata
1199-
1200-
12011193def _get_enabled_checkpoint_engine_config (
12021194 checkpoint_engine_config : dict [str , Any ] | None ,
12031195) -> dict [str , Any ] | None :
@@ -1206,71 +1198,6 @@ def _get_enabled_checkpoint_engine_config(
12061198 return checkpoint_engine_config
12071199
12081200
1209- def _refit_policy_generation_with_checkpoint_engine (
1210- policy : ColocatablePolicyInterface ,
1211- policy_generation : GenerationInterface ,
1212- checkpoint_engine_config : dict [str , Any ],
1213- kv_scales : Optional [dict [str , float ]] = None ,
1214- ) -> bool :
1215- backend = checkpoint_engine_config ["backend" ]
1216- bucket_size_bytes = (
1217- checkpoint_engine_config ["update_weights_bucket_megabytes" ] * 1024 * 1024
1218- )
1219- engine_kwargs = checkpoint_engine_config ["engine_kwargs" ][backend ]
1220-
1221- try :
1222- init_futures = policy .init_checkpoint_engine (
1223- backend = backend ,
1224- bucket_size_bytes = bucket_size_bytes ,
1225- engine_kwargs = engine_kwargs ,
1226- ) + policy_generation .init_checkpoint_engine (
1227- backend = backend ,
1228- bucket_size_bytes = bucket_size_bytes ,
1229- engine_kwargs = engine_kwargs ,
1230- )
1231- ray .get (init_futures )
1232-
1233- policy_metadata = _flatten_checkpoint_engine_metadata (
1234- ray .get (policy .prepare_checkpoint_engine ())
1235- )
1236- generation_metadata = _flatten_checkpoint_engine_metadata (
1237- ray .get (policy_generation .prepare_checkpoint_engine ())
1238- )
1239-
1240- train_world_size = len (policy_metadata )
1241- rollout_world_size = len (generation_metadata )
1242- metadata = policy_metadata + generation_metadata
1243- ray .get (
1244- policy .init_checkpoint_engine_process_group (
1245- metadata = metadata ,
1246- train_world_size = train_world_size ,
1247- rollout_world_size = rollout_world_size ,
1248- )
1249- + policy_generation .init_checkpoint_engine_process_group (
1250- metadata = metadata ,
1251- train_world_size = train_world_size ,
1252- rollout_world_size = rollout_world_size ,
1253- )
1254- )
1255-
1256- futures_train = policy .send_weights_via_checkpoint_engine (kv_scales = kv_scales )
1257- futures_inference = policy_generation .update_weights_from_checkpoint_engine ()
1258- ray .get (futures_train )
1259- results = ray .get (futures_inference )
1260- return all (result for result in results if result is not None )
1261- finally :
1262- try :
1263- ray .get (
1264- policy .finalize_checkpoint_engine ()
1265- + policy_generation .finalize_checkpoint_engine ()
1266- )
1267- except Exception as finalize_error :
1268- warnings .warn (
1269- f"Failed to finalize checkpoint-engine refit state: { finalize_error } " ,
1270- RuntimeWarning ,
1271- )
1272-
1273-
12741201def refit_policy_generation (
12751202 policy : ColocatablePolicyInterface ,
12761203 policy_generation : GenerationInterface ,
@@ -1300,101 +1227,44 @@ def refit_policy_generation(
13001227 "policy.generation.checkpoint_engine.enabled."
13011228 )
13021229
1303- if colocated_inference :
1304- policy .offload_before_refit ()
1305- policy_generation .prepare_for_generation (tags = ["weights" ])
1230+ if colocated_inference or checkpoint_engine_config is not None :
1231+ generation_backend = (
1232+ SGLANG_BACKEND
1233+ if isinstance (policy_generation , SGLangGeneration )
1234+ else VLLM_BACKEND
1235+ )
1236+ weight_sync = create_weight_synchronizer (
1237+ policy = policy ,
1238+ generation = policy_generation ,
1239+ generation_backend = generation_backend ,
1240+ colocated = colocated_inference ,
1241+ refit_buffer_size_gb = _refit_buffer_size_gb ,
1242+ )
1243+ weight_sync .sync_weights (timer = timer , kv_scales = kv_scales )
1244+ return
13061245
1307- # Create a context manager that does nothing when timer is None
13081246 timer_context = (
13091247 timer .time ("prepare_for_generation/transfer_and_update_weights" )
13101248 if timer is not None
13111249 else nullcontext ()
13121250 )
13131251 with timer_context :
1314- # update weights
1315- update_success = False
1316- if colocated_inference :
1317- # get model param keys, which is grouped by size
1318- if _refit_buffer_size_gb is not None :
1319- buffer_size_bytes = _refit_buffer_size_gb * (1024 ** 3 )
1320- else :
1321- # Empirically sets ratio as 30% to maximize efficiency.
1322- # The remaining 70% is a necessary buffer reserved for the parameter all-gathering across the expert-parallelism dimension.
1323- memory_ratio = os .getenv ("NRL_REFIT_BUFFER_MEMORY_RATIO" , "0.3" )
1324- buffer_size_bytes = int (
1325- policy .get_free_memory_bytes () * float (memory_ratio )
1326- )
1327-
1328- if isinstance (policy_generation , SGLangGeneration ):
1329- sglang_url_to_gpu_uuids = (
1330- policy_generation .get_sglang_url_to_gpu_uuids ()
1331- )
1332- # Stream weights via HTTP
1333- flush_success = policy_generation .invalidate_kv_cache ()
1334- if not flush_success :
1335- print ("SGLang KV cache invalidation failed before weight update. " )
1336- futures_train = policy .stream_weights_via_http (
1337- sglang_url_to_gpu_uuids = sglang_url_to_gpu_uuids ,
1338- )
1339- # Wait for all workers to complete
1340- ray .get (futures_train )
1341- update_success = True
1342- else :
1343- # Original ZMQ IPC path for vLLM
1344- futures_train = policy .stream_weights_via_ipc_zmq (
1345- buffer_size_bytes = buffer_size_bytes
1346- )
1347- futures_inference = policy_generation .update_weights_via_ipc_zmq ()
1348- # wait for all futures to complete
1349- ray .get (futures_train )
1350- results = ray .get (futures_inference )
1351- update_success = all (result for result in results if result is not None )
1352- else :
1353- if checkpoint_engine_config is not None :
1354- if isinstance (policy_generation , SGLangGeneration ):
1355- raise NotImplementedError (
1356- "SGLang does not support checkpoint-engine non-colocated refit."
1357- )
1358- update_success = _refit_policy_generation_with_checkpoint_engine (
1359- policy ,
1360- policy_generation ,
1361- checkpoint_engine_config ,
1362- kv_scales = kv_scales ,
1363- )
1364- else :
1365- # update weights through nccl
1366- # SGLang haven't implemented non-colocated inference mode.
1367- if isinstance (policy_generation , SGLangGeneration ):
1368- raise NotImplementedError (
1369- "SGLang haven't implemented non-colocated inference mode. "
1370- )
1371- futures_train = policy .broadcast_weights_for_collective (
1372- kv_scales = kv_scales
1373- )
1374- futures_inference = policy_generation .update_weights_from_collective ()
1375- # wait for all futures to complete
1376- ray .get (futures_train )
1377- results = ray .get (futures_inference )
1378- update_success = all (result for result in results if result is not None )
1379-
1380- # check if update is successful
1381- if not update_success :
1382- if colocated_inference :
1383- error_tag = "cuda-ipc"
1384- elif checkpoint_engine_config is not None :
1385- error_tag = checkpoint_engine_config ["backend" ]
1386- else :
1387- error_tag = "nccl"
1388- error_message = (
1389- "❌ Error: Updating weights for the generation policy failed during refit.\n "
1390- f"This often indicates an issue with { error_tag } or "
1391- "a problem within the generation backend (e.g., vLLM worker).\n "
1252+ if isinstance (policy_generation , SGLangGeneration ):
1253+ raise NotImplementedError (
1254+ "SGLang haven't implemented non-colocated inference mode. "
13921255 )
1393- raise RuntimeError (error_message )
1256+ futures_train = policy .broadcast_weights_for_collective (kv_scales = kv_scales )
1257+ futures_inference = policy_generation .update_weights_from_collective ()
1258+ ray .get (futures_train )
1259+ results = ray .get (futures_inference )
1260+ update_success = all (result for result in results if result is not None )
13941261
1395- if colocated_inference :
1396- policy .offload_after_refit ()
1397- policy_generation .prepare_for_generation (tags = ["kv_cache" ])
1262+ if not update_success :
1263+ raise RuntimeError (
1264+ "❌ Error: Updating weights for the generation policy failed during refit.\n "
1265+ "This often indicates an issue with nccl or a problem within the "
1266+ "generation backend (e.g., vLLM worker).\n "
1267+ )
13981268
13991269
14001270def _log_mixed_rewards_and_advantages_information (
0 commit comments