Skip to content

Release 2026-08-19 (i4 02f21ec8) - #208

Merged
lfengad merged 3 commits into
mainfrom
release/2026-08-19-02f21ec8
Aug 20, 2026
Merged

Release 2026-08-19 (i4 02f21ec8)#208
lfengad merged 3 commits into
mainfrom
release/2026-08-19-02f21ec8

Conversation

@yy-code-nv

Copy link
Copy Markdown
Collaborator

Automated release from i4.

_source_commit: 02f21ec8097056f5b94570463c41fc7dcf958934-dirty
_dest_commit (base): c14617c2bc93dacbf69674fb964eec93182933d9

_source_commit: 02f21ec8097056f5b94570463c41fc7dcf958934-dirty
_dest_commit:   c14617c
lfengad added a commit that referenced this pull request Aug 19, 2026
Lands ahead of the i4 sync in #208, which flips `ParallelDims.dp_enabled`
to unconditionally True under training semantics so the FSDP2 wrap always
has somewhere to install the mixed-precision policy. `build_meshes` then
always builds the dp mesh, even at world_size 1, and `init_device_mesh`
implicitly calls `init_process_group()`, which needs an `env://`
rendezvous.

`Cosmos3OmniModel` is built for inference and export only, including
plain single-process runs with no torchrun rendezvous: the checkpoint
conversion scripts (`convert_model_to_dcp`,
`convert_model_to_vlm_safetensors`, `_convert_model_to_diffusers`) reach
it through `from_pretrained_dcp`'s default `ParallelismConfig()`, and
`export_model` constructs it directly from a training config. Both
inherit training semantics, and on #208 both died with

    ValueError: Error initializing torch.distributed using env://
    rendezvous: environment variable RANK expected, but not set

Pin `enable_inference_mode` alongside the other training-only features
the wrapper already disables. This is a no-op on main, where a
single-rank `dp_replicate=1, dp_shard=1` already leaves `dp_enabled`
False, and real inference paths are unaffected either way:
`OmniInference._get_parallelism_config` already passes True.

Also teach `omni_mot_model_test.py`'s stand-in config about
`lidar_tokenizer`, which `set_up_tokenizers` reads as of #208. The extra
`SimpleNamespace` attribute is inert against main's tokenizer setup.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lfengad added a commit that referenced this pull request Aug 19, 2026
The i4 sync in #208 drops `rank0_only=False` from `IterSpeed.on_training_step_end`,
so the per-iteration line is emitted by rank 0 alone and no longer carries the
`[RANK n]` prefix:

    [RANK 0] Iteration 1: Hit counter: 1/50 | Loss: 0.2204 | Time: 75.78s   (before)
             Iteration 1: Hit counter: 1/50 | Loss: 0.2204 | Time: 76.09s   (after)

Both OSS-only test files anchor their loss regex on that prefix, so they parse
an empty series and fail before reaching what they actually assert:

    nano_training_smoke_test: expected 5 rank-0 losses, parsed []
    launch_regression_test:   No loss/grad-norm pairs found (losses=0, grads=10)

