Circuit cutting on gpus

I am able to simulate a 30 qubit circuit with the GPU backend.

n_qubits = 30

dev = qml.device('lightning.gpu', wires=n_qubits)

@qml.qnode(dev)
def circuit():
    for i in range(n_qubits): 
        qml.X(wires=i)

    return qml.expval(qml.pauli.string_to_pauli_word("Z"))


circuit()

However I get a out of memory error when I run 31 qubits which is expected:
PLException: [/project/pennylane_lightning_gpu/src/util/DataBuffer.hpp][Line:37][Method:DataBuffer]: Error in PennyLane Lightning: out of memory
Given that my GPU can support 30 qubits, I would like to employ circuit cutting to simulate a 31 qubit circuit as shown below:


n_qubits = 31

dev = qml.device('lightning.gpu', wires=n_qubits)

@qml.cut_circuit(auto_cutter=True)
@qml.qnode(dev)
def circuit():
    for i in range(n_qubits): 
        qml.X(wires=i)

    return qml.expval(qml.pauli.string_to_pauli_word("Z"))


circuit()

PLException: [/project/pennylane_lightning_gpu/src/util/DataBuffer.hpp][Line:37][Method:DataBuffer]: Error in PennyLane Lightning: out of memory

Why does this approach not work?

When I run circuit cutting for 15 qubits, I get the following error

n_qubits = 15

dev = qml.device('lightning.gpu', wires=n_qubits)

@qml.cut_circuit(auto_cutter=True)
@qml.qnode(dev)
def circuit():
    for i in range(n_qubits): 
        qml.X(wires=i)

    return qml.expval(qml.PauliZ(0))


circuit()

---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Cell In[11], line 14
      9         qml.X(wires=i)
     11     return qml.expval(qml.PauliZ(0))
---> 14 circuit()

File ~/.local/lib/python3.10/site-packages/pennylane/transforms/batch_transform.py:300, in batch_transform.default_qnode_wrapper.<locals>._wrapper(*args, **kwargs)
    297     qnode.interface = qml.math.get_interface(*args, *list(kwargs.values()))
    299 qnode.construct(args, kwargs)
--> 300 tapes, processing_fn = self.construct(qnode.qtape, *targs, **tkwargs)
    302 interface = qnode.interface
    303 execute_kwargs = getattr(qnode, "execute_kwargs", {}).copy()

File ~/.local/lib/python3.10/site-packages/pennylane/transforms/batch_transform.py:431, in batch_transform.construct(self, tape, *targs, **tkwargs)
    429 if argnums is not None:
    430     tape.trainable_params = argnums
--> 431 tapes, processing_fn = self.transform_fn(tape, *targs, **tkwargs)
    433 if processing_fn is None:
    435     def processing_fn(x):

File ~/.local/lib/python3.10/site-packages/pennylane/transforms/qcut/cutcircuit.py:349, in cut_circuit(tape, auto_cutter, use_opt_einsum, device_wires, max_depth, **kwargs)
    342     except ImportError as e:
    343         raise ImportError(
    344             "The opt_einsum package is required when use_opt_einsum is set to "
...
---> 85 order += 1  # pylint: disable=undefined-loop-variable
     86 for m in tape.measurements:
     87     obs = getattr(m, "obs", None)

UnboundLocalError: local variable 'order' referenced before assignment

Name: PennyLane
Version: 0.30.0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/XanaduAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: /home/cudaq/.local/lib/python3.10/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml
Required-by: PennyLane-Lightning, PennyLane-Lightning-GPU, PennyLane-qiskit

Platform info:           Linux-5.4.0-146-generic-x86_64-with-glibc2.35
Python version:          3.10.6
Numpy version:           1.23.5
Scipy version:           1.10.1
Installed devices:
- lightning.qubit (PennyLane-Lightning-0.30.0)
- qiskit.aer (PennyLane-qiskit-0.30.0)
- qiskit.basicaer (PennyLane-qiskit-0.30.0)
- qiskit.ibmq (PennyLane-qiskit-0.30.0)
- qiskit.ibmq.circuit_runner (PennyLane-qiskit-0.30.0)
- qiskit.ibmq.sampler (PennyLane-qiskit-0.30.0)
- default.gaussian (PennyLane-0.30.0)
- default.mixed (PennyLane-0.30.0)
- default.qubit (PennyLane-0.30.0)
- default.qubit.autograd (PennyLane-0.30.0)
- default.qubit.jax (PennyLane-0.30.0)
- default.qubit.tf (PennyLane-0.30.0)
- default.qubit.torch (PennyLane-0.30.0)
- default.qutrit (PennyLane-0.30.0)
- null.qubit (PennyLane-0.30.0)
- lightning.gpu (PennyLane-Lightning-GPU-0.29.1)

Thanks a lot for your help

Hey @Zohim_Chandani1! You’re using X instead of PauliX :slight_smile:. Try that out instead and see if that fixes things!

Thats weird since the below with X executes without an error:


n_qubits = 2

dev = qml.device('lightning.gpu', wires=n_qubits)

@qml.qnode(dev)
def circuit():
    for i in range(n_qubits): 
        qml.X(wires=i)

    return qml.expval(qml.PauliZ(0))


circuit()



Code snippet below throws up out of memory error. Shouldnt a 34q simulation be possible with circuit cutting?

Thanks a lot

n_qubits = 34

dev = qml.device('lightning.gpu', wires=n_qubits)

@qml.cut_circuit(auto_cutter=True)
@qml.qnode(dev)
def circuit():
    for i in range(n_qubits): 
        qml.PauliX(wires=i)

    return qml.expval(qml.PauliZ(0))

circuit()

PLException                               Traceback (most recent call last)
Cell In[4], line 3
      1 n_qubits = 34
----> 3 dev = qml.device('lightning.gpu', wires=n_qubits)
      5 @qml.cut_circuit(auto_cutter=True)
      6 @qml.qnode(dev)
      7 def circuit():
      8     for i in range(n_qubits): 

File ~/.local/lib/python3.10/site-packages/pennylane/__init__.py:326, in device(name, *args, **kwargs)
    320     raise DeviceError(
    321         f"The {name} plugin requires PennyLane versions {plugin_device_class.pennylane_requires}, "
    322         f"however PennyLane version {__version__} is installed."
    323     )
    325 # Construct the device
--> 326 dev = plugin_device_class(*args, **options)
    328 # Once the device is constructed, we set its custom expansion function if
    329 # any custom decompositions were specified.
    330 if custom_decomps is not None:

File ~/.local/lib/python3.10/site-packages/pennylane_lightning_gpu/lightning_gpu.py:217, in LightningGPU.__init__(self, wires, sync, c_dtype, shots, batch_obs)
    215     raise TypeError(f"Unsupported complex Type: {c_dtype}")
    216 super().__init__(wires, shots=shots, r_dtype=r_dtype, c_dtype=c_dtype)
--> 217 self._gpu_state = _gpu_dtype(c_dtype)(self.num_wires)
    218 self._create_basis_state_GPU(0)
    219 self._sync = sync

PLException: [/project/pennylane_lightning_gpu/src/util/DataBuffer.hpp][Line:37][Method:DataBuffer]: Error in PennyLane Lightning: out of memory

Thats weird since the below with X executes without an error:

Yep! X is the position operator in continuous variables :sweat_smile:. It’s still a pennylane operation :slight_smile:. https://docs.pennylane.ai/en/stable/code/api/pennylane.X.html?highlight=X

Shouldnt a 34q simulation be possible with circuit cutting?

It really depends on the cutting procedure and the circuit itself. With the simple circuit you have, though, there’s not really a place to put a circuit cut. I think you’re maybe wanting the circuit to be separated into, for example, two 17-qubit circuits, which isn’t necessarily circuit cutting in spirit. You’ve created a product state — you don’t need a 34-qubit circuit, you can just create 34 different 1-qubit circuits.