Skip to content

[models] fix: support CPU-only checkpoint conversion - #3853

Closed
yaoyu-33 wants to merge 6 commits into
mainfrom
dispatch/issue3295-cpu-conversion
Closed

[models] fix: support CPU-only checkpoint conversion#3853
yaoyu-33 wants to merge 6 commits into
mainfrom
dispatch/issue3295-cpu-conversion

Conversation

@yaoyu-33

Copy link
Copy Markdown
Contributor

Summary

Fixes #3295.

  • Use Gloo and CPU initialization when CUDA is not visible for provider-based model construction.
  • Disable MCore CPU-offload hooks/flags and TE-only persist_layer_norm behavior during CPU-only initialization.
  • Fall back to the local GPT layer spec for CPU-init/no-CUDA builds so TransformerEngine SelfAttention is not instantiated.
  • Add focused unit coverage for no-visible-CUDA provider initialization and GPT layer-spec selection.

Validation

  • cw job 11784762 completed 0:0
    • log: /lustre/fsw/portfolios/coreai/projects/coreai_dlalgo_llm/users/yuya/logs/issue3295/issue3295-cpu7_11784762.log
    • uv sync --frozen --no-install-project --no-install-package megatron-core
    • focused pytest: 6 passed, 30 deselected
    • no-CUDA tiny Llama AutoBridge.to_megatron_model(wrap_with_ddp=False, use_cpu_initialization=True) completed with REPRO_DONE
  • cw job 11784769 completed 0:0
    • log: /lustre/fsw/portfolios/coreai/projects/coreai_dlalgo_llm/users/yuya/logs/issue3295/issue3295-pc2_11784769.log
    • uv run --no-sync pre-commit run --all-files

@copy-pr-bot

copy-pr-bot Bot commented May 15, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@yaoyu-33

Copy link
Copy Markdown
Contributor Author

Progress update for issue #3295 CPU-only conversion:

  • Fixed provider initialization so no-visible-CUDA paths use CPU initialization and Gloo instead of CUDA/NCCL assumptions.
  • Disabled MCore CPU-offload context/flags and TE-only persist_layer_norm behavior for CPU-only initialization.
  • Added a no-CUDA GPT local layer-spec fallback so CPU conversion does not instantiate TransformerEngine SelfAttention.
  • Added focused regression coverage in test_model_provider_mixin.py and test_gpt_provider.py.

Validation on rebased HEAD 761a2f1ba96a959c2f233f104c6a4f09a963bc3a:

  • cw job 11784762 completed 0:0: focused pytest 6 passed, 30 deselected; no-CUDA tiny Llama AutoBridge.to_megatron_model(... use_cpu_initialization=True) reached REPRO_DONE.
    Log: /lustre/fsw/portfolios/coreai/projects/coreai_dlalgo_llm/users/yuya/logs/issue3295/issue3295-cpu7_11784762.log
  • cw job 11784769 completed 0:0: uv run --no-sync pre-commit run --all-files passed.
    Log: /lustre/fsw/portfolios/coreai/projects/coreai_dlalgo_llm/users/yuya/logs/issue3295/issue3295-pc2_11784769.log

Residual risk: this validates CPU-only model construction/conversion setup for the scoped wrap_with_ddp=False + use_cpu_initialization=True path with a tiny Llama repro. Broader CPU-only distributed conversion and non-GPT architectures may still need follow-up coverage.

@yaoyu-33

Copy link
Copy Markdown
Contributor Author

/ok to test 761a2f1

if getattr(config, "mtp_num_layers", None):
from megatron.core.models.gpt.gpt_layer_specs import get_gpt_mtp_block_spec

use_transformer_engine = not _should_use_local_layer_spec_for_cpu_only_initialization(config)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: The existing mtp_block_spec tests (lines 461, 494, 497, 526 in test_gpt_provider.py) all still assert use_transformer_engine=True — they pass because the test providers default to use_cpu_initialization=False. Consider adding one test that sets use_cpu_initialization=True with CUDA mocked away, so the use_transformer_engine=False path through get_gpt_mtp_block_spec and get_gpt_decoder_layer_specs is covered.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this coverage in test_mtp_block_spec_uses_local_decoder_spec_for_cpu_only_initialization.

The test forces use_cpu_initialization=True with no visible CUDA, drives the empty layer_specs fallback, and asserts both get_gpt_decoder_layer_specs() and get_gpt_mtp_block_spec() receive use_transformer_engine=False.

@claude

claude Bot commented May 15, 2026

Copy link
Copy Markdown
Contributor

Review: [models] fix: support CPU-only checkpoint conversion

Clean PR - the backend selection, TE feature disabling, and layer-spec fallback logic all look correct. The context manager in _disable_te_cpu_offload_context_for_cpu_only_initialization properly restores the monkey-patched attribute in the finally block, and the guard chain (import, getattr, patch) is defensive in the right places.

One gap: the mtp_block_spec path was changed from hardcoded use_transformer_engine=True to a computed value, but no test exercises the False branch. The existing MTP tests all pass because their providers default to use_cpu_initialization=False. See inline comment.

Suggested test cases: No perf tests impacted.

ModelT = TypeVar("ModelT", bound=MegatronModule)


def _cuda_is_available() -> bool:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you help to move utils functions to utils file?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the CPU-only helper functions out of model_provider.py into src/megatron/bridge/models/utils.py, with model_provider.py importing them from there. I also updated the affected mixin tests to patch the relocated helper module.

