Fix ModelPruning iterative reuse RuntimeError on non-leaf tensors#21717
Conversation
When ModelPruning with use_lottery_ticket_hypothesis=True is reused across multiple trainer.fit() calls, setup() is called again each run. After the first pass, _copy_param sets dst.data = src.data, making the parameters non-leaf tensors. The subsequent deepcopy(module) then raises: RuntimeError: Only Tensors created explicitly by the user (graph leaves) support the deepcopy protocol at the moment Fix by adding _deepcopy_for_pruning(), a helper that temporarily replaces non-leaf parameters with detached clones before deepcopy and restores the originals afterward. Also explicitly set _original_layers to None before re-populating in setup() so the previous run's tensor references are released before new copies are allocated. Fixes Lightning-AI#8542
The actual non-leaf tensor after pruning is module.weight stored in module.__dict__ by the forward pre-hook (weight_orig * weight_mask), not in module._parameters. Patching _parameters had two problems: 1. Did not fix the RuntimeError (wrong dict being patched) 2. Caused mypy errors: assigning Tensor to Parameter | None Switch to iterating module.__dict__ instead, which correctly captures the hook-written non-leaf weight attribute.
3de4112 to
03ed64a
Compare
for more information, see https://pre-commit.ci
|
Pinging for review — all CI checks are green (triage, pre-commit, GitGuardian, ReadTheDocs all pass). @justusschock @tchaton could one of you take a look when you get a chance? The fix is in |
|
Follow-up ping @justusschock @tchaton — CI is green and the fix is small: |
|
Codecov Report✅ All modified and coverable lines are covered by tests.
Additional details and impacted files@@ Coverage Diff @@
## master #21717 +/- ##
=========================================
- Coverage 87% 79% -8%
=========================================
Files 270 267 -3
Lines 24010 23963 -47
=========================================
- Hits 20790 18842 -1948
- Misses 3220 5121 +1901 |
What does this PR fix?
Fixes #8542.
When
ModelPruning(use_lottery_ticket_hypothesis=True)is reused across multipletrainer.fit()calls (iterative pruning), the second and subsequent calls tosetup()raise:Root cause: After the first training pass,
apply_lottery_ticket_hypothesis()calls_copy_param()which doesdst.data = src.data.to(dst.device). This in-place data assignment makes the model parameters non-leaf tensors. Whensetup()is called again on the nexttrainer.fit(),deepcopy(module)fails.Changes
src/lightning/pytorch/callbacks/pruning.py_deepcopy_for_pruning(module)static helper: temporarily replaces non-leaf parameters withdetach().clone()copies, deepcopies, then restores originalssetup()to use_deepcopy_for_pruninginstead of baredeepcopy(module)setup(), setself._original_layers = Nonebefore re-populating to release previous-run tensor referencestests/tests_pytorch/callbacks/test_pruning.pytest_iterative_pruning_no_runtime_error: runs 3 consecutivetrainer.fit()calls with the same pruning callback and verifies noRuntimeErroris raisedReproduction
📚 Documentation preview 📚: https://pytorch-lightning--21717.org.readthedocs.build/en/21717/