From 66279139c9e71b30774b31ea7c65f2feaaaf75c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Alfredo=20Nu=C3=B1ez=20Meneses?= Date: Wed, 11 Sep 2024 10:07:27 -0400 Subject: [PATCH] cleaning code --- .../core/_measurements_base.py | 21 -------- .../measurements/MeasurementsGPU.hpp | 1 - .../lightning_gpu/_measurements.py | 1 + .../lightning_gpu/_mpi_handler.py | 18 ++++++- .../lightning_gpu/_state_vector.py | 52 ++++--------------- .../lightning_gpu/lightning_gpu.py | 8 +-- .../lightning_kokkos/_measurements.py | 27 +--------- tests/conftest.py | 3 +- .../test_measurements_class.py | 16 +----- .../test_state_vector_class.py | 2 - tests/test_measurements.py | 4 +- 11 files changed, 37 insertions(+), 116 deletions(-) diff --git a/pennylane_lightning/core/_measurements_base.py b/pennylane_lightning/core/_measurements_base.py index 3c66109372..51538cd5ec 100644 --- a/pennylane_lightning/core/_measurements_base.py +++ b/pennylane_lightning/core/_measurements_base.py @@ -140,27 +140,6 @@ def probs(self, measurementprocess: MeasurementProcess): Returns: Probabilities of the supplied observable or wires """ - # diagonalizing_gates = measurementprocess.diagonalizing_gates() - # # print('*'*100) - # # print("probs: diagonalizing_gates:", diagonalizing_gates) - # if diagonalizing_gates: - # self._qubit_state.apply_operations(diagonalizing_gates) - # results = self._measurement_lightning.probs(measurementprocess.wires.tolist()) - - # # print("probs: result:",results) - # # print('*'*100) - # if diagonalizing_gates: - # self._qubit_state.apply_operations( - # [qml.adjoint(g, lazy=False) for g in reversed(diagonalizing_gates)] - # ) - - # # Device returns as col-major orderings, so perform transpose on data for bit-index shuffle for now. - # if len(results) > 0: - # num_local_wires = len(results).bit_length() - 1 if len(results) > 0 else 0 - # return results.reshape([2] * num_local_wires).transpose().reshape(-1) - - # return results - def var(self, measurementprocess: MeasurementProcess): """Variance of the supplied observable contained in the MeasurementProcess. diff --git a/pennylane_lightning/core/src/simulators/lightning_gpu/measurements/MeasurementsGPU.hpp b/pennylane_lightning/core/src/simulators/lightning_gpu/measurements/MeasurementsGPU.hpp index 12d99dedd9..fe19b5d025 100644 --- a/pennylane_lightning/core/src/simulators/lightning_gpu/measurements/MeasurementsGPU.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_gpu/measurements/MeasurementsGPU.hpp @@ -273,7 +273,6 @@ class Measurements final PL_CUSTATEVEC_IS_SUCCESS(custatevecSamplerSample( this->_statevector.getCusvHandle(), sampler, bitStrings.data(), bitOrdering.data(), bitStringLen, rand_nums.data(), num_samples, - // CUSTATEVEC_SAMPLER_OUTPUT_ASCENDING_ORDER)); CUSTATEVEC_SAMPLER_OUTPUT_RANDNUM_ORDER)); PL_CUDA_IS_SUCCESS(cudaStreamSynchronize( this->_statevector.getDataBuffer().getDevTag().getStreamID())); diff --git a/pennylane_lightning/lightning_gpu/_measurements.py b/pennylane_lightning/lightning_gpu/_measurements.py index 3839c5fd41..a2bbfcfc9d 100644 --- a/pennylane_lightning/lightning_gpu/_measurements.py +++ b/pennylane_lightning/lightning_gpu/_measurements.py @@ -134,6 +134,7 @@ def probs(self, measurementprocess: MeasurementProcess): if diagonalizing_gates: self._qubit_state.apply_operations(diagonalizing_gates) + results = self._measurement_lightning.probs(measurementprocess.wires.tolist()) if diagonalizing_gates: diff --git a/pennylane_lightning/lightning_gpu/_mpi_handler.py b/pennylane_lightning/lightning_gpu/_mpi_handler.py index b8e39209c6..11271d139d 100644 --- a/pennylane_lightning/lightning_gpu/_mpi_handler.py +++ b/pennylane_lightning/lightning_gpu/_mpi_handler.py @@ -1,4 +1,19 @@ +# Copyright 2022-2023 Xanadu Quantum Technologies Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +This module contains the :class:`~.LightningGPU_MPIHandler` class, a MPI handler to use LightningGPU device with multi-GPU on multi-node system. +""" try: # pylint: disable=no-name-in-module @@ -20,7 +35,7 @@ class LightningGPU_MPIHandler(): MPI handler to use a GPU-backed Lightning device using NVIDIA cuQuantum SDK with parallel capabilities. - Use the MPI library is necessary to initialize different variables and methods to handle the data across nodes and perform checks for memory allocation on each device. + Use the MPI library is necessary to initialize different variables and methods to handle the data across nodes and perform checks for memory allocation on each device. Args: mpi (bool): declare if the device will use the MPI support. @@ -52,7 +67,6 @@ def __init__(self, if (mpi_buf_size > 0 and (mpi_buf_size & (mpi_buf_size - 1))): - raise ValueError(f"Unsupported mpi_buf_size value: {mpi_buf_size}. mpi_buf_size should be power of 2.") # After check if all MPI parameter are ok diff --git a/pennylane_lightning/lightning_gpu/_state_vector.py b/pennylane_lightning/lightning_gpu/_state_vector.py index fcc92fbbee..20fab56840 100644 --- a/pennylane_lightning/lightning_gpu/_state_vector.py +++ b/pennylane_lightning/lightning_gpu/_state_vector.py @@ -43,12 +43,11 @@ from pennylane.wires import Wires from pennylane.measurements import MidMeasureMP from pennylane.ops import Conditional -from pennylane import QuantumFunctionError, DeviceError +from pennylane import DeviceError from pennylane_lightning.core._serialize import global_phase_diagonal from pennylane_lightning.core._state_vector_base import LightningBaseStateVector -from ._measurements import LightningGPUMeasurements from ._mpi_handler import LightningGPU_MPIHandler gate_cache_needs_hash = ( @@ -73,14 +72,14 @@ class LightningGPUStateVector(LightningBaseStateVector): device_name(string): state vector device name. Options: ["lightning.gpu"] """ - def __init__(self, num_wires, dtype=np.complex128, device_name="lightning.gpu", + def __init__(self, + num_wires, + dtype=np.complex128, + device_name="lightning.gpu", mpi_handler = None, sync=True, ): - if device_name != "lightning.gpu": - raise DeviceError(f'The device name "{device_name}" is not a valid option.') - super().__init__(num_wires, dtype) self._device_name = device_name @@ -216,9 +215,10 @@ def _apply_state_vector(self, state, device_wires, use_async=False): if isinstance(state, self._qubit_state.__class__): raise DeviceError("LightningGPU does not support allocate external state_vector.") - state_data = allocate_aligned_array(state.size, np.dtype(self.dtype), True) - state.getState(state_data) - state = state_data + # TODO + # state_data = allocate_aligned_array(state.size, np.dtype(self.dtype), True) + # state.getState(state_data) + # state = state_data state = self._asarray(state, dtype=self.dtype) # this operation on host output_shape = [2] * self._num_local_wires @@ -343,11 +343,6 @@ def _apply_lightning( method = getattr(state, name, None) wires = list(operation.wires) - # print("statevector: _apply_lightning: state:",state.__dir__) - # print("statevector: _apply_lightning: ops:",operation) - # print("statevector: _apply_lightning: name:",name) - # print("statevector: _apply_lightning: method:",method) - if isinstance(operation, Conditional): if operation.meas_val.concretize(mid_measurements): self._apply_lightning([operation.base]) @@ -373,13 +368,9 @@ def _apply_lightning( r_dtype = np.float32 if self.dtype == np.complex64 else np.float64 param = [[r_dtype(operation.hash)]] if isinstance(operation, gate_cache_needs_hash) else [] - # param = [] if len(mat) == 0: raise ValueError("Unsupported operation") - # print("statevector: _apply_lightning: method:",method) - # print("statevector: _apply_lightning: mat:", mat) - self._qubit_state.apply( name, wires, @@ -388,28 +379,3 @@ def _apply_lightning( mat.ravel(order="C"), # inv = False: Matrix already in correct form; ) # Parameters can be ignored for explicit matrices; F-order for cuQuantum - # ---------------------------------------------------------- - # method = getattr(state, "applyMatrix") - # # print("statevector: _apply_lightning: method:",method) - # # print("statevector: _apply_lightning: matrix:",qml.matrix(operation)) - # # print("statevector: _apply_lightning: matrix:",operation.matrix) - - # try: - # mat = qml.matrix(operation) - # except AttributeError: # pragma: no cover - # # To support older versions of PL - # mat = operation.matrix - - # # mat = mat.ravel(order='C') - # # mat = mat.conjugate().transpose() - - # print("statevector: _apply_lightning: mat:", mat) - # method(mat.ravel(order="C"), wires, False) - - # # try: - # # method(mat, wires, False) - # # except AttributeError: # pragma: no cover - # # # To support older versions of PL - # # method(mat, wires, False) - - diff --git a/pennylane_lightning/lightning_gpu/lightning_gpu.py b/pennylane_lightning/lightning_gpu/lightning_gpu.py index a06c47f869..f9ef0048ac 100644 --- a/pennylane_lightning/lightning_gpu/lightning_gpu.py +++ b/pennylane_lightning/lightning_gpu/lightning_gpu.py @@ -20,7 +20,7 @@ from ctypes.util import find_library from importlib import util as imp_util from pathlib import Path -from typing import Optional, Tuple, Callable, Union +from typing import Optional, Tuple Callable, Union import numpy as np import pennylane as qml @@ -291,7 +291,7 @@ def __init__( # pylint: disable=too-many-arguments ) # Set the attributes to call the LightningGPU classes - self._set_Lightning_classes() + self._set_lightning_classes() # GPU specific options self._dp = DevPool() @@ -303,7 +303,6 @@ def __init__( # pylint: disable=too-many-arguments self._num_local_wires = self._mpi_handler.num_local_wires - print("FSDX") self._statevector = self.LightningStateVector(self.num_wires, dtype=c_dtype, mpi_handler=self._mpi_handler, sync=self._sync) @@ -312,9 +311,10 @@ def name(self): """The name of the device.""" return "lightning.gpu" - def _set_Lightning_classes(self): + def _set_lightning_classes(self): """Load the LightningStateVector, LightningMeasurements, LightningAdjointJacobian as class attribute""" self.LightningStateVector = LightningGPUStateVector + self.LightningMeasurements = LightningGPUMeasurements def _setup_execution_config(self, config): """ diff --git a/pennylane_lightning/lightning_kokkos/_measurements.py b/pennylane_lightning/lightning_kokkos/_measurements.py index d46eda8a06..8070c26f80 100644 --- a/pennylane_lightning/lightning_kokkos/_measurements.py +++ b/pennylane_lightning/lightning_kokkos/_measurements.py @@ -93,9 +93,6 @@ def _process_single_shot(samples): return tuple(processed) - print("Kokkos: Measurements: _measure_with_samples_diagonalizing_gates: wires:",len(wires)) - print("Kokkos: Measurements: _measure_with_samples_diagonalizing_gates: shot:",shots.total_shots) - try: samples = self._measurement_lightning.generate_samples( len(wires), shots.total_shots @@ -105,36 +102,16 @@ def _process_single_shot(samples): if str(e) != "probabilities contain NaN": raise e samples = qml.math.full((shots.total_shots, len(wires)), 0) - + self._apply_diagonalizing_gates(mps, adjoint=True) - print("Kokkos: Measurements: _measure_with_samples_diagonalizing_gates: sample:") - unique, counts_uniq = np.unique(samples,axis=0, return_inverse=False, return_counts=True) - for val, c in zip(unique, counts_uniq): - print(val, c) - print("Kokkos: Measurements: _measure_with_samples_diagonalizing_gates: sample:",samples.shape) - print("Kokkos: Measurements: _measure_with_samples_diagonalizing_gates: sample:",samples.sum()) # if there is a shot vector, use the shots.bins generator to # split samples w.r.t. the shots processed_samples = [] - print("Kokkos: Measurements: _measure_with_samples_diagonalizing_gates: shots.bins:", list(shots.bins())) for lower, upper in shots.bins(): - # result = _process_single_shot(samples[..., lower:upper, :]) - tmp_sample = samples[..., lower:upper, :] - print("Kokkos: Measurements: _measure_with_samples_diagonalizing_gates: tmp_sample:") - unique, counts_uniq = np.unique(tmp_sample,axis=0, return_inverse=False, return_counts=True) - for val, c in zip(unique, counts_uniq): - print(val, c) - - print("Kokkos: Measurements: _measure_with_samples_diagonalizing_gates: tmp_sample", tmp_sample.shape) - print("Kokkos: Measurements: _measure_with_samples_diagonalizing_gates: tmp_sample", tmp_sample.sum()) - result = _process_single_shot(tmp_sample) - + result = _process_single_shot(samples[..., lower:upper, :]) processed_samples.append(result) - - print("Kokkos: Measurements: _measure_with_samples_diagonalizing_gates: result:", result) - print("I reach this place FDX") return ( tuple(zip(*processed_samples)) if shots.has_partitioned_shots else processed_samples[0] ) diff --git a/tests/conftest.py b/tests/conftest.py index 94d6bd5267..4cc0e4c5c0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -192,8 +192,7 @@ def _device(wires, shots=None): # General LightningStateVector fixture, for any number of wires. @pytest.fixture( scope="function", - # params=[np.complex64, np.complex128], - params=[np.complex128], + params=[np.complex64, np.complex128], ) def lightning_sv(request): def _statevector(num_wires): diff --git a/tests/lightning_qubit/test_measurements_class.py b/tests/lightning_qubit/test_measurements_class.py index f32ee39b18..5765af6d69 100644 --- a/tests/lightning_qubit/test_measurements_class.py +++ b/tests/lightning_qubit/test_measurements_class.py @@ -46,7 +46,6 @@ def get_hermitian_matrix(n): - np.random.seed(33) H = np.random.rand(n, n) + 1.0j * np.random.rand(n, n) return H + np.conj(H).T @@ -409,7 +408,7 @@ def calculate_reference(tape, lightning_sv): m = LightningMeasurements(statevector) return m.measure_final_state(tape) - @flaky(max_runs=1) + @flaky(max_runs=2) @pytest.mark.parametrize("shots", [None, 600_000, [790_000, 790_000]]) @pytest.mark.parametrize("measurement", [qml.expval, qml.probs, qml.var]) @pytest.mark.parametrize( @@ -450,12 +449,6 @@ def test_single_return_value(self, shots, measurement, observable, lightning_sv, pytest.skip( f"Measurement of type {type(measurement).__name__} does not have a keyword argument 'wires'." ) - - print() - print("shots:",shots) - print("measurement:",measurement) - print("observable:", observable) - rtol = 1.0e-2 # 1% of expected value as tolerance if shots != None and measurement is qml.expval: # Increase the number of shots @@ -481,7 +474,6 @@ def test_single_return_value(self, shots, measurement, observable, lightning_sv, tape = qml.tape.QuantumScript(ops, measurements, shots=shots) statevector = lightning_sv(n_qubits) - # print("dtype:",statevector.dtype) statevector = statevector.get_final_state(tape) m = LightningMeasurements(statevector) @@ -503,9 +495,6 @@ def test_single_return_value(self, shots, measurement, observable, lightning_sv, expected = self.calculate_reference(tape, lightning_sv) - print("Result:") - print(f'expected: {expected}') - print(f' result: {result}') # a few tests may fail in single precision, and hence we increase the tolerance if shots is None: assert np.allclose(result, expected, max(tol, 1.0e-4)) @@ -516,9 +505,8 @@ def test_single_return_value(self, shots, measurement, observable, lightning_sv, # allclose -> absolute(a - b) <= (atol + rtol * absolute(b)) assert np.allclose(result, expected, rtol=rtol, atol=atol) - @flaky(max_runs=1) + @flaky(max_runs=10) @pytest.mark.parametrize("shots", [None, 100_000, (90_000, 90_000)]) - # @pytest.mark.parametrize("shots", [None, 100_000]) @pytest.mark.parametrize("measurement", [qml.expval, qml.probs, qml.var]) @pytest.mark.parametrize( "obs0_", diff --git a/tests/lightning_qubit/test_state_vector_class.py b/tests/lightning_qubit/test_state_vector_class.py index bdfc1e2b3f..6e562d80cc 100644 --- a/tests/lightning_qubit/test_state_vector_class.py +++ b/tests/lightning_qubit/test_state_vector_class.py @@ -42,8 +42,6 @@ allow_module_level=True, ) -# if device_name == "lightning.gpu": -# pytest.skip("LGPU new API in WIP. Skipping.", allow_module_level=True) if not LightningDevice._CPP_BINARY_AVAILABLE: pytest.skip("No binary module found. Skipping.", allow_module_level=True) diff --git a/tests/test_measurements.py b/tests/test_measurements.py index c094c378f6..be8496587b 100644 --- a/tests/test_measurements.py +++ b/tests/test_measurements.py @@ -28,8 +28,8 @@ if not ld._CPP_BINARY_AVAILABLE: pytest.skip("No binary module found. Skipping.", allow_module_level=True) -# if device_name == "lightning.gpu": -# pytest.skip("LGPU new API in WIP. Skipping.", allow_module_level=True) +if device_name == "lightning.gpu": + pytest.skip("LGPU new API in WIP. Skipping.", allow_module_level=True) @pytest.mark.skipif(ld._new_API, reason="Old API required")