@yaoyu-33
yaoyu-33 force-pushed the dispatch/issue3295-cpu-conversion branch from 761a2f1 to 73080e4 Compare May 15, 2026 21:29
@yaoyu-33

Copy link
Copy Markdown
Contributor Author

Review follow-up pushed in 73080e44f841b486b5f3de4f3600b40269009a2d.

Changes:

  • Moved CPU-only provider helper functions from model_provider.py to src/megatron/bridge/models/utils.py.
  • Added focused MTP coverage for the no-CUDA + use_cpu_initialization=True path, including the empty-layer-spec decoder fallback and use_transformer_engine=False propagation.
  • Updated affected provider mixin tests for the relocated utility calls.

Validation:

  • cw 11785831 completed 0:0: focused pytest selected 11 provider tests (11 passed, 26 deselected) and the no-CUDA tiny Llama AutoBridge.to_megatron_model(... use_cpu_initialization=True) repro completed with REPRO_DONE.
    Log: /lustre/fsw/portfolios/coreai/projects/coreai_dlalgo_llm/users/yuya/logs/issue3295/issue3295-review-tests-container_11785831.log
  • cw 11785878 completed 0:0: uv run --no-sync pre-commit run --all-files passed.
    Log: /lustre/fsw/portfolios/coreai/projects/coreai_dlalgo_llm/users/yuya/logs/issue3295/issue3295-review-precommit-container_11785878.log

Residual risk: validation is focused on the CPU-only conversion/provider path and review-requested MTP fallback; full CI is still the broader safety net.

@yaoyu-33

Copy link
Copy Markdown
Contributor Author

/ok to test 73080e4

@yaoyu-33 yaoyu-33 added the needs-more-tests Requires additional L0 and L1 test coverage before merge label May 15, 2026
@@ -374,6 +374,58 @@ def test_default_layer_spec_default_case(self, mock_te_full_spec, mock_te_spec):
mock_te_spec.assert_called_once_with(provider)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a cpu only functional conversion tests please. Can be L1.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added L1 CPU-only functional conversion coverage in 2e33ee6250c0bfb3b7154aecf1859043a20f4b2a.

What changed:

  • Added tests/functional_tests/test_groups/converter/test_cpu_only_conversion.py, which creates a tiny local HF Llama model and runs AutoBridge.to_megatron_model(wrap_with_ddp=False, use_cpu_initialization=True) with CUDA hidden.
  • Added tests/functional_tests/launch_scripts/h100/active/L1_Launch_converter_cpu_only.sh so this is picked up as an H100 L1 functional launch script.

cw validation:

  • 11787115 completed 0:0: new L1 launch script passed (1 passed) and completed the CPU-only tiny Llama conversion.
    Log: /lustre/fsw/portfolios/coreai/projects/coreai_dlalgo_llm/users/yuya/logs/issue3295/issue3295-functional-cpu-container_11787115.log
  • 11787138 completed 0:0: uv run --no-sync pre-commit run --all-files passed.
    Log: /lustre/fsw/portfolios/coreai/projects/coreai_dlalgo_llm/users/yuya/logs/issue3295/issue3295-functional-precommit-container_11787138.log

yaoyu-33 added 5 commits May 15, 2026 15:39
Signed-off-by: yaoyu-33 <yaoyu.094@gmail.com>
Signed-off-by: yaoyu-33 <yaoyu.094@gmail.com>
Signed-off-by: yaoyu-33 <yaoyu.094@gmail.com>
Signed-off-by: yaoyu-33 <yaoyu.094@gmail.com>
Signed-off-by: yaoyu-33 <yaoyu.094@gmail.com>
@yaoyu-33
yaoyu-33 force-pushed the dispatch/issue3295-cpu-conversion branch from 73080e4 to 2e33ee6 Compare May 15, 2026 22:57
@yaoyu-33

Copy link
Copy Markdown
Contributor Author

/ok to test 2e33ee6

@yaoyu-33 yaoyu-33 added area:ckpt Checkpoint conversion, loading, export, and save paths bug Something isn't working needs-review PR is ready for code review and waiting on a reviewer labels May 15, 2026
@yaoyu-33

Copy link
Copy Markdown
Contributor Author

/ok to test f0788ae

)
spec = decoder_layer_specs[-1]
return get_gpt_mtp_block_spec(config, spec, use_transformer_engine=True, vp_stage=vp_stage)
return get_gpt_mtp_block_spec(config, spec, use_transformer_engine=use_transformer_engine, vp_stage=vp_stage)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can a model converted without TE work with TE training?

@yaoyu-33

Copy link
Copy Markdown
Contributor Author

Closing this PR without merge.

The scoped CPU-only path explored here gets model construction farther, but the compatibility tradeoff is too large to merge right now. If no GPU is available, we cannot use Transformer Engine, so this path has to fall back to the local spec. That means the imported model can have issues or differ from the model a user later trains on GPU with TE enabled.

We should defer this approach until there is a stronger request for CPU-only checkpoint conversion and a better compatibility design that preserves the intended GPU/TE training behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:ckpt Checkpoint conversion, loading, export, and save paths bug Something isn't working needs-more-tests Requires additional L0 and L1 test coverage before merge needs-review PR is ready for code review and waiting on a reviewer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[support] CPU-only Checkpoint Conversion

2 participants