Skip to content

refactor(fsdp)(4.2/5): add per-parameter dtype patch - #100

Merged
Rockdu merged 22 commits into
radixark:mainfrom
Rockdu:refactor/fsdp-4.1-param-dtype-patch
Aug 8, 2026
Merged

refactor(fsdp)(4.2/5): add per-parameter dtype patch#100
Rockdu merged 22 commits into
radixark:mainfrom
Rockdu:refactor/fsdp-4.1-param-dtype-patch

Conversation

@Rockdu

@Rockdu Rockdu commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

What

Adds a source-guarded PyTorch 2.11 monkeypatch for exact per-parameter FSDP2 mixed-precision policies. The public module dispatches by the installed Torch base version and lazily loads the version-specific implementation, so unsupported versions never import PyTorch 2.11 internals. This PR does not include Miles actor or parallel-plan integration.

The distributed suite covers real full-size Diffusers blocks, exact output/gradient parity, all-gathered dtype and shape checks, FQN validation, mixed-dtype communication, and adversarial dtype/shape combinations.

Most of the code changes are due to CI ported from torch to ensure FSDP functions normally.

API (PyTorch 2.11 only)

import torch
from torch.distributed.fsdp import fully_shard

from miles.backends.fsdp_utils.fsdp_param_dtype_patch import (
    ParamDtypeMixedPrecisionPolicy,
    apply_param_dtype_map_patch,
)

apply_param_dtype_map_patch()
policy = ParamDtypeMixedPrecisionPolicy(
    param_dtype=torch.bfloat16,
    reduce_dtype=torch.float32,
    output_dtype=None,
    cast_forward_inputs=True,
    param_dtype_map={
        "attn1.to_q.weight": torch.float32,
        "attn1.to_q.bias": torch.float32,
    },
)
fully_shard(model, mp_policy=policy)

For a single FSDP wrap spanning multiple modules:

layer_norms = [block.norm for block in model.blocks]
layer_norm_policy = ParamDtypeMixedPrecisionPolicy(
    param_dtype=torch.bfloat16,
    reduce_dtype=torch.float32,
    cast_forward_inputs=False,
    param_dtype_map={
        "weight": torch.float32,
        "bias": torch.float32,
    },
)

# One grouped wrap manages both LayerNorms. The exact `weight` and `bias`
# FQNs are broadcast to every matching module in this call.
fully_shard(layer_norms, mp_policy=layer_norm_policy)

param_dtype_map is a sparse mapping of exact FQNs, scoped to the modules managed by that fully_shard call. Unlisted parameters use param_dtype. When one call groups multiple modules, an exact FQN is broadcast to every matching managed parameter (for example, weight across multiple LayerNorms). Multiple aliases of one shared parameter may specify the same dtype; conflicting alias dtypes are rejected. Wildcards are intentionally not part of the patch API; Miles' model integration compiles patterns to exact FQNs separately. Mixed trainable parameter dtypes require an explicit common reduce_dtype.

Compatibility

  • Supports the PyTorch 2.11 base version, independent of the CUDA wheel suffix.
  • Dispatches before loading private Torch internals; unsupported versions fail with a clear error.
  • Keeps the complete source-guarded implementation in _fsdp_param_dtype_patch_2_11.py, leaving room for separate 2.12/2.13 implementations.
  • Pins the Torch dependency stack to torch==2.11.0, torchaudio==2.11.0, and torchvision==0.26.0 so bare CPU CI matches the production GPU image.
  • Verifies every patched upstream function by source hash before installation.
  • Preserves the standard MixedPrecisionPolicy and empty-map paths.
  • Tested mapped floating dtypes: float8_e4m3fn, float8_e4m3fnuz, float8_e5m2, float8_e5m2fnuz, float16, bfloat16, float32, and float64.
  • float8_e8m0fnu and packed float4_e2m1fn_x2 are intentionally unsupported because PyTorch 2.11 does not implement the required _foreach_copy_ cast path. The patch does not add a slow per-tensor fallback.
  • Integral, boolean, and complex tensors may coexist and participate in forward as ignored frozen parameters; upstream FSDP2 cannot manage non-floating nn.Parameter objects because it reconstructs sharded parameters with gradients enabled.

Performance guard

Wan2.2 was run with identical settings and no per-parameter dtype overrides, changing only whether the patch was installed:

  • Unpatched: 70.8656s per stable actor training step
  • Patched: 70.8985s per stable actor training step
  • Delta: +0.0329s (+0.046%), within run-to-run noise

Test plan

  • Full repository pre-commit suite.
  • Version-dispatch unit tests and successful lazy patch application on torch==2.11.0+cu129.
  • Selected upstream PyTorch 2.11 mixed-precision, collective, and frozen-parameter regression tests under run-ci-torch.
  • Four-rank H200: full-size single Wan2.2 and LTX2.3 blocks under FSDP 1x4 and HSDP 2x2.
  • Bitwise output and per-parameter gradient parity across unpatched, patched standard-policy, and all-BF16-map paths.
  • Bitwise parity between explicit FP32 child FSDP wrappers inside a BF16 root and one BF16 root wrapper with the same parameters mapped to FP32 by exact FQN.
  • Direct resolver unit coverage plus a four-rank two-block topology where one grouped FSDP call wraps both LayerNorms, each block is wrapped separately, gathered LayerNorm parameters are FP32, and outputs/gradients are bitwise-equal to separate FP32 LayerNorm wraps.
  • Forward pre-hooks verify every gathered parameter's FQN, dtype, shape, and numel, including dim-0 padding for prime-sized tensors.
  • Twelve distributed validation cases: duplicate-FQN broadcast across grouped modules, separate-wrap scoping, shared aliases with equal and conflicting dtypes, unknown FQNs, grouped LayerNorm parity, reduce-dtype requirements, frozen overrides, mixed forward/backward, empty-map delegation, and empty gradients.
  • Two adversarial four-rank cases: single-module FSDP and shared-parameter multi-module HSDP with dimensions 7, 97, 101, and 103 across the supported floating dtype matrix plus ignored integer/boolean/complex parameters.

@Rockdu Rockdu added run-ci-fsdp Run FSDP domain tests on this PR run-ci-torch Run ported PyTorch regression tests on this PR labels Aug 7, 2026
@Rockdu Rockdu changed the title refactor(fsdp)(4.1/5): add per-parameter dtype patch refactor(fsdp)(4.2/5): add per-parameter dtype patch Aug 7, 2026
@Rockdu
Rockdu marked this pull request as ready for review August 7, 2026 08:27
Rockdu and others added 18 commits August 7, 2026 01:33
Add a source-guarded PyTorch 2.11 FSDP extension while preserving standard mixed-precision behavior, with distributed regression coverage for dtype communication and accumulation paths.

This PR was authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Exercise unpatched, standard patched, and all-BF16 mapped policies on Wan2.2 and LTX2.3 blocks across fully and hybrid sharded layouts.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use production Wan2.2 and LTX2.3 block dimensions and exercise FQN ambiguity, wrap scoping, shared parameters, reduction requirements, and delegation behavior.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Exercise supported FP8 and floating targets alongside ignored integral and complex parameters under fully and hybrid sharded multi-module layouts.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Verify that one mapped FSDP group is bitwise equivalent to explicit FP32 child wrappers inside a BF16 root for full-size Wan2.2 and LTX2.3 blocks.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Run selected PyTorch FSDP mixed-precision, collective, and frozen-parameter tests with the Miles patch under the dedicated run-ci-torch label.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Allow tests gated by run-ci-torch to pass CI registry validation.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Apply the configured Ruff, isort, and Black fixes to the new FSDP patch tests.

Authored with Claude.
Defer 2.11-only collective symbols to static checking so unsupported environments reach the patch version guard, and make paired iteration invariants explicit.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep bare CPU CI aligned with the production GPU image and make patch guard tests valid when collection begins under another Torch version.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Make the supported upstream baseline explicit at the patch definition.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the public policy module independent of private Torch internals and load the source-guarded 2.11 implementation only after matching the installed base version.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Apply the repository import ordering and formatting to the split patch modules.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Require exact FQN rules to apply across grouped module roots while rejecting conflicting dtype aliases of one shared parameter.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Apply an exact FQN rule to every matching parameter across grouped roots while rejecting conflicting aliases of a shared parameter.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Wrap the grouped parameter modules beneath an FSDP root so the regression test follows the supported runtime topology.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Enumerate duplicate parameter names so equal alias overrides resolve once and conflicting alias overrides remain detectable.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
Exercise one FSDP group spanning two LayerNorms beneath separately wrapped blocks and require bitwise parity with independent FP32 LayerNorm groups.

Authored with Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Rockdu
Rockdu force-pushed the refactor/fsdp-4.1-param-dtype-patch branch from 63d1d5a to 9bb2873 Compare August 7, 2026 08:36
Rockdu added 3 commits August 7, 2026 01:52
Split vendored changes into focused upstream/replacement hunks so reviewers can distinguish additions from unchanged PyTorch code.
Keep patch banners within their surrounding scopes so Black preserves the review layout.
Document each large worker's test matrix, execution flow, and invariants so reviewers can understand the distributed coverage before reading implementation details.
Read each resolved parameter dtype from its effective policy instead of storing the same override on FSDPParam twice.
@Rockdu
Rockdu merged commit 068cb2e into radixark:main Aug 8, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-ci-fsdp Run FSDP domain tests on this PR run-ci-torch Run ported PyTorch regression tests on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant