Repository navigation
[OMNIML-6063] [18/21] Decompress compressed-tensors MoE experts on the fly as they load #2747
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
be5b211
6bfc329
61d62cf
1f43de9
2687bf1
33b0d89
eca24c2
b2387a3
0b3a09f
06b4184
ca7fc67
43d6854
cf60e7d
17f4119
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """Loading the modeling code a checkpoint ships with itself.""" | ||
|
|
||
| import glob | ||
| import os | ||
| import shutil | ||
| import tempfile | ||
| import warnings | ||
|
|
||
|
|
||
| def stage_full_remote_closure() -> None: | ||
| """Make transformers stage every module of a local checkpoint's remote code, not just one hop. | ||
|
|
||
| transformers' ``get_cached_module_file`` copies a remote module and its *direct* relative imports | ||
| into ``transformers_modules/<repo>/<hash>/``, but does not recurse. Remote code more than one import | ||
| deep -- Kimi-K2.5's ``modeling_kimi_k25 -> modeling_deepseek -> configuration_deepseek`` -- is | ||
| then staged incomplete, and the later recursive walk in ``get_relative_import_files`` fails with | ||
| ``FileNotFoundError``, from ``get_class_from_dynamic_module`` and ``from_pretrained`` alike. | ||
|
|
||
| Wrap ``get_cached_module_file`` so that, loading from a local checkpoint dir, it copies every | ||
| sibling ``*.py`` into the stage dir it just populated. Idempotent. | ||
| """ | ||
| import transformers.dynamic_module_utils as dmu | ||
| from transformers.utils import HF_MODULES_CACHE | ||
|
|
||
| if getattr(dmu.get_cached_module_file, "_modelopt_full_closure", False): | ||
| return | ||
| orig = dmu.get_cached_module_file | ||
|
|
||
| def _staged(pretrained_model_name_or_path, module_file, *args, **kwargs): | ||
| resolved = orig(pretrained_model_name_or_path, module_file, *args, **kwargs) | ||
| src = str(pretrained_model_name_or_path) | ||
| if os.path.isdir(src): | ||
| staged = str(resolved) | ||
| if not os.path.isabs(staged): | ||
| staged = os.path.join(HF_MODULES_CACHE, staged) | ||
| stage_dir = os.path.dirname(staged) | ||
| try: | ||
| for py in glob.glob(os.path.join(src, "*.py")): | ||
| dst = os.path.join(stage_dir, os.path.basename(py)) | ||
| if not os.path.exists(dst): | ||
| # Every rank loading the checkpoint stages into this dir and imports from it: | ||
| # renamed into place (atomic), a file appears there whole, never half written. | ||
| fd, tmp = tempfile.mkstemp(dir=stage_dir) | ||
| os.close(fd) | ||
| shutil.copy(py, tmp) | ||
| os.replace(tmp, dst) | ||
| except OSError as e: # a failed copy only matters if a deeper import needs the file | ||
| warnings.warn(f"Could not stage the remote code of {src}: {e}") | ||
| return resolved | ||
|
Comment on lines
+53
to
+64
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [SUGGESTION] The atomic rename is the right call; three follow-ups on the staging loop:
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pushing back on (2), and postponing (1) and (3). (2): |
||
|
|
||
| setattr(_staged, "_modelopt_full_closure", True) | ||
| dmu.get_cached_module_file = _staged | ||
|
shengliangxu marked this conversation as resolved.
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[SUGGESTION] The
shutil.copy-onto-mkstemprewrite addressed the 0600 mode from the last round, but two edges remain in the error path, and both come from thetrysitting outside the loop rather than inside it:OSError— an unreadable*.py, a full disk, a permission problem on one file — exits the whole loop, so the siblings after it are never staged. Since the point of this helper is to stage the full closure, a partial stage reproduces theFileNotFoundErrorfromget_relative_import_filesthat the docstring describes, just one import deeper.shutil.copyraises,os.replacenever runs andtmpstays in the stage dir. It is not a*.py, so it does not breakget_relative_import_files, but with every rank staging into a sharedHF_MODULES_CACHEthe droppings accumulate silently.Moving the
tryinside the loop with afinallythat unlinks fixes both — stage what you can, warn per file, leave nothing behind:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Postponed: both edges are real, but only after a copy has already failed and warned, and an import that needs a file left unstaged still fails loudly with
FileNotFoundError. Moving thetryinto the loop, with afinallythat unlinks the temp file, is a follow-up rather than a change to this approved slice.