Spaces:
Running on L40S
Running on L40S
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # SPDX-License-Identifier: OpenMDW-1.1 | |
| """FSDP2 wrapping for Cosmos3 VLM ``HFModel`` instances. | |
| Hosts the single VLM-specific ``parallelize`` entry point used by | |
| ``vlm_model.VLMModel._init_vlm``. Lives under ``projects/cosmos3/vfm/models/`` | |
| so the FSDP wrapping concern sits next to the model class it operates on | |
| (mirroring the layout of ``models/mot/parallelize_unified_mot.py`` for the | |
| MoT path). | |
| Pure parallelism plumbing — :class:`~projects.cosmos3.vfm.utils.parallelism.ParallelDims` | |
| and its meshes — stays in ``vfm/utils/parallelism.py``. | |
| """ | |
| from torch.distributed.fsdp import MixedPrecisionPolicy, fully_shard | |
| from cosmos_framework.utils import log | |
| from cosmos_framework.configs.base.defaults.parallelism import ( | |
| PRECISION_TO_TORCH_DTYPE, | |
| ParallelismConfig, | |
| ) | |
| from cosmos_framework.model.vfm.hf_model import HFModel | |
| from cosmos_framework.utils.vfm.parallelism import ParallelDims | |
| def parallelize( | |
| model: HFModel, | |
| parallel_dims: ParallelDims, | |
| parallelism_config: ParallelismConfig, | |
| precision: str, | |
| ) -> None: | |
| """Apply FSDP2 to an HFModel in-place. | |
| Uses torch.distributed.fsdp.fully_shard (FSDP2). Each transformer block is | |
| sharded individually for fine-grained memory savings; the outer model is then | |
| wrapped to cover remaining parameters (embeddings, layer norms, lm_head). | |
| Supported architectures: | |
| - Language models: ``inner.model.layers`` (standard HF LLM structure) | |
| - Vision-language models: additionally ``inner.visual.blocks`` (Qwen3-VL) | |
| No-op when FSDP is not needed (single-GPU or replicate-only). | |
| Args: | |
| model: HFModel instance (``model`` attribute must be on meta or CPU device). | |
| parallel_dims: ParallelDims with meshes already built via | |
| :meth:`ParallelDims.build_meshes`. | |
| parallelism_config: Source of FSDP master dtype (``fsdp_master_dtype``; | |
| threaded to ``MixedPrecisionPolicy.reduce_dtype``). | |
| precision: FSDP MixedPrecisionPolicy parameter dtype | |
| (``"bfloat16"``, ``"float16"``, or ``"float32"``). | |
| """ | |
| if not parallel_dims.dp_shard_enabled: | |
| # No shard axis: dp_shard <= 1. FSDP2 (fully_shard) has nothing to do. | |
| # For replicate-only (dp_replicate > 1, dp_shard == 1), use DDP outside | |
| # this function. | |
| log.info("parallelize: dp_shard <= 1 — skipping FSDP2 wrapping") | |
| return | |
| mp_policy = MixedPrecisionPolicy( | |
| param_dtype=PRECISION_TO_TORCH_DTYPE[precision], | |
| reduce_dtype=PRECISION_TO_TORCH_DTYPE[parallelism_config.fsdp_master_dtype], | |
| ) | |
| # 2-D (dp_replicate × dp_shard) mesh for HSDP, or 1-D dp_shard sub-mesh | |
| # for pure FSDP. In the overlay design cp does NOT fold into the FSDP | |
| # shard axis; cp/cfgp are handled by separate meshes. | |
| if parallel_dims.dp_replicate_enabled: | |
| fsdp_mesh = parallel_dims.dp_mesh | |
| else: | |
| fsdp_mesh = parallel_dims.dp_shard_mesh | |
| fsdp_kwargs = {"mesh": fsdp_mesh, "mp_policy": mp_policy} | |
| inner = model.model | |
| no_split_names = set(getattr(inner, "_no_split_modules", [])) | |
| wrapped = 0 | |
| for module in reversed(list(inner.modules())): | |
| if type(module).__name__ in no_split_names: | |
| fully_shard(module, **fsdp_kwargs) | |
| wrapped += 1 | |
| log.info(f"Wrapped {wrapped} sub-modules.") | |
| # Wrap the full inner model to cover remaining parameters | |
| # (embed_tokens, final layer norm, lm_head, visual projector stem, etc.) | |
| # NOTE: FSDP-2 CPU offload (offload_policy=CPUOffloadPolicy()) was never | |
| # wired through to any active recipe and the path was untested; see the | |
| # comment in vlm_model._init_vlm meta-materialize block (search for | |
| # "FSDP-2 CPU offload") for how to re-enable it. | |
| fully_shard(inner, **fsdp_kwargs) | |
| log.info("parallelize: FSDP2 applied to HFModel.model") | |