Skip to content

Load transformer models saved on GPU on CPU-only machines - #327

Open
maxteneff wants to merge 2 commits into
MTSWebServices:mainfrom
maxteneff:fix/load-gpu-model-on-cpu
Open

maxteneff wants to merge 2 commits into
MTSWebServices:mainfrom
maxteneff:fix/load-gpu-model-on-cpu

Conversation

@maxteneff

@maxteneff maxteneff commented Oct 17, 2026 •

Copy link
Copy Markdown

Description

Fixes #286.

A fitted SASRecModel or BERT4RecModel saved on a GPU machine can't be loaded with load_model, load or loads on a machine without CUDA:

RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=torch.device('cpu') to map your storages to the CPU.

A pickled fitted model holds its Lightning checkpoint, which TransformerModelBase.__setstate__ reads with torch.load(...) without a map_location. torch then tries to restore the tensors on the device they were saved on. Unlike load_from_checkpoint, load gives users no way to pass a map_location.

This PR makes __setstate__ load the checkpoint to CPU. Nothing changes on GPU machines: TransformerLightningModule._prepare_for_inference moves the model to recommend_torch_device (CUDA when it's available) before every inference, and the trainer places the model on its device when fitting.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Optimization

How Has This Been Tested?

  • Added test_load_fitted_model_saved_on_gpu_without_gpu for SASRecModel and BERT4RecModel. It saves a fitted model with tensors tagged as cuda:0 (patching torch.serialization.location_tag), makes torch.cuda.is_available() return False, loads the model, and checks that its recommendations match the original model. Without the fix it fails with the error above; with the fix it passes.
  • tests/models/nn/transformers: 213 passed, 57 skipped (GPU-only).
  • isort, black, flake8, pylint, mypy and codespell pass on the changed files.
  • I don't have a CUDA machine, so I haven't tried a checkpoint saved on a real GPU. The test reproduces the same code path by tagging the tensors as CUDA.

Checklist:

  • Read the contribution guide: yes
  • Docstrings: no public API changes
  • New tests: added
  • Changelog: updated

Not included here: load_weights_from_checkpoint also calls torch.load without a map_location, so a GPU checkpoint passed to it fails the same way on a CPU-only machine. Happy to handle it in a follow-up, e.g. by adding a map_location argument like load_from_checkpoint has.

Map the fitted checkpoint to CPU when unpickling transformer models, so a
model trained on GPU can be loaded with `load_model`, `load` or `loads` on a
machine without CUDA. Weights are moved to the target device before inference
and by the trainer when fitting, so nothing changes on GPU machines.

Fixes MTSWebServices#286
@maxteneff
maxteneff force-pushed the fix/load-gpu-model-on-cpu branch from 39ae5c4 to 2117a2b Compare October 17, 2026 17:12

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Is it not possible to load transformer model on cpu only

1 participant