Lightning GPU Support

Hi! Pennylane new release 0.32 doesn’t support GPU? With the last version I have no problems.

dev_train = qml.device("lightning.gpu", wires=WIRES + 1, shots=SHOTS)

If you want help with diagnosing an error, please put the full error message below:

ImportError                               Traceback (most recent call last)
Cell In[41], line 1
----> 1 dev_train = qml.device("lightning.gpu", wires=WIRES + 1, shots=SHOTS)

File ~/.local/lib/python3.10/site-packages/pennylane/__init__.py:336, in device(name, *args, **kwargs)
    333 options.update(kwargs)
    335 # loads the device class
--> 336 plugin_device_class = plugin_devices[name].load()
    338 if Version(version()) not in SimpleSpec(plugin_device_class.pennylane_requires):
    339     raise DeviceError(
    340         f"The {name} plugin requires PennyLane versions {plugin_device_class.pennylane_requires}, "
    341         f"however PennyLane version {__version__} is installed."
    342     )

File /usr/lib/python3/dist-packages/pkg_resources/__init__.py:2465, in EntryPoint.load(self, require, *args, **kwargs)
   2463 if require:
   2464     self.require(*args, **kwargs)
-> 2465 return self.resolve()

File /usr/lib/python3/dist-packages/pkg_resources/__init__.py:2471, in EntryPoint.resolve(self)
   2467 def resolve(self):
   2468     """
   2469     Resolve the entry point from its module and attrs.
   2470     """
-> 2471     module = __import__(self.module_name, fromlist=['__name__'], level=0)
   2472     try:
   2473         return functools.reduce(getattr, self.attrs, module)

File ~/.local/lib/python3.10/site-packages/pennylane_lightning_gpu/__init__.py:17
     14 """Top level PennyLane-Lightning-GPU module."""
     16 from ._version import __version__
---> 17 from .lightning_gpu import LightningGPU

File ~/.local/lib/python3.10/site-packages/pennylane_lightning_gpu/lightning_gpu.py:38
     24 import concurrent.futures
     26 from pennylane import (
     27     math,
     28     QubitDevice,
   (...)
     36     QubitStateVector,
     37 )
---> 38 from pennylane_lightning import LightningQubit
     39 from pennylane.operation import Tensor, Operation
     40 from pennylane.ops.op_math import Adjoint

ImportError: cannot import name 'LightningQubit' from 'pennylane_lightning' (unknown location)

And, finally, make sure to include the versions of your packages. Specifically, show us the output of qml.about().

Pennylane INFO
Name: PennyLane
Version: 0.32.0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: GitHub - PennyLaneAI/pennylane: PennyLane is a cross-platform Python library for differentiable programming of quantum computers. Train a quantum computer the same way as a neural network.
Author:
Author-email:
License: Apache License 2.0
Location: /home/contepablod/.local/lib/python3.10/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml, typing-extensions
Required-by: PennyLane-Lightning, PennyLane-Lightning-GPU, PennyLane-qiskit

Platform info: Linux-5.15.90.1-microsoft-standard-WSL2-x86_64-with-glibc2.35
Python version: 3.10.12
Numpy version: 1.23.5
Scipy version: 1.10.0
Installed devices:

  • lightning.qubit (PennyLane-Lightning-0.32.0)
  • default.gaussian (PennyLane-0.32.0)
  • default.mixed (PennyLane-0.32.0)
  • default.qubit (PennyLane-0.32.0)
  • default.qubit.autograd (PennyLane-0.32.0)
  • default.qubit.jax (PennyLane-0.32.0)
  • default.qubit.tf (PennyLane-0.32.0)
  • default.qubit.torch (PennyLane-0.32.0)
  • default.qutrit (PennyLane-0.32.0)
  • null.qubit (PennyLane-0.32.0)
  • qiskit.aer (PennyLane-qiskit-0.30.1)
  • qiskit.basicaer (PennyLane-qiskit-0.30.1)
  • qiskit.ibmq (PennyLane-qiskit-0.30.1)
  • qiskit.ibmq.circuit_runner (PennyLane-qiskit-0.30.1)
  • qiskit.ibmq.sampler (PennyLane-qiskit-0.30.1)
  • lightning.gpu (PennyLane-Lightning-GPU-0.30.0)

Hello @contepablod, lightning.gpu requires the NVIDIA cuQuantum SDK.

Reference:
https://docs.pennylane.ai/projects/lightning-gpu/en/latest/devices.html

Thanks @kevinkawchak. Trying installing the drivers!

Hi @kevinkawchak, Ihave installed the requirements, but the problems remains the same:

NVIDIA INFO
Mon Sep 4 12:29:52 2023
±--------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.104.05 Driver Version: 537.13 CUDA Version: 12.2 |
|-----------------------------------------±---------------------±---------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+======================+======================|
| 0 NVIDIA GeForce GTX 1650 Ti On | 00000000:01:00.0 On | N/A |
| N/A 48C P8 4W / 50W | 932MiB / 4096MiB | 15% Default |
| | | N/A |
±----------------------------------------±---------------------±---------------------+

±--------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=======================================================================================|
| 0 N/A N/A 333 G /Xwayland N/A |
±--------------------------------------------------------------------------------------+

CUDA INFO
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2023 NVIDIA Corporation
Built on Tue_Aug_15_22:02:13_PDT_2023
Cuda compilation tools, release 12.2, V12.2.140
Build cuda_12.2.r12.2/compiler.33191640_0

Hi @contepablod

It looks like your version of pennylane is 0.32 but lightning.gpu is 0.30.

If you upgrade lightning.gpu with pip install pennylane-lightning-gpu --upgrade I suspect this will fix your problem. The latest version of lightning.qubit has some architectural changes that require all packages to be at the same version. Feel free to try the above and let me know if it succeeds.

Thanks @mlxd! Actually that changed the error so i am moving on :upside_down_face:

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
File ~/.local/lib/python3.10/site-packages/pennylane_lightning_gpu/lightning_gpu.py:52
     51 try:
---> 52     from .lightning_gpu_qubit_ops import (
     53         LightningGPU_C128,
     54         LightningGPU_C64,
     55         AdjointJacobianGPU_C128,
     56         AdjointJacobianGPU_C64,
     57         device_reset,
     58         is_gpu_supported,
     59         get_gpu_arch,
     60         DevPool,
     61         DevTag,
     62         NamedObsGPU_C64,
     63         NamedObsGPU_C128,
     64         TensorProdObsGPU_C64,
     65         TensorProdObsGPU_C128,
     66         HamiltonianGPU_C64,
     67         HamiltonianGPU_C128,
     68         SparseHamiltonianGPU_C64,
     69         SparseHamiltonianGPU_C128,
     70         OpsStructGPU_C128,
     71         OpsStructGPU_C64,
     72         PLException,
     73     )
     75     try:

ImportError: libcudart.so.11.0: cannot open shared object file: No such file or directory

During handling of the above exception, another exception occurred:

NameError                                 Traceback (most recent call last)
Cell In[51], line 1
----> 1 dev_train = qml.device("lightning.gpu", wires=WIRES + 1, shots=SHOTS)

File ~/.local/lib/python3.10/site-packages/pennylane/__init__.py:336, in device(name, *args, **kwargs)
    333 options.update(kwargs)
    335 # loads the device class
--> 336 plugin_device_class = plugin_devices[name].load()
    338 if Version(version()) not in SimpleSpec(plugin_device_class.pennylane_requires):
    339     raise DeviceError(
    340         f"The {name} plugin requires PennyLane versions {plugin_device_class.pennylane_requires}, "
    341         f"however PennyLane version {__version__} is installed."
    342     )

File /usr/lib/python3/dist-packages/pkg_resources/__init__.py:2465, in EntryPoint.load(self, require, *args, **kwargs)
   2463 if require:
   2464     self.require(*args, **kwargs)
-> 2465 return self.resolve()

File /usr/lib/python3/dist-packages/pkg_resources/__init__.py:2471, in EntryPoint.resolve(self)
   2467 def resolve(self):
   2468     """
   2469     Resolve the entry point from its module and attrs.
   2470     """
-> 2471     module = __import__(self.module_name, fromlist=['__name__'], level=0)
   2472     try:
   2473         return functools.reduce(getattr, self.attrs, module)

File ~/.local/lib/python3.10/site-packages/pennylane_lightning_gpu/__init__.py:17
     14 """Top level PennyLane-Lightning-GPU module."""
     16 from ._version import __version__
---> 17 from .lightning_gpu import LightningGPU

File ~/.local/lib/python3.10/site-packages/pennylane_lightning_gpu/lightning_gpu.py:111
    108         raise ValueError(f"CUDA device is an unsupported version: {get_gpu_arch()}")
    110     CPP_BINARY_AVAILABLE = True
--> 111 except (ModuleNotFoundError, ImportError, ValueError, PLException) as e:
    112     warn(str(e), UserWarning)
    113     CPP_BINARY_AVAILABLE = False

NameError: name 'PLException' is not defined

Seems that Penny does not support CUDA12+?

Glad to help.

Yes, this is correct — currently lightning.gpu supports CUDA 11.5+ only. We plan to migrate to CUDA 12 in the coming months, but for now we require a CUDA 11 runtime library, CUDA 11 cublas library, and a CUDA 11 version of cuQuantum’s custatevec library. You may be able to pip install these, assuming you have a recent driver installed:

python3 -m venv pyenv
source ./pyenv/bin/activate
python -m pip install pennylane pennylane-lightning-gpu nvidia-cuda-runtime-cu11 nvidia-cublas-cu11 custatevec-cu11

Once installed, you may be able to ensure the required libraries are loaded and usable via:

export LD_LIBRARY_PATH=/path/to/pyenv/lib/python3.10/site-packages/nvidia/cublas/lib:/path/to/pyenv/lib/python3.10/site-packages/nvidia/cuda_runtime/lib:$LD_LIBRARY_PATH
ldd /path/to/pyenv/lib/python3.10/site-packages/pennylane_lightning_gpu/lightning_gpu_qubit_ops.cpython-310-x86_64-linux-gnu.so
python myscript.py

which can verify if the libraries satisfy the dependencies of lightning.gpus compiled module, and runs your script. Though, this may not work in practice, and may require a full installation of CUDA 11 to function correctly, but I suggested the above as a quicker path to verify if you wish.

Feel free to let us know if we can be any further help.

1 Like

Thanks, i will try to downgrade to CUDA 11+ and let you know!

@mlxd thanks! it worked with CUDA 11.8.
Maybe you can help me with these. I wan to draw a circuit and the pennylane drawer shows an error of size
qml.draw_mpl(circuit_train, style="pennylane")(image.flatten(), initial_weights
plt.show()
Error:

ValueError                                Traceback (most recent call last)
Cell In[66], line 1
----> 1 qml.draw_mpl(circuit_train, style="pennylane")(image.flatten(), initial_weights)
      2 plt.show()

File ~/.local/lib/python3.10/site-packages/pennylane/drawer/draw.py:548, in _draw_mpl_qnode..wrapper(*args, **kwargs_qnode)
    544     qnode.expansion_strategy = original_expansion_strategy
    546 _wire_order = wire_order or getattr(qnode.device, "wires", None)
--> 548 return tape_mpl(
    549     qnode.qtape,
    550     wire_order=_wire_order,
    551     show_all_wires=show_all_wires,
    552     decimals=decimals,
    553     style=style,
    554     **kwargs,
    555 )

File ~/.local/lib/python3.10/site-packages/pennylane/drawer/tape_mpl.py:391, in tape_mpl(tape, wire_order, show_all_wires, decimals, style, **kwargs)
    389     _set_style(style)
    390 try:
--> 391     return _tape_mpl(
    392         tape, wire_order=wire_order, show_all_wires=show_all_wires, decimals=decimals, **kwargs
    393     )
    394 finally:
    395     if update_style:
    396         # we don't want to mess with how it modifies whether the interface is interactive
    397         # but we want to restore everything else

File ~/.local/lib/python3.10/site-packages/pennylane/drawer/tape_mpl.py:181, in _tape_mpl(tape, wire_order, show_all_wires, decimals, **kwargs)
    174             if control_wires:
    175                 drawer.ctrl(
    176                     layer,
    177                     control_wires,
    178                     wires_target=target_wires,
    179                     control_values=control_values,
    180                 )
--> 181             drawer.box_gate(
    182                 layer,
    183                 target_wires,
    184                 op.label(decimals=decimals),
    185                 box_options={
    186                     "zorder": 4
    187                 },  # make sure box and text above control wires if controlled
    188                 text_options={"zorder": 5},
    189                 active_wire_notches=active_wire_notches,
    190             )
    192 # store wires we've already drawn on
    193 # max one measurement symbol per wire
    194 measured_wires = Wires([])

File ~/.local/lib/python3.10/site-packages/pennylane/drawer/mpldrawer.py:477, in MPLDrawer.box_gate(self, layer, wires, text, box_options, text_options, **kwargs)
    474 # factor of 2 makes it look nicer
    475 max_height = box_height - 2 * margin + 2 * self._pad
--> 477 w, h = self._text_dims(text_obj)
    479 # rotate the text
    480 if (box_min != box_max) and (w > max_width) and (w > h):

File ~/.local/lib/python3.10/site-packages/pennylane/drawer/mpldrawer.py:539, in MPLDrawer._text_dims(self, text_obj)
    522 def _text_dims(self, text_obj):
    523     """Get width and height of text object in data coordinates.
    524 
    525     See `this tutorial `_
   (...)
    537         height (float): the height of the text in data coordinates
    538     """
--> 539     renderer = self._fig.canvas.get_renderer()
    541     # https://matplotlib.org/stable/api/_as_gen/matplotlib.artist.Artist.get_window_extent.html
    542     # Quote: "Be careful when using this function, the results will not update if the artist
    543     # window extent of the artist changes. "
    544     # But I haven't encountered any issues yet and don't see a better solution
    545     bbox = text_obj.get_window_extent(renderer)

File ~/.local/lib/python3.10/site-packages/matplotlib/_api/deprecation.py:384, in delete_parameter..wrapper(*inner_args, **inner_kwargs)
    379 @functools.wraps(func)
    380 def wrapper(*inner_args, **inner_kwargs):
    381     if len(inner_args) <= name_idx and name not in inner_kwargs:
    382         # Early return in the simple, non-deprecated case (much faster than
    383         # calling bind()).
--> 384         return func(*inner_args, **inner_kwargs)
    385     arguments = signature.bind(*inner_args, **inner_kwargs).arguments
    386     if is_varargs and arguments.get(name):

File ~/.local/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:411, in FigureCanvasAgg.get_renderer(self, cleared)
    409 reuse_renderer = (self._lastKey == key)
    410 if not reuse_renderer:
--> 411     self.renderer = RendererAgg(w, h, self.figure.dpi)
    412     self._lastKey = key
    413 elif cleared:

File ~/.local/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:84, in RendererAgg.__init__(self, width, height, dpi)
     82 self.width = width
     83 self.height = height
---> 84 self._renderer = _RendererAgg(int(width), int(height), dpi)
     85 self._filter_renderers = []
     87 self._update_methods()

ValueError: Image size of 205700x1800 pixels is too large. It must be less than 2^16 in each direction.

Any insights how to render it? image.flatten has shape (1024,) and weights (1,10). Numbers of wires 16

Hi @contepablod, you can use qml.draw(), which is not as nice as the mpl drawer but it won’t show the size error that you’re seeing.

You can use it with print(qml.draw(circuit)(params)) where params are the parameters that your circuit takes (initial_weights I guess in your case).

I hope this works for what you need!

By the way, we have a new PennyLane survey. Let us know your thoughts about PennyLane in order to keep bringing you amazing features :sparkles:.

Thnaks @CatalinaAlbornoz. I’ll try that. Btw, I would be awesome to have that pennylane style for this amount of qubits. Another question if you can help me, do it have to do a measure to reset a qubit state using the new feature?

Hi @contepablod ,

I agree with you on part number one! Unfortunately for such large circuits I think it would still look very bad but maybe you can do a workaround by creating a custom gate or something similar that can reduce the size of the printed circuit.

Regarding your second question, you do indeed need to measure in order to reset qubits at the moment. You can learn how to do this here. I’d love to learn more about your need to reset without measuring. What is your use case?

@CatalinaAlbornoz i am using swap gates to reset qubits, so i need to add extra-ones, so i want to reduce the numbers only by resetting the existing ones

@qml.qnode(test_dev)
def circuit_test(features):
    # Amplitude Embedding
    qml.AmplitudeEmbedding(
        features=features, wires=range(0, NUM_LAT + NUM_TRASH), normalize=True
    )
    # Unitary Operation (U)
    qml.BasicEntanglerLayers(
        weights=optimal_result, wires=range(0, NUM_LAT + NUM_TRASH), rotation=qml.RY
    )
    # Reset trash space qubits to the |0> state
    for i in range(NUM_LAT, NUM_LAT + NUM_TRASH):
        qml.SWAP(wires=[i, NUM_TRASH + i])
    # Inversed BEL (Udagger)
    qml.CNOT(wires=[NUM_LAT + NUM_TRASH - 1, 0])
    for i in range(NUM_LAT + NUM_TRASH - 1, 0, -1):
        qml.CNOT(wires=[i - 1, i])
    for i in range(0, NUM_LAT + NUM_TRASH):
        qml.RY(-optimal_result[0][i], wires=i)
    return qml.density_matrix(wires=range(0, int((NUM_LAT + NUM_TRASH) / 2)))

Hi @contepablod,

I don’t really understand why you would want to reset some of your qubits here, but the way measurement and reset works at the moment (as mentioned in our latest blog post) you do indeed need extra qubits. We are looking into ways of improving this in the future so definitely stay tuned for this.

From your code I noticed that you may benefit from using qml.adjoint for simplicity in the last part of your circuit. You can try it out and let me know how it goes!

@CatalinaAlbornoz it’s an autoencoder, so I am trying to reset those qubits (trash space) because i dont need them when i extract the statevector at the end. you may check this qiskit (sorry jaja) tutotrial: The Quantum Autoencoder — Qiskit Machine Learning 0.6.1 documentation
I am trying to replicate the same in penny.

Ah I now see what you want to do @contepablod!

@sophchoe made a continuous-variable quantum-classical auto-encoder using PennyLane and the PennyLane-SF plugin a while ago. You can see her work here. The code in this repo uses a very old version of PennyLane but maybe it can inspire you to create an autoencoder that works fully on PennyLane with the latest version (v0.32) and with the gate-based model instead of the CV model.

At the moment our reset functionality (as explained here) uses qml.defer_measurements under the hood, so you do need extra qubits unfortunately. However, we’re exploring how to support qubit reuse without consuming additional qubits so this may come in future PennyLane releases.

If you’re ok with using a few extra qubits I would recommend using qml.measure() in order to reset your qubits. I know that you don’t specifically need the output of this measurement, but this is a good way to reset them. In the example below qubit 1 is being reset to the |0\rangle state.

m = qml.measure(1, reset=True) 

Please let me know if you have any questions about this.

I hope this helps!