Skip to content

Commit 646f4f7

Browse files
committed
Fix segfault and add an end-to-end stepper check
Signed-off-by: Thien Nguyen <[email protected]>
1 parent bc40e5a commit 646f4f7

File tree

4 files changed

+48
-20
lines changed

4 files changed

+48
-20
lines changed

Diff for: runtime/cudaq/cudm_state.h

+4
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ class cudm_state {
7272
/// @return A copy of the raw data as a vector of complex numbers.
7373
std::vector<std::complex<double>> get_raw_data() const;
7474

75+
/// @brief Get the pointer to device memory buffer storing the state.
76+
/// @return GPU device pointer
77+
void *get_device_pointer() const;
78+
7579
/// @brief Get a copy of the hilbert space dimensions for the quantum state.
7680
/// @return A copy of the hilbert space dimensions of a vector of integers.
7781
std::vector<int64_t> get_hilbert_space_dims() const;

Diff for: runtime/cudaq/dynamics/cudm_helpers.cpp

+17-20
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
#include "cudaq/cudm_error_handling.h"
1111

1212
namespace cudaq {
13-
// Function to flatten a matrix into a 1D array
13+
// Function to flatten a matrix into a 1D array (column major)
1414
std::vector<std::complex<double>> flatten_matrix(const matrix_2 &matrix) {
1515
std::vector<std::complex<double>> flat_matrix;
16-
17-
for (size_t i = 0; i < matrix.get_rows(); i++) {
18-
for (size_t j = 0; j < matrix.get_columns(); j++) {
19-
flat_matrix.push_back(matrix[{i, j}]);
16+
flat_matrix.reserve(matrix.get_size());
17+
for (size_t col = 0; col < matrix.get_columns(); col++) {
18+
for (size_t row = 0; row < matrix.get_rows(); row++) {
19+
flat_matrix.push_back(matrix[{row, col}]);
2020
}
2121
}
2222

@@ -53,19 +53,14 @@ cudensitymatElementaryOperator_t create_elementary_operator(
5353

5454
cudensitymatElementaryOperator_t cudm_elem_op = nullptr;
5555

56-
std::vector<double> interleaved_matrix;
57-
interleaved_matrix.reserve(flat_matrix.size() * 2);
58-
59-
for (const auto &value : flat_matrix) {
60-
interleaved_matrix.push_back(value.real());
61-
interleaved_matrix.push_back(value.imag());
62-
}
56+
// FIXME: leak (need to track this buffer somewhere and delete **after** the
57+
// whole evolve)
58+
auto *elementaryMat_d = create_array_gpu(flat_matrix);
6359

6460
cudensitymatStatus_t status = cudensitymatCreateElementaryOperator(
6561
handle, static_cast<int32_t>(subspace_extents.size()),
6662
subspace_extents.data(), CUDENSITYMAT_OPERATOR_SPARSITY_NONE, 0, nullptr,
67-
CUDA_C_64F, static_cast<void *>(interleaved_matrix.data()),
68-
{nullptr, nullptr}, &cudm_elem_op);
63+
CUDA_C_64F, elementaryMat_d, {nullptr, nullptr}, &cudm_elem_op);
6964

7065
if (status != CUDENSITYMAT_STATUS_SUCCESS) {
7166
std::cerr << "Error: Failed to create elementary operator. Status: "
@@ -92,7 +87,7 @@ void append_elementary_operator_to_term(
9287
std::vector<cudensitymatElementaryOperator_t> elem_ops = {elem_op};
9388

9489
std::vector<int32_t> modeActionDuality(degrees.size(), 0);
95-
90+
assert(elem_ops.size() == degrees.size());
9691
HANDLE_CUDM_ERROR(cudensitymatOperatorTermAppendElementaryProduct(
9792
handle, term, static_cast<int32_t>(degrees.size()), elem_ops.data(),
9893
degrees.data(), modeActionDuality.data(), make_cuDoubleComplex(1.0, 0.0),
@@ -233,13 +228,15 @@ cudensitymatOperator_t convert_to_cudensitymat_operator(
233228
handle, operator_handle, term, 0, make_cuDoubleComplex(1.0, 0.0),
234229
{nullptr, nullptr}));
235230

231+
// FIXME: leak
232+
// We must track these handles and destroy **after** evolve finishes
236233
// Destroy the term
237-
HANDLE_CUDM_ERROR(cudensitymatDestroyOperatorTerm(term));
234+
// HANDLE_CUDM_ERROR(cudensitymatDestroyOperatorTerm(term));
238235

239-
// Cleanup
240-
for (auto &elem_op : elementary_operators) {
241-
HANDLE_CUDM_ERROR(cudensitymatDestroyElementaryOperator(elem_op));
242-
}
236+
// // Cleanup
237+
// for (auto &elem_op : elementary_operators) {
238+
// HANDLE_CUDM_ERROR(cudensitymatDestroyElementaryOperator(elem_op));
239+
// }
243240
}
244241

245242
return operator_handle;

Diff for: runtime/cudaq/dynamics/cudm_state.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ std::vector<std::complex<double>> cudm_state::get_raw_data() const {
120120
return rawData_;
121121
}
122122

123+
void *cudm_state::get_device_pointer() const { return gpuData_; }
124+
123125
std::vector<int64_t> cudm_state::get_hilbert_space_dims() const {
124126
return hilbertSpaceDims_;
125127
}

Diff for: unittests/dynamics/test_cudm_time_stepper.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,28 @@ TEST_F(CuDensityMatTimeStepperTest, ComputeStepZeroStepSize) {
9191
TEST_F(CuDensityMatTimeStepperTest, ComputeStepLargeTimeValues) {
9292
EXPECT_NO_THROW(time_stepper_->compute(*state_, 1e6, 1e3));
9393
}
94+
95+
TEST_F(CuDensityMatTimeStepperTest, ComputeStepCheckOutput) {
96+
const std::vector<std::complex<double>> initialState = {
97+
{1.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}};
98+
const std::vector<int64_t> dims = {4};
99+
auto inputState = std::make_unique<cudm_state>(handle_, initialState, dims);
100+
auto op = cudaq::matrix_operator::create(0);
101+
auto cudmOp = cudaq::convert_to_cudensitymat_operator<cudaq::matrix_operator>(
102+
handle_, {}, op, dims); // Initialize the time stepper
103+
auto time_stepper = std::make_unique<cudm_time_stepper>(handle_, cudmOp);
104+
auto outputState = time_stepper->compute(*inputState, 0.0, 1.0);
105+
106+
std::vector<std::complex<double>> outputStateVec(4);
107+
HANDLE_CUDA_ERROR(cudaMemcpy(
108+
outputStateVec.data(), outputState.get_device_pointer(),
109+
outputStateVec.size() * sizeof(std::complex<double>), cudaMemcpyDefault));
110+
// Create operator move the state up 1 step.
111+
const std::vector<std::complex<double>> expectedOutputState = {
112+
{0.0, 0.0}, {1.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}};
113+
114+
for (std::size_t i = 0; i < expectedOutputState.size(); ++i) {
115+
EXPECT_TRUE(std::abs(expectedOutputState[i] - outputStateVec[i]) < 1e-12);
116+
}
117+
HANDLE_CUDM_ERROR(cudensitymatDestroyOperator(cudmOp));
118+
}

0 commit comments

Comments
 (0)