Lightning-AI / Lightning-AI/pytorch-lightning

Modules with `nn.Parameter` not Converted by Lightning Mixed Precision

Open
#19,699 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

question ver: 2.0.x
Dominant language
Python
Stars
31.4k
Forks
3.8k
Avg merge
6d 7h
Merged PRs (30d)
6

Description

Bug description

I have an nn.Module (call it Mod) which adds its input x to an internal nn.Parameter. I'm using Mod as part of a pl.LightningModule which I'm training in 16-mixed precision. However, the output of calling Mod is a tensor with dtype torch.float32. When I use other layer types, they output torch.float16 tensors as expected. This failure is often silent (as in the example provided below), but can cause issues if a model contains a component (e.g. flash attention) that requires fp16. Furthermore, after loading a model trained this way at inference time and calling .half() on it, the output is NaN or otherwise nonsensical, despite being perfectly fine if I load the model in fp32.

What version are you seeing the problem on?

v2.0

How to reproduce the bug

This is a small, reproducible example with lightning==2.0.2. Note how the output of Mod has dtype torch.float32 while the output of a linear layer has dtype torch.float16. The example runs distributed on 8 GPUs, but the issue is the same on a single GPU.

from lightning import pytorch as pl
import torch
from torch import nn
from torch.utils.data import TensorDataset, DataLoader


class Mod(nn.Module):
    def __init__(self):
        super().__init__()
        derp = torch.randn((1, 32))
        self.p = nn.Parameter(derp, requires_grad=False)
    def forward(self, x):
        return x + self.p

class Model(pl.LightningModule):
    def __init__(self):
        super().__init__()
        self.lin = nn.Linear(32, 32)
        self.m = Mod()
        self.l = nn.MSELoss()
    def forward(self, x):
        print('x', x.dtype)
        y = self.lin(x)
        print('y', y.dtype)
        z = self.m(y)
        print('z', z.dtype)

        print('p',self.m.p.dtype)
        print('lin', self.lin.weight.dtype)
        return z
    def training_step(self, batch, batch_idx):
        x, y = batch
        z = self(x)
        loss = self.l(z, y)
        return loss
    def configure_optimizers(self):
        return torch.optim.Adam(self.parameters())

xdata = torch.randn((1000, 32))
ydata = xdata + torch.randn_like(xdata) * .1
dataset=TensorDataset(xdata,ydata)
dataloader=DataLoader(dataset, batch_size=8, num_workers=4, pin_memory=True)
model = Model()
trainer = pl.Trainer(
    strategy='ddp',
    accelerator='gpu',
    devices=list(range(8)),
    precision='16-mixed'
)


trainer.fit(model=model, train_dataloaders=dataloader)
Error messages and logs

Example output:

Epoch 3:  78%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                               | 98/125 [00:00<00:00, 138.94it/s, v_num=5]x torch.float32
x torch.float32
y torch.float16
z torch.float32
p torch.float32
lin torch.float32
Environment
Current environment
#- Lightning Component (e.g. Trainer, LightningModule, LightningApp, LightningWork, LightningFlow): Trainer, LightningModule
#- PyTorch Lightning Version (e.g., 1.5.0): 2.0.2
#- PyTorch Version (e.g., 2.0): 2.1.0
#- Python version (e.g., 3.9): 3.10.12
#- OS: Ubuntu 20.04.6 LTS (Focal Fossa)
#- CUDA/cuDNN version: 11.8
#- GPU models and configuration: 8xA100
#- How you installed Lightning(`conda`, `pip`, source): pip
More info

Thank you for your help!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the provided minimal reproduction with Trainer precision='16-mixed' and inspect Mod.forward, especially the addition of x and self.p. Compare its dtype with the linear layer output and verify the behavior on a single GPU. Done means the reproduced module follows the expected mixed-precision behavior without producing invalid inference results after loading and calling half().

Written by the indexing model from the issue text.

Assessment

Tech stack
python, pytorch
Domain
machine-learning
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.