Save a checkpoint to the `run_dir` only containing the state_dicts for trainable parameters by default.
(
self,
run_dir: Path,
global_step: int,
epoch: int,
train_loss: Optional[float] = None,
only_trainable: bool = True,
)
| 250 | dist.barrier() |
| 251 | |
| 252 | def save_checkpoint( |
| 253 | self, |
| 254 | run_dir: Path, |
| 255 | global_step: int, |
| 256 | epoch: int, |
| 257 | train_loss: Optional[float] = None, |
| 258 | only_trainable: bool = True, |
| 259 | ) -> None: |
| 260 | """Save a checkpoint to the `run_dir` only containing the state_dicts for trainable parameters by default.""" |
| 261 | assert isinstance(self.vlm, FSDP), "FSDPStrategy.save_checkpoint assumes VLM is already wrapped in FSDP!" |
| 262 | |
| 263 | # Summon Full State Dictionary =>> Reconstitute from Shards |
| 264 | with FSDP.state_dict_type(self.vlm, self.fsdp_state_dict_type, self.fsdp_save_policy): |
| 265 | full_vlm_state_dict = self.vlm.state_dict() |
| 266 | model_state_dicts = { |
| 267 | mkey: OrderedDict() for mkey in (self.trainable_module_keys if only_trainable else self.all_module_keys) |
| 268 | } |
| 269 | |
| 270 | # Iterate through `full_vlm_state_dict` and split `mkey.{full_dotted_path}` -> `mkey: {full_dotted_path}` |
| 271 | for key, param in full_vlm_state_dict.items(): |
| 272 | for mkey in model_state_dicts: |
| 273 | if key.startswith(mprefix := f"{mkey}."): |
| 274 | model_state_dicts[mkey][key.removeprefix(mprefix)] = param |
| 275 | |
| 276 | # Save on rank zero *only* |
| 277 | if overwatch.is_rank_zero(): |
| 278 | checkpoint_dir = run_dir / "checkpoints" |
| 279 | if train_loss is None: |
| 280 | checkpoint_path = checkpoint_dir / f"step-{global_step:06d}-epoch-{epoch:02d}-loss=inf.pt" |
| 281 | else: |
| 282 | checkpoint_path = ( |
| 283 | checkpoint_dir / f"step-{global_step:06d}-epoch-{epoch:02d}-loss={train_loss:.4f}.pt" |
| 284 | ) |
| 285 | |
| 286 | # Save Checkpoint & Copy Latest to `latest-checkpoint.pt` |
| 287 | torch.save({"model": model_state_dicts}, checkpoint_path) |
| 288 | |
| 289 | # TODO (siddk) :: This breaks w/ Sagemaker default permissions (root vs. <user>)... skip? |
| 290 | # shutil.copy(checkpoint_path, checkpoint_dir / "latest-checkpoint.pt") |
| 291 | |
| 292 | def run_setup(self, run_dir: Path, n_train_examples: int) -> None: |
| 293 | # Iteratively Assemble FSDP Wrapping Policy by fetching the wrapping policies for each backbone/constituent |
no test coverage detected