Skip to content

Commit

Permalink
cpu-statevector on gpu
Browse files Browse the repository at this point in the history
  • Loading branch information
gandalfr-KY committed Jan 17, 2025
1 parent 0989281 commit 1391e2b
Show file tree
Hide file tree
Showing 20 changed files with 1,085 additions and 957 deletions.
95 changes: 81 additions & 14 deletions exe/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include <cstdint>
#include <iostream>
#include <scaluq/gate/gate.hpp>
#include <scaluq/gate/gate_factory.hpp>

using namespace scaluq;
using namespace nlohmann;
Expand All @@ -14,22 +14,89 @@ int main() {

Kokkos::Timer tm;
for (int i = 0; i < 10; ++i) {
// auto xgate = scaluq::gate::X<double>(2);
// xgate->update_quantum_state(gpu_state);
auto xgate = scaluq::gate::X<double, DefaultSpace>(2);
xgate->update_quantum_state(gpu_state);
}
std::cout << tm.seconds() << std::endl;
}
{
std::uint64_t n_qubits = 28;
scaluq::StateVector<double, CPUSpace> cpu_state(n_qubits);

Kokkos::Timer tm;
for (int i = 0; i < 10; ++i) {
auto xgate = scaluq::gate::X<double, CPUSpace>(2);
xgate->update_quantum_state(cpu_state);
}
std::cout << tm.seconds() << std::endl;
}
{
std::uint64_t n_qubits = 28;
scaluq::StateVector<float, DefaultSpace> gpu_state(n_qubits);

Kokkos::Timer tm;
for (int i = 0; i < 10; ++i) {
auto xgate = scaluq::gate::X<float, DefaultSpace>(2);
xgate->update_quantum_state(gpu_state);
}
std::cout << tm.seconds() << std::endl;
}
{
std::uint64_t n_qubits = 28;
scaluq::StateVector<float, CPUSpace> cpu_state(n_qubits);

Kokkos::Timer tm;
for (int i = 0; i < 10; ++i) {
auto xgate = scaluq::gate::X<float, CPUSpace>(2);
xgate->update_quantum_state(cpu_state);
}
std::cout << tm.seconds() << std::endl;
}

{
std::uint64_t n_qubits = 5;
scaluq::StateVector<double, DefaultSpace> gpu_state(n_qubits);

Kokkos::Timer tm;
for (int i = 0; i < 1000; ++i) {
auto xgate = scaluq::gate::X<double, DefaultSpace>(2);
xgate->update_quantum_state(gpu_state);
}
std::cout << tm.seconds() << std::endl;
}
{
std::uint64_t n_qubits = 5;
scaluq::StateVector<double, CPUSpace> cpu_state(n_qubits);

Kokkos::Timer tm;
for (int i = 0; i < 1000; ++i) {
auto xgate = scaluq::gate::X<double, CPUSpace>(2);
xgate->update_quantum_state(cpu_state);
}
std::cout << tm.seconds() << std::endl;
}
{
std::uint64_t n_qubits = 5;
scaluq::StateVector<float, DefaultSpace> gpu_state(n_qubits);

Kokkos::Timer tm;
for (int i = 0; i < 1000; ++i) {
auto xgate = scaluq::gate::X<float, DefaultSpace>(2);
xgate->update_quantum_state(gpu_state);
}
std::cout << tm.seconds() << std::endl;
}
{
std::uint64_t n_qubits = 5;
scaluq::StateVector<float, CPUSpace> cpu_state(n_qubits);

Kokkos::Timer tm;
for (int i = 0; i < 1000; ++i) {
auto xgate = scaluq::gate::X<float, CPUSpace>(2);
xgate->update_quantum_state(cpu_state);
}
std::cout << tm.seconds() << std::endl;
}
// {
// std::uint64_t n_qubits = 28;
// scaluq::StateVector<double, CPUSpace> cpu_state(n_qubits);

// Kokkos::Timer tm;
// for (int i = 0; i < 10; ++i) {
// // auto xgate = scaluq::gate::X<double>(2);
// // xgate->update_quantum_state(cpu_state);
// }
// std::cout << tm.seconds() << std::endl;
// }

// {
// std::uint64_t n_qubits = 3;
Expand Down
326 changes: 164 additions & 162 deletions include/scaluq/gate/gate_factory.hpp

Large diffs are not rendered by default.

36 changes: 18 additions & 18 deletions include/scaluq/gate/gate_matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

namespace scaluq {
namespace internal {
template <std::floating_point Fp>
class DenseMatrixGateImpl : public GateBase<Fp> {
template <std::floating_point Fp, ExecutionSpace Sp>
class DenseMatrixGateImpl : public GateBase<Fp, Sp> {
Matrix<Fp> _matrix;
bool _is_unitary;

Expand All @@ -21,14 +21,14 @@ class DenseMatrixGateImpl : public GateBase<Fp> {
const ComplexMatrix<Fp>& mat,
bool is_unitary = false);

std::shared_ptr<const GateBase<Fp>> get_inverse() const override;
std::shared_ptr<const GateBase<Fp, Sp>> get_inverse() const override;

Matrix<Fp> get_matrix_internal() const;

ComplexMatrix<Fp> get_matrix() const override;

void update_quantum_state(StateVector<Fp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp>& states) const override;
void update_quantum_state(StateVector<Fp, Sp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp, Sp>& states) const override;

std::string to_string(const std::string& indent) const override;

Expand All @@ -40,8 +40,8 @@ class DenseMatrixGateImpl : public GateBase<Fp> {
}
};

template <std::floating_point Fp>
class SparseMatrixGateImpl : public GateBase<Fp> {
template <std::floating_point Fp, ExecutionSpace Sp>
class SparseMatrixGateImpl : public GateBase<Fp, Sp> {
SparseMatrix<Fp> _matrix;
std::uint64_t num_nnz;

Expand All @@ -50,16 +50,16 @@ class SparseMatrixGateImpl : public GateBase<Fp> {
std::uint64_t control_mask,
const SparseComplexMatrix<Fp>& mat);

std::shared_ptr<const GateBase<Fp>> get_inverse() const override;
std::shared_ptr<const GateBase<Fp, Sp>> get_inverse() const override;

Matrix<Fp> get_matrix_internal() const;

ComplexMatrix<Fp> get_matrix() const override;

SparseComplexMatrix<Fp> get_sparse_matrix() const { return get_matrix().sparseView(); }

void update_quantum_state(StateVector<Fp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp>& states) const override;
void update_quantum_state(StateVector<Fp, Sp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp, Sp>& states) const override;

std::string to_string(const std::string& indent) const override;

Expand All @@ -73,21 +73,21 @@ class SparseMatrixGateImpl : public GateBase<Fp> {

} // namespace internal

template <std::floating_point Fp>
using SparseMatrixGate = internal::GatePtr<internal::SparseMatrixGateImpl<Fp>>;
template <std::floating_point Fp>
using DenseMatrixGate = internal::GatePtr<internal::DenseMatrixGateImpl<Fp>>;
template <std::floating_point Fp, ExecutionSpace Sp>
using SparseMatrixGate = internal::GatePtr<internal::SparseMatrixGateImpl<Fp, Sp>>;
template <std::floating_point Fp, ExecutionSpace Sp>
using DenseMatrixGate = internal::GatePtr<internal::DenseMatrixGateImpl<Fp, Sp>>;

#ifdef SCALUQ_USE_NANOBIND
namespace internal {
template <std::floating_point Fp>
template <std::floating_point Fp, ExecutionSpace Sp>
void bind_gate_gate_matrix_hpp(nb::module_& m) {
DEF_GATE(SparseMatrixGate, Fp, "Specific class of sparse matrix gate.")
.def("matrix", [](const SparseMatrixGate<Fp>& gate) { return gate->get_matrix(); })
.def("matrix", [](const SparseMatrixGate<Fp, Sp>& gate) { return gate->get_matrix(); })
.def("sparse_matrix",
[](const SparseMatrixGate<Fp>& gate) { return gate->get_sparse_matrix(); });
[](const SparseMatrixGate<Fp, Sp>& gate) { return gate->get_sparse_matrix(); });
DEF_GATE(DenseMatrixGate, Fp, "Specific class of dense matrix gate.")
.def("matrix", [](const DenseMatrixGate<Fp>& gate) { return gate->get_matrix(); });
.def("matrix", [](const DenseMatrixGate<Fp, Sp>& gate) { return gate->get_matrix(); });
}
} // namespace internal
#endif
Expand Down
52 changes: 26 additions & 26 deletions include/scaluq/gate/gate_pauli.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,25 @@
namespace scaluq {
namespace internal {

template <std::floating_point Fp>
class PauliGateImpl : public GateBase<Fp> {
const PauliOperator<Fp> _pauli;
template <std::floating_point Fp, ExecutionSpace Sp>
class PauliGateImpl : public GateBase<Fp, Sp> {
const PauliOperator<Fp, Sp> _pauli;

public:
PauliGateImpl(std::uint64_t control_mask, const PauliOperator<Fp>& pauli)
: GateBase<Fp>(vector_to_mask<false>(pauli.target_qubit_list()), control_mask),
PauliGateImpl(std::uint64_t control_mask, const PauliOperator<Fp, Sp>& pauli)
: GateBase<Fp, Sp>(vector_to_mask<false>(pauli.target_qubit_list()), control_mask),
_pauli(pauli) {}

PauliOperator<Fp> pauli() const { return _pauli; };
PauliOperator<Fp, Sp> pauli() const { return _pauli; };
std::vector<std::uint64_t> pauli_id_list() const { return _pauli.pauli_id_list(); }

std::shared_ptr<const GateBase<Fp>> get_inverse() const override {
std::shared_ptr<const GateBase<Fp, Sp>> get_inverse() const override {
return this->shared_from_this();
}
internal::ComplexMatrix<Fp> get_matrix() const override { return this->_pauli.get_matrix(); }

void update_quantum_state(StateVector<Fp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp>& states) const override;
void update_quantum_state(StateVector<Fp, Sp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp, Sp>& states) const override;

std::string to_string(const std::string& indent) const override;

Expand All @@ -37,30 +37,30 @@ class PauliGateImpl : public GateBase<Fp> {
}
};

template <std::floating_point Fp>
class PauliRotationGateImpl : public GateBase<Fp> {
const PauliOperator<Fp> _pauli;
template <std::floating_point Fp, ExecutionSpace Sp>
class PauliRotationGateImpl : public GateBase<Fp, Sp> {
const PauliOperator<Fp, Sp> _pauli;
const Fp _angle;

public:
PauliRotationGateImpl(std::uint64_t control_mask, const PauliOperator<Fp>& pauli, Fp angle)
: GateBase<Fp>(vector_to_mask<false>(pauli.target_qubit_list()), control_mask),
PauliRotationGateImpl(std::uint64_t control_mask, const PauliOperator<Fp, Sp>& pauli, Fp angle)
: GateBase<Fp, Sp>(vector_to_mask<false>(pauli.target_qubit_list()), control_mask),
_pauli(pauli),
_angle(angle) {}

PauliOperator<Fp> pauli() const { return _pauli; }
PauliOperator<Fp, Sp> pauli() const { return _pauli; }
std::vector<std::uint64_t> pauli_id_list() const { return _pauli.pauli_id_list(); }
Fp angle() const { return _angle; }

std::shared_ptr<const GateBase<Fp>> get_inverse() const override {
return std::make_shared<const PauliRotationGateImpl<Fp>>(
std::shared_ptr<const GateBase<Fp, Sp>> get_inverse() const override {
return std::make_shared<const PauliRotationGateImpl<Fp, Sp>>(
this->_control_mask, _pauli, -_angle);
}

internal::ComplexMatrix<Fp> get_matrix() const override;

void update_quantum_state(StateVector<Fp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp>& states) const override;
void update_quantum_state(StateVector<Fp, Sp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp, Sp>& states) const override;

std::string to_string(const std::string& indent) const override;

Expand All @@ -73,13 +73,13 @@ class PauliRotationGateImpl : public GateBase<Fp> {
};
} // namespace internal

template <std::floating_point Fp>
using PauliGate = internal::GatePtr<internal::PauliGateImpl<Fp>>;
template <std::floating_point Fp>
using PauliRotationGate = internal::GatePtr<internal::PauliRotationGateImpl<Fp>>;
template <std::floating_point Fp, ExecutionSpace Sp>
using PauliGate = internal::GatePtr<internal::PauliGateImpl<Fp, Sp>>;
template <std::floating_point Fp, ExecutionSpace Sp>
using PauliRotationGate = internal::GatePtr<internal::PauliRotationGateImpl<Fp, Sp>>;

namespace internal {
#define DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE(Type) \
/*#define DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE(Type) \
template <> \
inline std::shared_ptr<const PauliGateImpl<Type>> get_from_json(const Json& j) { \
auto controls = j.at("control").get<std::vector<std::uint64_t>>(); \
Expand All @@ -97,13 +97,13 @@ namespace internal {
DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE(double)
DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE(float)
#undef DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE
#undef DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE*/

} // namespace internal

#ifdef SCALUQ_USE_NANOBIND
namespace internal {
template <std::floating_point Fp>
template <std::floating_point Fp, ExecutionSpace Sp>
void bind_gate_gate_pauli_hpp(nb::module_& m) {
DEF_GATE(PauliGate,
Fp,
Expand Down
28 changes: 14 additions & 14 deletions include/scaluq/gate/gate_probablistic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
namespace scaluq {
namespace internal {

template <std::floating_point Fp>
class ProbablisticGateImpl : public GateBase<Fp> {
template <std::floating_point Fp, ExecutionSpace Sp>
class ProbablisticGateImpl : public GateBase<Fp, Sp> {
std::vector<Fp> _distribution;
std::vector<Fp> _cumulative_distribution;
std::vector<Gate<Fp>> _gate_list;
std::vector<Gate<Fp, Sp>> _gate_list;

public:
ProbablisticGateImpl(const std::vector<Fp>& distribution,
const std::vector<Gate<Fp>>& gate_list);
const std::vector<Gate<Fp>>& gate_list() const { return _gate_list; }
const std::vector<Gate<Fp, Sp>>& gate_list);
const std::vector<Gate<Fp, Sp>>& gate_list() const { return _gate_list; }
const std::vector<Fp>& distribution() const { return _distribution; }

std::vector<std::uint64_t> target_qubit_list() const override {
Expand Down Expand Up @@ -51,15 +51,15 @@ class ProbablisticGateImpl : public GateBase<Fp> {
"ProbablisticGateImpl.");
}

std::shared_ptr<const GateBase<Fp>> get_inverse() const override;
std::shared_ptr<const GateBase<Fp, Sp>> get_inverse() const override;
internal::ComplexMatrix<Fp> get_matrix() const override {
throw std::runtime_error(
"ProbablisticGateImpl::get_matrix(): This function must not be used in "
"ProbablisticGateImpl.");
}

void update_quantum_state(StateVector<Fp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp>& states) const override;
void update_quantum_state(StateVector<Fp, Sp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp, Sp>& states) const override;

std::string to_string(const std::string& indent) const override;

Expand All @@ -71,12 +71,12 @@ class ProbablisticGateImpl : public GateBase<Fp> {
};
} // namespace internal

template <std::floating_point Fp>
using ProbablisticGate = internal::GatePtr<internal::ProbablisticGateImpl<Fp>>;
template <std::floating_point Fp, ExecutionSpace Sp>
using ProbablisticGate = internal::GatePtr<internal::ProbablisticGateImpl<Fp, Sp>>;

namespace internal {

#define DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE(Type) \
/*#define DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE(Type) \
template <> \
inline std::shared_ptr<const ProbablisticGateImpl<Type>> get_from_json(const Json& j) { \
auto distribution = j.at("distribution").get<std::vector<Type>>(); \
Expand All @@ -86,7 +86,7 @@ namespace internal {
DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE(double)
DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE(float)
#undef DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE
#undef DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE*/

} // namespace internal

Expand All @@ -100,11 +100,11 @@ void bind_gate_gate_probablistic(nb::module_& m) {
"distribution.")
.def(
"gate_list",
[](const ProbablisticGate<Fp>& gate) { return gate->gate_list(); },
[](const ProbablisticGate<Fp, Sp>& gate) { return gate->gate_list(); },
nb::rv_policy::reference)
.def(
"distribution",
[](const ProbablisticGate<Fp>& gate) { return gate->distribution(); },
[](const ProbablisticGate<Fp, Sp>& gate) { return gate->distribution(); },
nb::rv_policy::reference);
}
} // namespace internal
Expand Down
Loading

0 comments on commit 1391e2b

Please sign in to comment.