Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cupy matrices #1558

Merged
merged 36 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
295ccb1
fix: some fixes for cupy
BrunoLiegiBastonLiegi Jan 21, 2025
ce72115
fix: casting to numpy in optimizers
BrunoLiegiBastonLiegi Jan 21, 2025
745f605
fix: specifying dtype
BrunoLiegiBastonLiegi Jan 22, 2025
dd70ea9
feat: playing around with the selfhosted workflow
BrunoLiegiBastonLiegi Jan 22, 2025
1ed9f2b
feat: trying out numba threads fix
BrunoLiegiBastonLiegi Jan 23, 2025
40c5b69
build: lock update
BrunoLiegiBastonLiegi Jan 23, 2025
b43767e
feat: update actions/upload-artifact
BrunoLiegiBastonLiegi Jan 23, 2025
236fee7
feat: forcing numba threads to 1 in clifford backend
BrunoLiegiBastonLiegi Jan 24, 2025
35cfeb7
Merge branch 'master' into selfhosted_workflow
BrunoLiegiBastonLiegi Jan 28, 2025
6a4c31c
fix: removing explicit NUMBA_NUM_THREADS setting
BrunoLiegiBastonLiegi Jan 30, 2025
dcb9379
feat: restore original workflow
BrunoLiegiBastonLiegi Jan 30, 2025
964a45f
feat: cupy fixes
BrunoLiegiBastonLiegi Jan 30, 2025
1643a19
Merge branch 'cupy_matrices' into selfhosted_workflow
BrunoLiegiBastonLiegi Jan 31, 2025
b4c662a
Merge branch 'master' into cupy_matrices
BrunoLiegiBastonLiegi Jan 31, 2025
ec805dc
feat: added fixture for numba threads setting
BrunoLiegiBastonLiegi Jan 31, 2025
6a7c610
Merge branch 'cupy_matrices' into selfhosted_workflow
BrunoLiegiBastonLiegi Jan 31, 2025
5281a3a
build: updated qibojit dep
BrunoLiegiBastonLiegi Jan 31, 2025
445013e
feat: removing manual thread setting
BrunoLiegiBastonLiegi Jan 31, 2025
1e093f8
fix: import at top level
BrunoLiegiBastonLiegi Jan 31, 2025
3bb38f9
Merge pull request #1561 from qiboteam/selfhosted_workflow
BrunoLiegiBastonLiegi Jan 31, 2025
a6e59bf
build: bump up cupy version
BrunoLiegiBastonLiegi Feb 3, 2025
e8f2397
refactor: Propagate qibojit changes in Qibo
andrea-pasquale Feb 3, 2025
e1a9243
test: Adapt list of backends for GPU
andrea-pasquale Feb 3, 2025
73729c1
fix: Fixer for pytorch and qibojit-numba
andrea-pasquale Feb 3, 2025
d2ff7a6
fix: fixing some cuquantum tests
BrunoLiegiBastonLiegi Feb 3, 2025
851cd1e
fix: some more test fixing
BrunoLiegiBastonLiegi Feb 3, 2025
c44a8ec
fix: further minor test fixes
BrunoLiegiBastonLiegi Feb 3, 2025
2e465a4
Merge branch 'cupy_matrices' into fix_cuquantum
andrea-pasquale Feb 3, 2025
aab1d45
build: Update qibojit branch
andrea-pasquale Feb 3, 2025
bb9de64
fix: GST tests
andrea-pasquale Feb 3, 2025
e9ebc82
build: Revert branch to cupy_matrices
andrea-pasquale Feb 4, 2025
48143d7
Merge pull request #1573 from qiboteam/fix_cuquantum
andrea-pasquale Feb 4, 2025
bed410f
fix: fixing BM20 and dropping support for AG04
BrunoLiegiBastonLiegi Feb 4, 2025
75c85d2
fix: adding a no cover
BrunoLiegiBastonLiegi Feb 4, 2025
a1de6c0
build: Revert qibojit to main branch
andrea-pasquale Feb 5, 2025
bca0443
fix: moving the pragma to the right place
BrunoLiegiBastonLiegi Feb 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,283 changes: 1,375 additions & 908 deletions poetry.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ ipython = "^8.10.0"
qulacs = { version = "^0.6.4", markers = "(sys_platform == 'darwin' and python_version > '3.9') or sys_platform != 'darwin'" }
seaborn = "^0.13.2"
ipykernel = "^6.29.4"
qibojit = { git = "https://github.com/qiboteam/qibojit.git" }
qibojit = { git = "https://github.com/qiboteam/qibojit.git", branch="cupy_matrices" }

[tool.poetry.group.tests]
optional = true
Expand All @@ -70,7 +70,7 @@ pytest-cov = "^4.0.0"
pylint = "3.1.0"
matplotlib = "^3.7.0"
torch = "^2.1.1,<2.4"
qibojit = { git = "https://github.com/qiboteam/qibojit.git" }
qibojit = { git = "https://github.com/qiboteam/qibojit.git", branch="cupy_matrices" }
qibotn = { git = "https://github.com/qiboteam/qibotn.git" }
qiboml = { git = "https://github.com/qiboteam/qiboml.git" }
stim = "^1.12.0"
Expand All @@ -89,19 +89,19 @@ test-docs = "make -C doc doctest"
optional = true

[tool.poetry.group.cuda11.dependencies]
cupy-cuda11x = "^12.0.0"
cupy-cuda11x = "^13.1.0"
cuquantum-python-cu11 = "^23.3.0"
qibojit = { git = "https://github.com/qiboteam/qibojit.git" }
qibojit = { git = "https://github.com/qiboteam/qibojit.git", branch="cupy_matrices" }
qibotn = { git = "https://github.com/qiboteam/qibotn.git" }


[tool.poetry.group.cuda12]
optional = true

[tool.poetry.group.cuda12.dependencies]
cupy-cuda12x = "^12.0.0"
cupy-cuda12x = "^13.1.0"
cuquantum-python-cu12 = "^23.3.0"
qibojit = { git = "https://github.com/qiboteam/qibojit.git" }
qibojit = { git = "https://github.com/qiboteam/qibojit.git", branch="cupy_matrices" }
qibotn = { git = "https://github.com/qiboteam/qibotn.git" }

[tool.poetry.extras]
Expand Down
4 changes: 4 additions & 0 deletions src/qibo/backends/clifford.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ def __init__(self, engine=None):
if engine == "numpy":
pass
elif engine == "numba":
from numba import set_num_threads
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from numba import set_num_threads
from numba import set_num_threads # pylint: disable=C0415


set_num_threads(1)

from qibojit.backends import ( # pylint: disable=C0415
clifford_operations_cpu,
)
Expand Down
4 changes: 3 additions & 1 deletion src/qibo/backends/npmatrices.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ def __init__(self, dtype):
self.np = np

def _cast(self, x, dtype):
return self.np.array(x, dtype=dtype)
if isinstance(x, list):
return self.np.array(x, dtype=dtype)
return x.astype(dtype)

@cached_property
def H(self):
Expand Down
8 changes: 5 additions & 3 deletions src/qibo/optimizers.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ def myloss(parameters, circuit):
RuntimeError,
"The keyword 'bounds' cannot be used with the cma optimizer. Please use 'options' instead as defined by the cma documentation: ex. options['bounds'] = [0.0, 1.0].",
)
return cmaes(loss, initial_parameters, args, callback, options)
return cmaes(
loss, backend.to_numpy(initial_parameters), args, callback, options
)
elif method == "sgd":
from qibo.backends import _check_backend

Expand Down Expand Up @@ -208,13 +210,13 @@ def newtonian(
callback=callback,
options=options,
)
m = o.run(initial_parameters)
m = o.run(backend.to_numpy(initial_parameters))
else:
from scipy.optimize import minimize

m = minimize(
loss,
initial_parameters,
backend.to_numpy(initial_parameters),
args=args,
method=method,
jac=jac,
Expand Down
12 changes: 6 additions & 6 deletions src/qibo/tomography/gate_set_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def _gate_tomography(
gate = gate.__class__(*gate.qubits, **gate.init_kwargs)

# GST for empty circuit or with gates
matrix_jk = np.zeros((4**nqubits, 4**nqubits))
matrix_jk = 1j * np.zeros((4**nqubits, 4**nqubits))
for k in range(4**nqubits):
circ = Circuit(nqubits, density_matrix=True)
circ.add(_prepare_state(k, nqubits))
Expand All @@ -211,7 +211,7 @@ def _gate_tomography(
backend.execute_circuit(new_circ, nshots=nshots).frequencies()
)
matrix_jk[j, k] = exp_val
return matrix_jk
return backend.cast(matrix_jk, dtype=matrix_jk.dtype)


def GST(
Expand Down Expand Up @@ -327,20 +327,20 @@ def GST(
if np.linalg.det(gauge_matrix) == 0:
raise_error(ValueError, "Matrix is not invertible")
else:
gauge_matrix = np.array(
gauge_matrix = backend.cast(
[[1, 1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 1], [1, -1, 0, 0]]
)
PL_matrices = []
gauge_matrix_1q = gauge_matrix
gauge_matrix_2q = np.kron(gauge_matrix, gauge_matrix)
gauge_matrix_2q = backend.np.kron(gauge_matrix, gauge_matrix)
for matrix in matrices:
gauge_matrix = gauge_matrix_1q if matrix.shape[0] == 4 else gauge_matrix_2q
empty = empty_matrices[0] if matrix.shape[0] == 4 else empty_matrices[1]
PL_matrices.append(
gauge_matrix
@ np.linalg.inv(empty)
@ backend.np.linalg.inv(empty)
@ matrix
@ np.linalg.inv(gauge_matrix)
@ backend.np.linalg.inv(gauge_matrix)
)
matrices = PL_matrices

Expand Down
20 changes: 6 additions & 14 deletions src/qibo/transpiler/unitary_decompositions.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ def u3_decomposition(unitary, backend):
minus = backend.np.angle(su2[1, 0])
phi = plus + minus
lam = plus - minus

return theta, phi, lam
# explicit conversion to float to avoid issue on GPU
return float(theta), float(phi), float(lam)


def calculate_psi(unitary, backend, magic_basis=magic_basis):
Expand All @@ -51,16 +51,6 @@ def calculate_psi(unitary, backend, magic_basis=magic_basis):
Returns:
ndarray: Eigenvectors in the computational basis and eigenvalues of :math:`U^{T} U`.
"""

if backend.__class__.__name__ in [
"CupyBackend",
"CuQuantumBackend",
]: # pragma: no cover
raise_error(
NotImplementedError,
f"{backend.__class__.__name__} does not support `linalg.eig.`",
)

magic_basis = backend.cast(magic_basis)
unitary = backend.cast(unitary)
# write unitary in magic basis
Expand All @@ -71,10 +61,12 @@ def calculate_psi(unitary, backend, magic_basis=magic_basis):
)
# construct and diagonalize UT_U
ut_u = backend.np.transpose(u_magic, (1, 0)) @ u_magic
if backend.__class__.__name__ != "PyTorchBackend":
if backend.__class__.__name__ not in ("PyTorchBackend", "TensorflowBackend"):
# eig seems to have a different behavior based on backend/hardware,
# use np.round to increase precision seems to fix the issue
eigvals, psi_magic = np.linalg.eig(np.round(ut_u, decimals=20))
eigvals, psi_magic = backend.calculate_eigenvectors(
np.round(ut_u, decimals=20), hermitian=False
)
else:
eigvals, psi_magic = backend.calculate_eigenvectors(ut_u, hermitian=False)
# orthogonalize eigenvectors in the case of degeneracy (Gram-Schmidt)
Expand Down
7 changes: 6 additions & 1 deletion tests/test_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from qibo import construct_backend, gates, list_available_backends, set_backend
from qibo.backends import MetaBackend

from .conftest import AVAILABLE_BACKENDS

####################### Test `matrix` #######################
GATES = [
("H", (0,), np.array([[1, 1], [1, -1]]) / np.sqrt(2)),
Expand Down Expand Up @@ -119,7 +121,10 @@ def test_list_available_backends():
available_backends = {
"numpy": True,
"qulacs": qulacs,
"qibojit": {"numba": True, "cupy": False, "cuquantum": False},
"qibojit": {
platform: any(platform in backend for backend in AVAILABLE_BACKENDS)
for platform in ["numba", "cupy", "cuquantum"]
},
"qibolab": False,
"qibo-cloud-backends": False,
"qibotn": {"cutensornet": False, "qutensornet": True},
Expand Down
8 changes: 4 additions & 4 deletions tests/test_backends_clifford.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import numpy as np
import pytest
from qiboml.backends import PyTorchBackend, TensorflowBackend

from qibo import Circuit, gates, get_backend, set_backend
from qibo.backends import CliffordBackend, NumpyBackend
Expand All @@ -16,9 +15,10 @@


def construct_clifford_backend(backend):
if (
isinstance(backend, (TensorflowBackend, PyTorchBackend))
or backend.__class__.__name__ == "CuQuantumBackend"
if backend.__class__.__name__ in (
"TensorflowBackend",
"PyTorchBackend",
"CuQuantumBackend",
):
with pytest.raises(NotImplementedError):
clifford_backend = CliffordBackend(backend.name)
Expand Down
8 changes: 2 additions & 6 deletions tests/test_backends_qibotn.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import os

from qibo import get_backend, get_threads, set_backend

# Force quimb to use qibojit default number of threads.
os.environ["NUMBA_NUM_THREADS"] = f"{get_threads()}"
from qibotn.backends.quimb import QuimbBackend

from qibo import get_backend, set_backend


def test_backend_qibotn():
set_backend(backend="qibotn", platform="qutensornet", runcard=None)
Expand Down
3 changes: 2 additions & 1 deletion tests/test_models_variational.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ def test_vqe(backend, method, options, compile, filename):

def callback(parameters, loss_values=loss_values, vqe=v):
vqe.circuit.set_parameters(parameters)
loss_values.append(vqe.hamiltonian.expectation(vqe.circuit().state()))
state = vqe.backend.execute_circuit(vqe.circuit).state()
loss_values.append(vqe.hamiltonian.expectation(state))

best, params, _ = v.minimize(
initial_parameters,
Expand Down
8 changes: 4 additions & 4 deletions tests/test_quantum_info_clifford.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import numpy as np
import pytest
from qiboml.backends import PyTorchBackend, TensorflowBackend

from qibo import Circuit, gates, matrices
from qibo.backends import CliffordBackend
Expand All @@ -18,9 +17,10 @@


def construct_clifford_backend(backend):
if (
isinstance(backend, (TensorflowBackend, PyTorchBackend))
or backend.__class__.__name__ == "CuQuantumBackend"
if backend.__class__.__name__ in (
"TensorflowBackend",
"PyTorchBackend",
"CuQuantumBackend",
):
with pytest.raises(NotImplementedError):
clifford_backend = CliffordBackend(backend.name)
Expand Down
23 changes: 2 additions & 21 deletions tests/test_quantum_info_entropies.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,17 +436,8 @@ def test_von_neumann_entropy(backend, base, check_hermitian):
state, base=base, check_hermitian="False", backend=backend
)

if backend.__class__.__name__ in ["CupyBackend", "CuQuantumBackend"]:
with pytest.raises(NotImplementedError):
state = random_unitary(4, backend=backend)
test = von_neumann_entropy(
state, base=base, check_hermitian=True, backend=backend
)
else:
state = random_unitary(4, backend=backend)
test = von_neumann_entropy(
state, base=base, check_hermitian=True, backend=backend
)
state = random_unitary(4, backend=backend)
test = von_neumann_entropy(state, base=base, check_hermitian=True, backend=backend)

state = np.array([1.0, 0.0])
state = backend.cast(state, dtype=state.dtype)
Expand Down Expand Up @@ -842,16 +833,6 @@ def test_entanglement_entropy(backend, bipartition, base, check_hermitian):
check_hermitian=check_hermitian,
backend=backend,
)
if backend.__class__.__name__ == "CupyBackend":
with pytest.raises(NotImplementedError):
state = random_unitary(4, backend=backend)
test = entanglement_entropy(
state,
bipartition=bipartition,
base=base,
check_hermitian=True,
backend=backend,
)

# Bell state
state = np.array([1.0, 0.0, 0.0, 1.0]) / np.sqrt(2)
Expand Down
10 changes: 6 additions & 4 deletions tests/test_tomography_gate_set_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,10 @@ def test_gate_tomography_noise_model(backend):
)
@pytest.mark.parametrize("pauli_liouville", [False, True])
def test_GST(backend, target_gates, pauli_liouville):
T = np.array([[1, 1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 1], [1, -1, 0, 0]])
T = backend.cast(T, dtype=T.dtype)
T = np.array(
[[1.0, 1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 1], [1, -1, 0, 0]], dtype=np.complex128
)
T = backend.cast(T)
Comment on lines +219 to +222
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
T = np.array(
[[1.0, 1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 1], [1, -1, 0, 0]], dtype=np.complex128
)
T = backend.cast(T)
T = backend.cast(
[[1.0, 1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 1], [1, -1, 0, 0]], dtype=np.complex128
)

target_matrices = [g.matrix(backend=backend) for g in target_gates]
# superoperator representation of the target gates in the Pauli basis
target_matrices = [
Expand All @@ -237,11 +239,11 @@ def test_GST(backend, target_gates, pauli_liouville):
pauli_liouville=pauli_liouville,
backend=backend,
)
T_2q = np.kron(T, T)
T_2q = backend.np.kron(T, T)
for target, estimate in zip(target_matrices, approx_gates):
if not pauli_liouville:
G = empty_1q if estimate.shape[0] == 4 else empty_2q
G_inv = np.linalg.inv(G)
G_inv = backend.np.linalg.inv(G)
T_matrix = T if estimate.shape[0] == 4 else T_2q
estimate = T_matrix @ G_inv @ estimate @ G_inv
backend.assert_allclose(
Expand Down
Loading