Make the prefix an optional capture and keep a match only when the rank is
absent (already rank-0-only) or zero, so one entry per step is parsed under
either format rather than nothing or every rank's copy. Verified against both
real CI logs: 5/5 and 10/10 rank-0 values, matching the values the green
baseline parsed from the prefixed format.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lfengad added a commit that referenced this pull request Aug 19, 2026
…esh (#211)

Unblocks the five red checks on #208 (the 2026-08-19 i4 sync). Lands on
`main` first; #208 then picks it up by updating/rebasing its release
branch, which is also where the fix actually gets exercised — the GPU
suite only triggers on `pull_request: branches: [main]`, so on this PR
it runs against code that does not yet contain the i4 change and can
only show the fix is inert here.

All three touched files are OSS-only (none appear in
`.file_mapping.json`), so the next i4 release will not clobber them and
no imaginaire4 MR is needed.

## Root cause 1 — single-process scripts are forced to build a device
mesh

#208 flips `ParallelDims.dp_enabled` to `True` unconditionally under
training semantics, so the FSDP2 wrap always has somewhere to install
the `MixedPrecisionPolicy`. As a consequence `build_meshes()` always
builds the dp mesh, even at `world_size == 1`, and `init_device_mesh`
implicitly calls `init_process_group()`, which needs an `env://`
rendezvous. Reproduced directly against `ParallelDims` on #208's tree:

```
enable_inference_mode=False -> dp_enabled=True  -> ValueError: environment variable RANK expected, but not set
enable_inference_mode=True  -> dp_enabled=False -> no mesh built, no process group needed
```

`Cosmos3OmniModel` is only ever built for inference and export,
including plain single-process runs with no torchrun rendezvous:

- the conversion scripts (`convert_model_to_dcp`,
`convert_model_to_vlm_safetensors`, `_convert_model_to_diffusers`) reach
it via `from_pretrained_dcp`'s default `ParallelismConfig()`, which is
training semantics;
- `export_model` constructs it directly from a training config.

`convert_model_to_dcp.sh` even runs with `CUDA_VISIBLE_DEVICES=` and
`COSMOS_DEVICE=cpu`, so there is no rendezvous to inherit. This one
cause accounts for `generator-training-regression`,
`reasoner-training-regression`, `reasoner-inference-smoke`,
`training-smoke`, and `unittest`'s
`scripts/_test.py::test_level_0[convert_model_to_dcp]` on #208 — all
failed in fixture setup, not in the code under test.

The fix pins `enable_inference_mode = True` in
`Cosmos3OmniModel.__init__`, next to the `ema.enabled` /
`activation_checkpointing.mode` overrides the wrapper already applies
for the same reason. Doing it in `__init__` rather than in
`from_pretrained_dcp`'s default also covers `export_model`'s direct
construction. Real inference is unaffected:
`OmniInference._get_parallelism_config` already passes
`enable_inference_mode=True`. On `main` it is a no-op, since a
single-rank `dp_replicate=1, dp_shard=1` already leaves `dp_enabled`
False.

## Root cause 2 — OSS-only test does not know about the new LiDAR config
field

As of #208 `set_up_tokenizers` reads `config.lidar_tokenizer`.
`omni_mot_model_test.py` is OSS-only and builds its config from
`SimpleNamespace`, so it raised `AttributeError: 'types.SimpleNamespace'
object has no attribute 'lidar_tokenizer'`. Added `lidar_tokenizer=None`
to both stand-in configs; the extra attribute is inert against main's
tokenizer setup.

## Verification

- `pytest cosmos_framework/model/generator/omni_mot_model_test.py` — 2
failed then 2 passed on #208's tree; 2 passed on this branch.
- Root cause 1 reproduced directly against `ParallelDims` (output quoted
above). The end-to-end `convert_model_to_dcp` run is left to #208's GPU
suite once it picks this up.
- `ruff check` and `ruff format --check` clean on the three files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lfengad
lfengad enabled auto-merge (squash) August 19, 2026 16:42
The VFM moved onto FSDP2 mixed precision. What changed is which layer owns the
FP32 master, not whether one exists:

  before: sharded parameter BF16; FusedAdam holds the master itself, because
          ``_needs_master_weights`` is True for a BF16 parameter, and dispatches
          to TE's ``multi_tensor_adam_capturable_master``.
  after:  ``fsdp_master_dtype`` (until now VLM-only -- ``set_up_model`` built the
          net at ``self.precision``) makes the sharded parameter FP32 and installs
          a MixedPrecisionPolicy that down-casts to BF16 for compute, so FusedAdam
          needs no master and takes the plain capturable path.

Both arrangements accumulate in FP32 and run forward/backward in BF16, so they
are equivalent on paper. The series shifts anyway because the implementations
differ: a different TE kernel, and the BF16 down-cast moving from the optimizer
to the FSDP all-gather. This is also why ``dp_enabled`` became unconditional
under training semantics -- a degree-1 run still needs the wrap that carries the
policy.

    got     : [0.2242, 0.2141, 0.2428, 0.2259, 0.2607, 0.2553, 0.3318, 0.2252, 0.2035, 0.2609]
    expected: [0.2242, 0.2141, 0.2429, 0.2259, 0.2608, 0.2555, 0.332,  0.2256, 0.2041, 0.2621]

iter-0 is unchanged (forward only, and an FP32 master loaded from BF16 weights
down-casts back losslessly); the gap grows monotonically to 1.2e-3 by iter 9,
past the 1e-3 tolerance. Two independent runs of this build agree to within
2e-4, so the shift is systematic rather than run-to-run noise, and the refreshed
series accepts both while still rejecting the pre-mixed-precision one. The
tolerance is left at 1e-3 rather than widened, so the guard keeps its
sensitivity to a real regression.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lfengad
lfengad merged commit cb76f47 into main Aug 20, 2026
9 checks passed
@lfengad
lfengad deleted the release/2026-08-19-02f21ec8 branch August 20, 2026 06:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants