-
Notifications
You must be signed in to change notification settings - Fork 0
Gather DDSIM benchmarks #12
base: main
Are you sure you want to change the base?
Changes from 9 commits
ac5da11
200ac3c
d18d2f3
c0c3975
b7c2a84
984c665
45bafa1
5d05049
9ab6f20
dfc92bc
bee7e17
39885e5
d0edbe2
fdadb63
9aec66f
eb183d3
52756e7
b1f0fe8
9574955
1e86792
206321a
a234b9f
668f36d
5683b0b
3931e6f
9a8472c
f1b0634
2188a03
3246ec7
77a1505
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
if(NOT TARGET gtest OR NOT TARGET gmock) | ||
# Prevent overriding the parent project's compiler/linker settings on Windows | ||
set(gtest_force_shared_crt # cmake-lint: disable=C0103 | ||
ON | ||
CACHE BOOL "" FORCE) | ||
|
||
# store path to googletest in variable | ||
set(GTEST_PATH "extern/ddsim/extern/qfr/extern/dd_package/extern/googletest") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not that the googletest path is subject to change once you rebase the QFR (now MQT Core) PR and the DSSIM/QCEC PRs. Then this becomes: |
||
add_subdirectory("${PROJECT_SOURCE_DIR}/${GTEST_PATH}" "${GTEST_PATH}" | ||
EXCLUDE_FROM_ALL) | ||
endif() | ||
|
||
package_add_test( | ||
${PROJECT_NAME}_sim_benchmark ${PROJECT_NAME} benchmark_simexec_qpe.cpp | ||
benchmark_simexec_ghz.cpp benchmark_simexec_berstein.cpp | ||
benchmark_simexec_grover.cpp) |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just commenting on this file, but everything here holds for the other files as well: Furthermore, the benchmarks should really test a broad range of qubits, from really small to really large to cover the whole range of circuit sizes and complexity. Last but not least, this is missing quite some algorithms that are directly available in our libraries. There should be a parity between the algorithms tested in this repo and the algorithms used for benchmarking. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to be clear you mean that I should run the same algorithms both for test and benchmark with the only difference being benchmark being more thorough (more tests with different numbers of qubits), right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah. The tests can just cover certain instances of each benchmark, while the benchmarks should cover a broad range. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#include "QuantumComputation.hpp" | ||
#include "algorithms/BernsteinVazirani.hpp" | ||
#include "executors/CircuitSimulatorExecutor.hpp" | ||
#include "executors/HybridSimulatorAmplitudeExecutor.hpp" | ||
#include "executors/HybridSimulatorDDExecutor.hpp" | ||
#include "executors/StochasticNoiseSimulatorExecutor.hpp" | ||
#include "tasks/SimulationTask.hpp" | ||
|
||
#include "gtest/gtest.h" | ||
|
||
TEST(SimExecBenchmarkBerstein, HybridSimulatorAmplitudeExec) { | ||
auto hybridSimulatorAmplitudeExecutor = | ||
std::make_unique<HybridSimulatorAmplitudeExecutor>(); | ||
std::size_t const n = 25; | ||
auto qc = std::make_unique<qc::BernsteinVazirani>(n, false); | ||
SimulationTask const simulationTask(std::move(qc)); | ||
const auto result = hybridSimulatorAmplitudeExecutor->execute(simulationTask); | ||
std::cout << result << "\n"; | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() > | ||
1000000); | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() < | ||
300000000); | ||
} | ||
|
||
TEST(SimExecBenchmarkBerstein, HybridSimulatorDDExec) { | ||
auto hybridSimulatorDDExecutor = | ||
std::make_unique<HybridSimulatorDDExecutor>(); | ||
std::size_t const n = 40; | ||
auto qc = std::make_unique<qc::BernsteinVazirani>(n, false); | ||
SimulationTask const simulationTask(std::move(qc)); | ||
const auto result = hybridSimulatorDDExecutor->execute(simulationTask); | ||
std::cout << result << "\n"; | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() > | ||
1000000); | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() < | ||
300000000); | ||
} | ||
|
||
TEST(SimExecBenchmarkBerstein, StochasticNoiseSimulatorExec) { | ||
auto stochasticNoiseSimulatorExecutor = | ||
std::make_unique<StochasticNoiseSimulatorExecutor>(); | ||
std::size_t const n = 30; | ||
auto qc = std::make_unique<qc::BernsteinVazirani>(n, false); | ||
SimulationTask const simulationTask(std::move(qc)); | ||
const auto result = stochasticNoiseSimulatorExecutor->execute(simulationTask); | ||
std::cout << result << "\n"; | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() > | ||
1000000); | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() < | ||
300000000); | ||
} | ||
|
||
// Gives "C++ exception with description "Unsupported non-unitary functionality | ||
// 'Rst '." thrown in the test body." when run in dynamic |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#include "QuantumComputation.hpp" | ||
#include "algorithms/Entanglement.hpp" | ||
#include "executors/CircuitSimulatorExecutor.hpp" | ||
#include "executors/DeterministicNoiseSimExecutor.hpp" | ||
#include "executors/HybridSimulatorAmplitudeExecutor.hpp" | ||
#include "tasks/SimulationTask.hpp" | ||
|
||
#include "gtest/gtest.h" | ||
|
||
TEST(SimExecBenchmarkGHZ, HybridSimulatorAmplitudeExec) { | ||
auto hybridSimulatorAmplitudeExecutor = | ||
std::make_unique<HybridSimulatorAmplitudeExecutor>(); | ||
auto qc = std::make_unique<qc::Entanglement>(25); | ||
SimulationTask const simulationTask(std::move(qc)); | ||
const auto result = hybridSimulatorAmplitudeExecutor->execute(simulationTask); | ||
std::cout << result << "\n"; | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() > | ||
1000000); | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() < | ||
300000000); | ||
} | ||
|
||
TEST(SimExecBenchmarkGHZ, DeterministicNoiseSimExec) { | ||
auto deterministicNoiseSimulatorExecutor = | ||
std::make_unique<DeterministicNoiseSimExecutor>(); | ||
auto qc = std::make_unique<qc::Entanglement>(20); | ||
SimulationTask const simulationTask(std::move(qc)); | ||
const auto result = | ||
deterministicNoiseSimulatorExecutor->execute(simulationTask); | ||
std::cout << result << "\n"; | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() > | ||
1000000); | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() < | ||
300000000); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#include "QuantumComputation.hpp" | ||
#include "algorithms/Grover.hpp" | ||
#include "executors/CircuitSimulatorExecutor.hpp" | ||
#include "executors/UnitarySimRecursiveExecutor.hpp" | ||
#include "executors/UnitarySimSequentialExecutor.hpp" | ||
#include "tasks/SimulationTask.hpp" | ||
|
||
#include "gtest/gtest.h" | ||
|
||
TEST(SimExecBenchmarkGrover, CircuitSimulatorExec) { | ||
auto circuitSimulatorExecutor = std::make_unique<CircuitSimulatorExecutor>(); | ||
std::size_t const n = 25; | ||
auto qc = std::make_unique<qc::Grover>(n); | ||
SimulationTask const simulationTask(std::move(qc)); | ||
const auto result = circuitSimulatorExecutor->execute(simulationTask); | ||
std::cout << result << "\n"; | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() > | ||
1000000); | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() < | ||
300000000); | ||
} | ||
|
||
TEST(SimExecBenchmarkGrover, UnitarySimSequentialExec) { | ||
auto unitarySimSequentialExecutor = | ||
std::make_unique<UnitarySimSequentialExecutor>(); | ||
std::size_t const n = 22; | ||
auto qc = std::make_unique<qc::Grover>(n); | ||
SimulationTask const simulationTask(std::move(qc)); | ||
const auto result = unitarySimSequentialExecutor->execute(simulationTask); | ||
std::cout << result << "\n"; | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() > | ||
1000000); | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() < | ||
300000000); | ||
} | ||
|
||
TEST(SimExecBenchmarkGrover, UnitarySimRecursiveExec) { | ||
auto unitarySimRecursiveExecutor = | ||
std::make_unique<UnitarySimRecursiveExecutor>(); | ||
std::size_t const n = 22; | ||
auto qc = std::make_unique<qc::Grover>(n); | ||
SimulationTask const simulationTask(std::move(qc)); | ||
const auto result = unitarySimRecursiveExecutor->execute(simulationTask); | ||
std::cout << result << "\n"; | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() > | ||
1000000); | ||
EXPECT_TRUE(result["construction_time"].get<int>() + | ||
result["execution_time"].get<int>() < | ||
300000000); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#include "algorithms/QPE.hpp" | ||
#include "executors/CircuitSimulatorExecutor.hpp" | ||
#include "executors/UnitarySimRecursiveExecutor.hpp" | ||
#include "executors/UnitarySimSequentialExecutor.hpp" | ||
#include "tasks/SimulationTask.hpp" | ||
|
||
#include "gtest/gtest.h" | ||
|
||
// QPE fails from n=65 on in ComplexTable line 151. See if later versions of the | ||
// dd package can fix this. | ||
|
||
TEST(SimExecBenchmarkQPE, CircuitSimulatorExec) { | ||
auto circuitSimulatorExecutor = std::make_unique<CircuitSimulatorExecutor>(); | ||
std::size_t const n = 65; | ||
auto qc = std::make_unique<qc::QPE>(n, true, false); | ||
SimulationTask const simulationTask(std::move(qc)); | ||
EXPECT_DEATH(circuitSimulatorExecutor->execute(simulationTask), "Assertion"); | ||
} | ||
|
||
TEST(SimExecBenchmarkQPE, UnitarySimRecursiveExec) { | ||
auto unitarySimRecursiveExecutor = | ||
std::make_unique<UnitarySimRecursiveExecutor>(); | ||
std::size_t const n = 65; | ||
auto qc = std::make_unique<qc::QPE>(n, true, false); | ||
SimulationTask const simulationTask(std::move(qc)); | ||
EXPECT_DEATH(unitarySimRecursiveExecutor->execute(simulationTask), | ||
"Assertion"); | ||
} | ||
|
||
TEST(SimExecBenchmarkQPE, UnitarySimSequentialExec) { | ||
auto unitarySimSequentialExecutor = | ||
std::make_unique<UnitarySimSequentialExecutor>(); | ||
std::size_t const n = 65; | ||
auto qc = std::make_unique<qc::QPE>(n, true, false); | ||
SimulationTask const simulationTask(std::move(qc)); | ||
EXPECT_DEATH(unitarySimSequentialExecutor->execute(simulationTask), | ||
"Assertion"); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#pragma once | ||
|
||
#include "Executor.hpp" | ||
#include "tasks/SimulationTask.hpp" | ||
|
||
class DeterministicNoiseSimExecutor : public Executor<SimulationTask> { | ||
public: | ||
json execute(const SimulationTask& task) override; | ||
|
||
[[nodiscard]] std::string getIdentifier() const override { | ||
return "deterministic_noise_simulator"; | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#pragma once | ||
|
||
#include "Executor.hpp" | ||
#include "tasks/SimulationTask.hpp" | ||
|
||
class HybridSimulatorAmplitudeExecutor : public Executor<SimulationTask> { | ||
public: | ||
json execute(const SimulationTask& task) override; | ||
|
||
[[nodiscard]] std::string getIdentifier() const override { | ||
return "hybrid_schrodinger_feynman_simulator_amplitude"; | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#pragma once | ||
|
||
#include "Executor.hpp" | ||
#include "tasks/SimulationTask.hpp" | ||
|
||
class HybridSimulatorDDExecutor : public Executor<SimulationTask> { | ||
public: | ||
json execute(const SimulationTask& task) override; | ||
|
||
[[nodiscard]] std::string getIdentifier() const override { | ||
return "hybrid_schrodinger_feynman_simulator_dd"; | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#pragma once | ||
|
||
#include "Executor.hpp" | ||
#include "tasks/SimulationTask.hpp" | ||
|
||
class StochasticNoiseSimulatorExecutor : public Executor<SimulationTask> { | ||
public: | ||
json execute(const SimulationTask& task) override; | ||
|
||
[[nodiscard]] std::string getIdentifier() const override { | ||
return "stochastic_noise_simulator"; | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#pragma once | ||
|
||
#include "Executor.hpp" | ||
#include "tasks/SimulationTask.hpp" | ||
|
||
class UnitarySimRecursiveExecutor : public Executor<SimulationTask> { | ||
public: | ||
json execute(const SimulationTask& task) override; | ||
|
||
[[nodiscard]] std::string getIdentifier() const override { | ||
return "unitary_simulator_recursive"; | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#pragma once | ||
|
||
#include "Executor.hpp" | ||
#include "tasks/SimulationTask.hpp" | ||
|
||
class UnitarySimSequentialExecutor : public Executor<SimulationTask> { | ||
public: | ||
json execute(const SimulationTask& task) override; | ||
|
||
[[nodiscard]] std::string getIdentifier() const override { | ||
return "unitary_simulator_sequential"; | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#include "executors/DeterministicNoiseSimExecutor.hpp" | ||
|
||
#include "DeterministicNoiseSimulator.hpp" | ||
|
||
json DeterministicNoiseSimExecutor::execute(const SimulationTask& task) { | ||
json result; | ||
auto const constructionStart = std::chrono::steady_clock::now(); | ||
|
||
auto qc = std::make_unique<qc::QuantumComputation>(task.getQc()->clone()); | ||
auto circuitSimulator = | ||
std::make_unique<DeterministicNoiseSimulator<>>(std::move(qc), 23); | ||
|
||
auto const executionStart = std::chrono::steady_clock::now(); | ||
|
||
result["measurement_results"] = circuitSimulator->deterministicSimulate(); | ||
// Add memory usage | ||
|
||
auto const executionStop = std::chrono::steady_clock::now(); | ||
auto const constructionTime = | ||
std::chrono::duration_cast<std::chrono::microseconds>(executionStart - | ||
constructionStart); | ||
auto const execTime = std::chrono::duration_cast<std::chrono::microseconds>( | ||
executionStop - executionStart); | ||
result["construction_time"] = constructionTime.count(); | ||
result["execution_time"] = execTime.count(); | ||
|
||
result["executor"] = getIdentifier(); | ||
result["task"] = task.getIdentifier(); | ||
|
||
return result; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want the cpp-linter to work properly, you also have to set that option in the corresponding CI workflow (
.github/workflows/cpp-linter.yaml
)