Repository navigation
feat(dynamo): map_weights - compile from memory-mapped checkpoint weights - #4854
Draft
cehongwang wants to merge 5 commits into
Draft
cehongwang wants to merge 5 commits into
cehongwang wants to merge 5 commits into
Conversation
3 of 7 tasks
…o-pass mapping, weakref registry, inward page release, strict = all zero-copy
…releasable, page-size-independent test, clearer header errors
cehongwang
added a commit
that referenced
this pull request
Oct 13, 2026
cehongwang
changed the base branch from
main
to
cehongw/release-weights-after-build
October 13, 2026 08:00
6 of 7 tasks
cehongwang
added this pull request to stack #4859
October 13, 2026 08:04
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds
torch_tensorrt.dynamo.map_weights, which points a model's weights at zero-copy views of a safetensors checkpoint, andsave_weights_for_mapping, which writes a model's weights in a formmap_weightscan map.Compiling on the CPU (model and inputs kept on the CPU through
torch_tensorrt.dynamo.compile) already avoids a GPU copy of the weights: TensorRT takes weights as host pointers, and the converters pass a CPU tensor's owndata_ptr(). But the weights still have to be loaded into host memory first, all of them, before the first engine is built. Withmap_weightsthe checkpoint is mapped copy-on-write (mmap.ACCESS_COPY, so the file is never written) and each parameter and buffer becomes atorch.frombufferview of it.torch.exportreads only shapes, so a weight's pages become resident only when TensorRT reads them, while building the engine of the partition that uses the weight.map_weights(model_or_exported_program, path, *, key_map=None, strict=False) -> MappedWeightsmetadevice: they are replaced wherever they are registered, so tied weights stay tied. Real tensors keep theirParameterobjects and get.data = view; on any device they end up on the CPU, ready for CPU compilation.ExportedProgram'sstate_dictandconstantsare remapped, tied weights included.key_map(a callable or a dict) maps model names to checkpoint names.strict=Trueraises unless every tensor in the model'sstate_dictis mapped without a copy: no name missing, as withload_state_dict(strict=True), and no dtype mismatch. Non-persistent buffers, such as rotary frequencies, are not required.copied, and missing names inmissing(still_metafor those onmeta). A shape mismatch always raises.data_offsetsin bounds and matching dtype × shape.MappedWeightsis a context manager.close()drops only the handle's reference: the weights stay mapped and releasable while they're in use, so mapping in awithblock and compiling afterwards still releases pages.release_mapped_storage(storage) -> booldrops a mapped storage's resident pages withmadvise(MADV_DONTNEED). The tensor stays valid and is re-read from the file if used again. Only pages entirely inside the storage are dropped, so a neighbor's in-place writes survive.release_weights_after_build(feat(dynamo): release model weights once their last engine is built #4853; this PR is stacked on it, merge feat(dynamo): release model weights once their last engine is built #4853 first):resize_(0)on its storage. That fails on a mapped weight, which is a view of a file.release_storage: ifrelease_mapped_storagerecognizes the storage, its pages are dropped andresize_(0)is skipped._weight_release.py.save_weights_for_mapping(model_or_exported_program, path)writes one entry per tensor object (a tied weight once), in the model's current dtypes. That's for checkpoints cast while loading, e.g. stored in fp32 and run in bf16.safetensorspackage map too, and vice versa.docsrc/py_api/dynamo.rst.Compared to
safetensors.torch.load_file+load_state_dict(assign=True), which also return file-backed views:ExportedPrograms;Measurements
pi0.5 (lerobot, bf16, Anthony Shoumikhin's ExecuTorch export), CPU compilation, resource partitioner with a fixed per-engine cap (16 engines), weights released after each engine, A40, TensorRT 11.0; host RSS + GPU memory, load phase excluded. The checkpoint is fp32, so
save_weights_for_mappingwrote the bf16 weights once (6.74 GiB); the run maps them with this PR'smap_weights(policy, path, strict=True)in place of my earlier prototype:map_weights(this PR)6.74 GiB mapped, nothing missing or copied. For comparison, loading the weights into host memory instead of mapping them peaks at 10.1 GiB (27-engine split, otherwise the same).
Testing
tests/py/dynamo/models/test_weight_mapping.py(17 tests):release_storagedrops a mapped weight's pages without resizing it, and still resizes an ordinary storage;release_weights_after_build=Truereleases every weight throughrelease_mapped_storage, the output matches eager, and the weights still read correctly afterwards.metamodule, a real module, a bf16 checkpoint, a realExportedProgramand ametaExportedProgramwith tied weights.data_ptr()is inside the mapping, values match, tied weights stay tied, and nothing is reported missing.ExportedProgram.module()reproduces the original output.key_mapand missing names (still_meta);strict=Trueraises on missing persistent names and on dtype mismatches, leaving the model unchanged, but accepts a missing non-persistent buffer (asafetensorsstate_dict()checkpoint); withoutstrict, a dtype mismatch is cast and reported;safetensors.torch.save_filemaps.mmap.PAGESIZE, so this holds on 64 KiB-page kernels too;meta-built model mapped and compiled from its CPU weights matches eager.Mutation checks: if
map_weightscopies instead of mapping, 6 tests fail; with the earlier outward page rounding, the neighbor test fails. mypy (strict, with torch) is clean. #4853's tests pass on this branch.Type of change
Checklist: