Skip to content

convert_to_analog drops a repeated layer from nn.Sequential #825

Open

Description

@vera-rubin

Description

Converting nn.Sequential(layer, layer) removes the second application of the shared layer. With FloatingPointRPUConfig, the converted model returns 0.25 instead of 0.0625.

aihwkit 1.2.0 at b5aeea78859a4a028975519e154088d3ae0efeaf, PyTorch 2.5.1+cpu, Python 3.12.3, NumPy 2.5.4, Linux x86_64, GCC 13.3.0, OpenBLAS 0.3.28, native CPU Release build, CUDA off, Conda N/A.

How to reproduce

Using a CPU source build of that commit, save this as sequential_repro.py.

"""Default conversion drops a repeated layer from nn.Sequential."""
import numpy as np
import torch
from torch import nn
from aihwkit.nn.conversion import convert_to_analog
from aihwkit.simulator.configs import FloatingPointRPUConfig

torch.set_num_threads(1)
weight = np.float64(1 / 4)
x = np.float64(1)
expected = np.array([[weight * weight * x]], dtype=np.float64)
layer = nn.Linear(1, 1, bias=False)
with torch.no_grad():
    layer.weight.fill_(float(weight))
digital = nn.Sequential(layer, layer)
input_tensor = torch.tensor([[x]], dtype=torch.float32)
np.testing.assert_array_equal(digital(input_tensor).detach().numpy(), expected)
analog = convert_to_analog(digital, FloatingPointRPUConfig())
actual = analog(input_tensor).detach().numpy()
print(f"Layer count: original={len(digital)}, converted={len(analog)}")
print(f"Output: expected={expected.tolist()}, actual={actual.tolist()}")
np.testing.assert_array_equal(actual, expected)
OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 python sequential_repro.py

Observed output before the final assertion fails.

Layer count: original=2, converted=1
Output: expected=[[0.0625]], actual=[[0.25]]

Expected behavior

The conversion contract promises replacement of all Conv/Linear layers. Both applications should remain and yield (1/4)*(1/4)*1 = 1/16, following the ideal tile equation. The conversion docs are silent about repeated layer registrations.

Other information

The container conversion rebuilds the sequence from named_children(), which omits duplicate module objects. We tested CPU float32 with both inplace settings and passing distinct-layer controls, but did not test CUDA or convolution reuse.

The reproducer is CC0-1.0.

— ChipLab

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions