CoolFace
Apppublic

ALSv/self-forcing

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
distributed.py126 linesDownload Raw Back to utils
1from datetime import timedelta2from functools import partial3import os4import torch5import torch.distributed as dist6from torch.distributed.fsdp import FullStateDictConfig, FullyShardedDataParallel as FSDP, MixedPrecision, ShardingStrategy, StateDictType7from torch.distributed.fsdp.api import CPUOffload8from torch.distributed.fsdp.wrap import size_based_auto_wrap_policy, transformer_auto_wrap_policy9 10 11def fsdp_state_dict(model):12    fsdp_fullstate_save_policy = FullStateDictConfig(13        offload_to_cpu=True, rank0_only=True14    )15    with FSDP.state_dict_type(16        model, StateDictType.FULL_STATE_DICT, fsdp_fullstate_save_policy17    ):18        checkpoint = model.state_dict()19 20    return checkpoint21 22 23def fsdp_wrap(module, sharding_strategy="full", mixed_precision=False, wrap_strategy="size", min_num_params=int(5e7), transformer_module=None, cpu_offload=False):24    if mixed_precision:25        mixed_precision_policy = MixedPrecision(26            param_dtype=torch.bfloat16,27            reduce_dtype=torch.float32,28            buffer_dtype=torch.float32,29            cast_forward_inputs=False30        )31    else:32        mixed_precision_policy = None33 34    if wrap_strategy == "transformer":35        auto_wrap_policy = partial(36            transformer_auto_wrap_policy,37            transformer_layer_cls=transformer_module38        )39    elif wrap_strategy == "size":40        auto_wrap_policy = partial(41            size_based_auto_wrap_policy,42            min_num_params=min_num_params43        )44    else:45        raise ValueError(f"Invalid wrap strategy: {wrap_strategy}")46 47    os.environ["NCCL_CROSS_NIC"] = "1"48 49    sharding_strategy = {50        "full": ShardingStrategy.FULL_SHARD,51        "hybrid_full": ShardingStrategy.HYBRID_SHARD,52        "hybrid_zero2": ShardingStrategy._HYBRID_SHARD_ZERO2,53        "no_shard": ShardingStrategy.NO_SHARD,54    }[sharding_strategy]55 56    module = FSDP(57        module,58        auto_wrap_policy=auto_wrap_policy,59        sharding_strategy=sharding_strategy,60        mixed_precision=mixed_precision_policy,61        device_id=torch.cuda.current_device(),62        limit_all_gathers=True,63        use_orig_params=True,64        cpu_offload=CPUOffload(offload_params=cpu_offload),65        sync_module_states=False  # Load ckpt on rank 0 and sync to other ranks66    )67    return module68 69 70def barrier():71    if dist.is_initialized():72        dist.barrier()73 74 75def launch_distributed_job(backend: str = "nccl"):76    rank = int(os.environ["RANK"])77    local_rank = int(os.environ["LOCAL_RANK"])78    world_size = int(os.environ["WORLD_SIZE"])79    host = os.environ["MASTER_ADDR"]80    port = int(os.environ["MASTER_PORT"])81 82    if ":" in host:  # IPv683        init_method = f"tcp://[{host}]:{port}"84    else:  # IPv485        init_method = f"tcp://{host}:{port}"86    dist.init_process_group(rank=rank, world_size=world_size, backend=backend,87                            init_method=init_method, timeout=timedelta(minutes=30))88    torch.cuda.set_device(local_rank)89 90 91class EMA_FSDP:92    def __init__(self, fsdp_module: torch.nn.Module, decay: float = 0.999):93        self.decay = decay94        self.shadow = {}95        self._init_shadow(fsdp_module)96 97    @torch.no_grad()98    def _init_shadow(self, fsdp_module):99        from torch.distributed.fsdp import FullyShardedDataParallel as FSDP100        with FSDP.summon_full_params(fsdp_module, writeback=False):101            for n, p in fsdp_module.module.named_parameters():102                self.shadow[n] = p.detach().clone().float().cpu()103 104    @torch.no_grad()105    def update(self, fsdp_module):106        d = self.decay107        from torch.distributed.fsdp import FullyShardedDataParallel as FSDP108        with FSDP.summon_full_params(fsdp_module, writeback=False):109            for n, p in fsdp_module.module.named_parameters():110                self.shadow[n].mul_(d).add_(p.detach().float().cpu(), alpha=1. - d)111 112    # Optional helpers ---------------------------------------------------113    def state_dict(self):114        return self.shadow            # picklable115 116    def load_state_dict(self, sd):117        self.shadow = {k: v.clone() for k, v in sd.items()}118 119    def copy_to(self, fsdp_module):120        # load EMA weights into an (unwrapped) copy of the generator121        from torch.distributed.fsdp import FullyShardedDataParallel as FSDP122        with FSDP.summon_full_params(fsdp_module, writeback=True):123            for n, p in fsdp_module.module.named_parameters():124                if n in self.shadow:125                    p.data.copy_(self.shadow[n].to(p.dtype, device=p.device))126