PennyLaneAI / pennylane-lightning

The PennyLane-Lightning plugin provides a fast state-vector simulator written in C++ for use with PennyLane
https://docs.pennylane.ai/projects/lightning
Apache License 2.0
83 stars 35 forks source link

[BUG] Exception when deepcopy because of non-pickle-able lightning device #677

Open TheRisenPhoenix opened 5 months ago

TheRisenPhoenix commented 5 months ago

Issue description

I use a pennylane circuit inside a torch model, which needs to be (deep)copied. If I use the default.qubit device, everything works fine, but when I switch to a lightning device (lightning.qubit / lightning.gpu), an exception is thrown. I provide a minimal example to reproduce below.

Platform info: Linux-5.15.146.1-microsoft-standard-WSL2-x86_64-with-glibc2.35 Python version: 3.11.7 Numpy version: 1.26.4 Scipy version: 1.12.0 Installed devices:

Source code and tracebacks

I've prepared this example which I hope helps to reproduce the issue:

import pennylane as qml
import torch
from copy import deepcopy

n_qubits = 2
n_layers = 6
weight_shapes = {"weights": (n_layers, n_qubits)}

# default.qubit works fine
# lightning.qubit also fails
dev = qml.device("lightning.gpu", wires=n_qubits)

@qml.qnode(dev)
def qnode(inputs, weights):
    qml.AngleEmbedding(inputs, wires=range(n_qubits))
    qml.BasicEntanglerLayers(weights, wires=range(n_qubits))
    return [qml.expval(qml.PauliZ(wires=i)) for i in range(n_qubits)]

class Model(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.qlayer_1 = qml.qnn.TorchLayer(qnode, weight_shapes)

    def forward(self, x):
        x = self.qlayer_1(x)
        return x

model = Model()
model2 = deepcopy(model)

This is the stacktrace:

Traceback (most recent call last):
  File "/mnt/d/Code/report.py", line 32, in <module>
    model2 = deepcopy(model)
             ^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 172, in deepcopy
    y = _reconstruct(x, memo, *rv)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 271, in _reconstruct
    state = deepcopy(state, memo)
            ^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 146, in deepcopy
    y = copier(x, memo)
        ^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 231, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
                             ^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 172, in deepcopy
    y = _reconstruct(x, memo, *rv)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 297, in _reconstruct
    value = deepcopy(value, memo)
            ^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 172, in deepcopy
    y = _reconstruct(x, memo, *rv)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 271, in _reconstruct
    state = deepcopy(state, memo)
            ^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 146, in deepcopy
    y = copier(x, memo)
        ^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 231, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
                             ^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 172, in deepcopy
    y = _reconstruct(x, memo, *rv)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 271, in _reconstruct
    state = deepcopy(state, memo)
            ^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 146, in deepcopy
    y = copier(x, memo)
        ^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 231, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
                             ^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 172, in deepcopy
    y = _reconstruct(x, memo, *rv)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 271, in _reconstruct
    state = deepcopy(state, memo)
            ^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 146, in deepcopy
    y = copier(x, memo)
        ^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 231, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
                             ^^^^^^^^^^^^^^^^^^^^^
  File "/lib/python3.11/copy.py", line 161, in deepcopy
    rv = reductor(4)
         ^^^^^^^^^^^
TypeError: cannot pickle 'pennylane_lightning.lightning_gpu_ops.DevPool' object
mlxd commented 5 months ago

Hi @TheRisenPhoenix Thanks for the report on this. The object in question is generally tied to specific local instances of GPUs on the system you are running, so we do not have serialisation rules in place for it. However, we can take a look at what seems sensible here and update you when we have a resolution.

TheRisenPhoenix commented 5 months ago

I appreciate your efforts in looking into this matter and keeping me informed! Looking forward to hearing back :)