How to get the matrix of circuit in cuda?

hi,
I’m trying to get the unitaries of a circuit with inputs in cuda, It doesn’t work…
It works well for the CPU. When I change the device to cuda, it fails. :smiling_face_with_tear:
Is there any way I can fix this?

import torch
import pennylane as qml

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
dev = qml.device("lightning.gpu", wires=2)

# device = 'cpu'
# dev = qml.device("default.qubit", wires=2)
@qml.qnode(dev,interface = 'torch')
def circuit(theta):
    qml.RX(theta, wires=1) 
    qml.PauliZ(wires=0)
    qml.CNOT(wires=[0, 1])
    return qml.expval(qml.Identity(wires=[0,1]))

def cost(theta):
    print('theta device',theta.device)
    matrix = qml.matrix(circuit)(theta)
    print('matrix device:', matrix.device)
    return matrix
params = torch.tensor(torch.rand(5)).to(device)
print('input params:', params.device)
u = cost(torch.tensor(params,requires_grad=True))
print('u',u)
print('u device', u.device)

Hey @Jian_1_2! Can you print qml.about() in the same environment where you’re trying to run this code?

Hi, @isaacdevlugt here is my pennylane information:

Name: PennyLane
Version: 0.33.0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/PennyLaneAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: /home/zhange/anaconda3/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

Platform info:           Linux-6.2.0-36-generic-x86_64-with-glibc2.35
Python version:          3.10.9
Numpy version:           1.23.5
Scipy version:           1.10.1
Installed devices:
- lightning.gpu (PennyLane-Lightning-GPU-0.33.1)
- lightning.qubit (PennyLane-Lightning-0.33.1)
- default.gaussian (PennyLane-0.33.0)
- default.mixed (PennyLane-0.33.0)
- default.qubit (PennyLane-0.33.0)
- default.qubit.autograd (PennyLane-0.33.0)
- default.qubit.jax (PennyLane-0.33.0)
- default.qubit.legacy (PennyLane-0.33.0)
- default.qubit.tf (PennyLane-0.33.0)
- default.qubit.torch (PennyLane-0.33.0)
- default.qutrit (PennyLane-0.33.0)
- null.qubit (PennyLane-0.33.0)
None

Thanks @Jian_1_2! I need to look into this a bit more, so I’ll get back to you in a few business days. Sit tight!

@Jian_1_2 could you also share the full error message that you get when you run your code?

Here is my error information. Have a nice weekend :grin:

Traceback (most recent call last):
  File "/home/--/qml-about.py", line 23, in <module>
    u = cost(torch.tensor(params,requires_grad=True))
  File "/home/--/qml-about.py", line 18, in cost
    matrix = qml.matrix(circuit)(theta)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/qnode.py", line 1027, in __call__
    res = qml.execute(
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/interfaces/execution.py", line 612, in execute
    return post_processing(tapes)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/interfaces/execution.py", line 609, in post_processing
    return program_post_processing(program_pre_processing(results))
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/transforms/core/transform_program.py", line 86, in _apply_postprocessing_stack
    results = postprocessing(results)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/transforms/core/transform_program.py", line 56, in _batch_postprocessing
    return tuple(fn(results[sl]) for fn, sl in zip(individual_fns, slices))
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/transforms/core/transform_program.py", line 56, in <genexpr>
    return tuple(fn(results[sl]) for fn, sl in zip(individual_fns, slices))
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/ops/functions/matrix.py", line 165, in processing_fn
    params = res[0].get_parameters(trainable_only=False)
AttributeError: 'tensor' object has no attribute 'get_parameters'

@Jian_1_2 do you have cuQuantum SDK installed? This might be the issue

@isaacdevlugt I think the cuquantum is installed well:

cuquantum-python-cu11         23.3.0

And I change my code to try to fix my bugs:

import torch
import pennylane as qml
import warnings
warnings.filterwarnings('ignore')

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

dev = qml.device("lightning.gpu", wires=2, batch_obs=True)

@qml.batch_params
@qml.qnode(dev, interface='torch', diff_method='adjoint')
def circuit(theta):
    qml.RX(theta, wires=1) 
    qml.PauliZ(wires=0)
    qml.CNOT(wires=[0, 1])
    return qml.expval(qml.Identity(wires=[0,1]))


print('circuit device:', circuit.device)

def get_U(theta):
    matrix = qml.matrix(circuit)(theta)
    return matrix


params = torch.tensor(torch.rand(5)).to(device)
print('input params:', params.device)
u = get_U(torch.tensor(params,requires_grad=True))
print(u)
print('u device', u.device)

I got new errors :smiling_face_with_tear:, and this is what I exactly want to find out:

Traceback (most recent call last):
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/ops/functions/matrix.py", line 141, in matrix
    return op.matrix(wire_order=wire_order)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/operation.py", line 780, in matrix
    return expand_matrix(canonical_matrix, wires=self.wires, wire_order=wire_order)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/math/matrix_manipulation.py", line 171, in expand_matrix
    expanded_batch_matrices = [reduce(kron_interface, mats) for mats in mats_list]
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/math/matrix_manipulation.py", line 171, in <listcomp>
    expanded_batch_matrices = [reduce(kron_interface, mats) for mats in mats_list]
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/math/matrix_manipulation.py", line 129, in kron_interface
    return qml.math.kron(mat1, mat2, like=interface)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/math/multi_dispatch.py", line 151, in wrapper
    return fn(*args, **kwargs)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/math/multi_dispatch.py", line 163, in kron
    return ar.numpy.kron(*args, like=like, **kwargs)
  File "/home/--/.local/lib/python3.10/site-packages/autoray/autoray.py", line 79, in do
    return get_lib_fn(backend, fn)(*args, **kwargs)
RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu!

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/--/test_matrix.py", line 27, in <module>
    u = get_U(torch.tensor(params,requires_grad=True))
  File "/home/--/test_matrix.py", line 21, in get_U
    matrix = qml.matrix(circuit)(theta)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/qnode.py", line 1027, in __call__
    res = qml.execute(
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/interfaces/execution.py", line 612, in execute
    return post_processing(tapes)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/interfaces/execution.py", line 609, in post_processing
    return program_post_processing(program_pre_processing(results))
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/transforms/core/transform_program.py", line 86, in _apply_postprocessing_stack
    results = postprocessing(results)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/transforms/core/transform_program.py", line 56, in _batch_postprocessing
    return tuple(fn(results[sl]) for fn, sl in zip(individual_fns, slices))
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/transforms/core/transform_program.py", line 56, in <genexpr>
    return tuple(fn(results[sl]) for fn, sl in zip(individual_fns, slices))
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/ops/functions/matrix.py", line 172, in processing_fn
    result = matrix(res[0].operations[0], wire_order=wire_order)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/ops/functions/matrix.py", line 143, in matrix
    return matrix(op.expand(), wire_order=wire_order)
  File "/home/--/anaconda3/lib/python3.10/site-packages/pennylane/operation.py", line 1425, in expand
    raise DecompositionUndefinedError
pennylane.operation.DecompositionUndefinedError

The error information tells me that I use two devices: cuda and CPU. I don’t know how this bug happened:smiling_face_with_tear:, I have sent the variable to the cuda device params = torch.tensor(torch.rand(5)).to(device). The only way I find out is to put everything in the CPU, but it’s not what I want. Do you have any insight?

Hey @Jian_1_2,

This issue is coming up in a few other places on the forum (e.g., here: Quantum Transfer Learning). You’re not alone!

I spoke with someone internally and it looks like this issue might be due to the fact that putting the torch tensor on a gpu is problematic when lightning-gpu is being used as well. Lightning-gpu and torch’s gpu pipeline are entirely differerent, and lightning-gpu expects the data to be on the host right now, so that should fix it!