Skip to content

Commit bc23ba1

Browse files
committed
Refactor qubit high performance functions
Signed-off-by: Vlad Gheorghiu <vsoftco@gmail.com>
1 parent 1885ac8 commit bc23ba1

39 files changed

Lines changed: 3098 additions & 759 deletions

CHANGES.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
manipulation and qubit circuit execution through extensive optimizations of
55
`qpp::apply()`, `qpp::applyCTRL()`, and `qpp::measure_seq()`.
66
- **pyqpp** is now feature complete, providing Python users with
7+
- Added `pyqpp.QEngine.get_stats_to_JSON()` to display the measurement
8+
statistics in JSON format from **pyqpp**
79
complete access to the full **Quantum++** API
810
- Switched to MAJOR.MINOR.PATCH release versioning system:
911
- MAJOR -- introduces significant changes that break backward compatibility
@@ -40,11 +42,8 @@
4042
`${CMAKE_BUILD_DIR}`
4143
- Added benchmarking suite using [Catch2](https://github.com/catchorg/Catch2)
4244
in ["benchmarks"](https://github.com/softwareQinc/qpp/blob/main/benchmarks)
45+
- Removed the `stress_tests` suite, as the new benchmarking suite supersedes it
4346
- Bugfixes for `qpp::QFT()` and `qpp::TFQ()`
44-
- Added `pyqpp.QEngine.get_stats_to_JSON()` to display the measurement
45-
statistics in JSON format from **pyqpp**
46-
- **pyqpp** is feature-complete, now all Quantum++ functions have corresponding
47-
bindings in Python
4847

4948
# Version 6.0 - 14 April 2025
5049

benchmarks/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# Benchmarks with Catch2
22
cmake_minimum_required(VERSION 3.20)
33

4-
project(benchmarks)
4+
project(benchmarks LANGUAGES CXX)
55

66
find_package(qpp REQUIRED)
77

88
set(CMAKE_CXX_STANDARD 17)
9+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
910
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
1011

1112
include(FetchContent)

benchmarks/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ a specific benchmark, e.g., `qft_bench`, execute
4343
For help and additional options, run any benchmark with the `--help` flag.
4444

4545
> **Note:**
46-
> All **Quantum++**
46+
> **Quantum++**
4747
> [CMake flags and arguments](https://github.com/softwareQinc/qpp/blob/main/INSTALL.md#cmake-flags-and-optional-arguments)
4848
> **do not propagate** to the benchmarks. They must be defined independently if
4949
> they are needed.

benchmarks/include/openmp_utils.hpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,42 @@
99
#include <omp.h>
1010

1111
// CLI override (default -1 -> auto-detect)
12-
inline int cli_core_count = -1;
12+
inline int cli_threads = -1;
1313

1414
/**
1515
* @brief Detects/sets the number of OpenMP threads
16-
* @param requested Optional requested thread count; uses \a cli_core_count by
16+
* @param requested Optional requested thread count; uses \a cli_threads by
1717
* default
1818
*
1919
* @return Final number of threads used
2020
*/
2121
inline int set_openmp_threads(int requested = -1) {
22-
int core_count = (requested >= 0) ? requested : cli_core_count;
22+
int threads = (requested >= 0) ? requested : cli_threads;
2323

2424
const char* env = std::getenv("OMP_NUM_THREADS");
2525
const bool env_set = (env && std::atoi(env) > 0);
2626

2727
// 1. Environment variable has highest priority
2828
if (env_set) {
29-
core_count = std::atoi(env);
30-
std::cout << "OpenMP enabled, core_count=" << core_count
29+
threads = std::atoi(env);
30+
std::cout << "OpenMP enabled, threads=" << threads
3131
<< " set by OMP_NUM_THREADS\n";
3232
}
3333
// 2. If NOT set by OMP_NUM_THREADS
34-
else if (core_count <= 0) {
35-
core_count = omp_get_max_threads();
36-
std::cout << "OpenMP enabled, core_count=" << core_count
34+
else if (threads <= 0) {
35+
threads = omp_get_max_threads();
36+
std::cout << "OpenMP enabled, threads=" << threads
3737
<< " auto-detected by OpenMP\n";
3838
}
39-
// 3. Otherwise (core_count > 0) and NOT set by OMP_NUM_THREADS
39+
// 3. Otherwise (threads > 0) and NOT set by OMP_NUM_THREADS
4040
else {
41-
std::cout << "OpenMP enabled, core_count=" << core_count
41+
std::cout << "OpenMP enabled, threads=" << threads
4242
<< " set by the CLI\n";
4343
}
4444

45-
omp_set_num_threads(core_count);
45+
omp_set_num_threads(threads);
4646

47-
return core_count;
47+
return threads;
4848
}
4949
#endif // QPP_OPENMP
5050

benchmarks/src/measure_seq_psi_bench.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ qpp::idx nq = 10; // default number of qubits if none provided at runtime
1414
int main(int argc, char* argv[]) {
1515
Catch::Session session;
1616

17-
auto cli =
18-
session.cli() | Catch::Clara::Opt(nq, "nq")["--nq"]("Number of qubits");
17+
auto cli = session.cli() |
18+
Catch::Clara::Opt(nq, "qubits")["--nq"]("Number of qubits");
1919
#ifdef QPP_OPENMP
20-
cli |= Catch::Clara::Opt(cli_core_count, "core_count")["--core_count"](
20+
cli |= Catch::Clara::Opt(cli_threads, "threads")["--threads"](
2121
"Number of OpenMP threads/cores (ignored if the environment variable "
2222
"OMP_NUM_THREADS is set)");
2323
#endif // QPP_OPENMP

benchmarks/src/measure_seq_rho_bench.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ qpp::idx nq = 10; // default number of qubits if none provided at runtime
1414
int main(int argc, char* argv[]) {
1515
Catch::Session session;
1616

17-
auto cli =
18-
session.cli() | Catch::Clara::Opt(nq, "nq")["--nq"]("Number of qubits");
17+
auto cli = session.cli() |
18+
Catch::Clara::Opt(nq, "qubits")["--nq"]("Number of qubits");
1919
#ifdef QPP_OPENMP
20-
cli |= Catch::Clara::Opt(cli_core_count, "core_count")["--core_count"](
20+
cli |= Catch::Clara::Opt(cli_threads, "threads")["--threads"](
2121
"Number of OpenMP threads/cores (ignored if the environment variable "
2222
"OMP_NUM_THREADS is set)");
2323
#endif // QPP_OPENMP

benchmarks/src/ptrace_psi_bench.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@
77

88
#include "openmp_utils.hpp"
99

10+
#include "qpp/internal/kernels/qubit/ptrace.hpp"
11+
1012
namespace {
1113
qpp::idx nq = 10; // default number of qubits if none provided at runtime
1214
} // namespace
1315

1416
int main(int argc, char* argv[]) {
1517
Catch::Session session;
1618

17-
auto cli =
18-
session.cli() | Catch::Clara::Opt(nq, "nq")["--nq"]("Number of qubits");
19+
auto cli = session.cli() |
20+
Catch::Clara::Opt(nq, "qubits")["--nq"]("Number of qubits");
1921
#ifdef QPP_OPENMP
20-
cli |= Catch::Clara::Opt(cli_core_count, "core_count")["--core_count"](
22+
cli |= Catch::Clara::Opt(cli_threads, "threads")["--threads"](
2123
"Number of OpenMP threads/cores (ignored if the environment variable "
2224
"OMP_NUM_THREADS is set)");
2325
#endif // QPP_OPENMP
@@ -63,11 +65,23 @@ TEST_CASE("qpp::ptrace() state vector benchmark",
6365
// calculation away.
6466
return qpp::ptrace_new1(psi, subsys, dims);
6567
};
68+
// Benchmarked portion (executed repeatedly)
69+
BENCHMARK("Partial trace new2 (psi) nq=" + std::to_string(nq)) {
70+
// CRITICAL: Return the result so the compiler doesn't optimize the
71+
// calculation away.
72+
return qpp::ptrace_new2(psi, subsys, dims);
73+
};
74+
// Benchmarked portion (executed repeatedly)
75+
BENCHMARK("Partial trace new3 (psi) nq=" + std::to_string(nq)) {
76+
// CRITICAL: Return the result so the compiler doesn't optimize the
77+
// calculation away.
78+
return qpp::ptrace_new3(psi, subsys, dims);
79+
};
6680

6781
// Benchmarked portion (executed repeatedly)
6882
BENCHMARK("Partial trace qubits (psi) nq=" + std::to_string(nq)) {
6983
// CRITICAL: Return the result so the compiler doesn't optimize the
7084
// calculation away.
71-
return qpp::internal::ptrace_psi_kq(psi, subsys, nq);
85+
return qpp::internal::kernels::qubit::ptrace_psi_kq(psi, subsys, nq);
7286
};
7387
}

benchmarks/src/ptrace_rho_bench.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@
77

88
#include "openmp_utils.hpp"
99

10+
#include "qpp/internal/kernels/qubit/ptrace.hpp"
11+
1012
namespace {
1113
qpp::idx nq = 10; // default number of qubits if none provided at runtime
1214
} // namespace
1315

1416
int main(int argc, char* argv[]) {
1517
Catch::Session session;
1618

17-
auto cli =
18-
session.cli() | Catch::Clara::Opt(nq, "nq")["--nq"]("Number of qubits");
19+
auto cli = session.cli() |
20+
Catch::Clara::Opt(nq, "qubits")["--nq"]("Number of qubits");
1921
#ifdef QPP_OPENMP
20-
cli |= Catch::Clara::Opt(cli_core_count, "core_count")["--core_count"](
22+
cli |= Catch::Clara::Opt(cli_threads, "threads")["--threads"](
2123
"Number of OpenMP threads/cores (ignored if the environment variable "
2224
"OMP_NUM_THREADS is set)");
2325
#endif // QPP_OPENMP
@@ -63,11 +65,23 @@ TEST_CASE("qpp::ptrace() density matrix benchmark",
6365
// calculation away.
6466
return qpp::ptrace_new1(rho, subsys, dims);
6567
};
68+
// Benchmarked portion (executed repeatedly)
69+
BENCHMARK("Partial trace new2 (rho) nq=" + std::to_string(nq)) {
70+
// CRITICAL: Return the result so the compiler doesn't optimize the
71+
// calculation away.
72+
return qpp::ptrace_new2(rho, subsys, dims);
73+
};
74+
// Benchmarked portion (executed repeatedly)
75+
BENCHMARK("Partial trace new3 (rho) nq=" + std::to_string(nq)) {
76+
// CRITICAL: Return the result so the compiler doesn't optimize the
77+
// calculation away.
78+
return qpp::ptrace_new3(rho, subsys, dims);
79+
};
6680

6781
// Benchmarked portion (executed repeatedly)
6882
BENCHMARK("Partial trace qubits (rho) nq=" + std::to_string(nq)) {
6983
// CRITICAL: Return the result so the compiler doesn't optimize the
7084
// calculation away.
71-
return qpp::internal::ptrace_rho_kq(rho, subsys, nq);
85+
return qpp::internal::kernels::qubit::ptrace_rho_kq(rho, subsys, nq);
7286
};
7387
}

benchmarks/src/ptranspose_psi_bench.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@
77

88
#include "openmp_utils.hpp"
99

10+
#include "qpp/internal/kernels/qubit/ptranspose.hpp"
11+
1012
namespace {
1113
qpp::idx nq = 10; // default number of qubits if none provided at runtime
1214
} // namespace
1315

1416
int main(int argc, char* argv[]) {
1517
Catch::Session session;
1618

17-
auto cli =
18-
session.cli() | Catch::Clara::Opt(nq, "nq")["--nq"]("Number of qubits");
19+
auto cli = session.cli() |
20+
Catch::Clara::Opt(nq, "qubits")["--nq"]("Number of qubits");
1921
#ifdef QPP_OPENMP
20-
cli |= Catch::Clara::Opt(cli_core_count, "core_count")["--core_count"](
22+
cli |= Catch::Clara::Opt(cli_threads, "threads")["--threads"](
2123
"Number of OpenMP threads/cores (ignored if the environment variable "
2224
"OMP_NUM_THREADS is set)");
2325
#endif // QPP_OPENMP
@@ -69,6 +71,7 @@ TEST_CASE("qpp::ptranspose() state vector benchmark",
6971
BENCHMARK("Partial transpose qubits (psi) nq=" + std::to_string(nq)) {
7072
// CRITICAL: Return the result so the compiler doesn't optimize the
7173
// calculation away.
72-
return qpp::internal::ptranspose_psi_kq(psi, subsys, nq);
74+
return qpp::internal::kernels::qubit::ptranspose_psi_kq(psi, subsys,
75+
nq);
7376
};
7477
}

benchmarks/src/ptranspose_rho_bench.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@
77

88
#include "openmp_utils.hpp"
99

10+
#include "qpp/internal/kernels/qubit/ptranspose.hpp"
11+
1012
namespace {
1113
qpp::idx nq = 10; // default number of qubits if none provided at runtime
1214
} // namespace
1315

1416
int main(int argc, char* argv[]) {
1517
Catch::Session session;
1618

17-
auto cli =
18-
session.cli() | Catch::Clara::Opt(nq, "nq")["--nq"]("Number of qubits");
19+
auto cli = session.cli() |
20+
Catch::Clara::Opt(nq, "qubits")["--nq"]("Number of qubits");
1921
#ifdef QPP_OPENMP
20-
cli |= Catch::Clara::Opt(cli_core_count, "core_count")["--core_count"](
22+
cli |= Catch::Clara::Opt(cli_threads, "threads")["--threads"](
2123
"Number of OpenMP threads/cores (ignored if the environment variable "
2224
"OMP_NUM_THREADS is set)");
2325
#endif // QPP_OPENMP
@@ -56,11 +58,19 @@ TEST_CASE("qpp::ptranspose() density matrix benchmark",
5658
// calculation away.
5759
return qpp::ptranspose(rho, subsys);
5860
};
61+
std::vector<qpp::idx> dims(nq, 2);
62+
// Benchmarked portion (executed repeatedly)
63+
BENCHMARK("Partial transpose new (rho) nq=" + std::to_string(nq)) {
64+
// CRITICAL: Return the result so the compiler doesn't optimize the
65+
// calculation away.
66+
return qpp::ptranspose_new(rho, subsys, dims);
67+
};
5968

6069
// Benchmarked portion (executed repeatedly)
6170
BENCHMARK("Partial transpose qubits (rho) nq=" + std::to_string(nq)) {
6271
// CRITICAL: Return the result so the compiler doesn't optimize the
6372
// calculation away.
64-
return qpp::internal::ptranspose_rho_kq(rho, subsys, nq);
73+
return qpp::internal::kernels::qubit::ptranspose_rho_kq(rho, subsys,
74+
nq);
6575
};
6676
}

0 commit comments

Comments
 (0)