From 8ac96771934265197be8ea2085ef4dba9ed29c2b Mon Sep 17 00:00:00 2001 From: Drewniok Date: Tue, 21 Feb 2023 14:00:56 +0100 Subject: [PATCH 1/9] :sparkles: multithreading implemented --- .../algorithms/simulation/sidb/quicksim.hpp | 79 +++++++++++++------ .../charge_distribution_surface.hpp | 7 ++ 2 files changed, 62 insertions(+), 24 deletions(-) diff --git a/include/fiction/algorithms/simulation/sidb/quicksim.hpp b/include/fiction/algorithms/simulation/sidb/quicksim.hpp index 468246963..d668040b6 100644 --- a/include/fiction/algorithms/simulation/sidb/quicksim.hpp +++ b/include/fiction/algorithms/simulation/sidb/quicksim.hpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include namespace fiction @@ -40,6 +42,11 @@ struct quicksim_params * Alpha parameter for the *quicksim* algorithm (should be reduced if no result is found). */ double alpha{0.7}; + + /** + * Number of spawning threads. + */ + uint64_t number_threads{std::thread::hardware_concurrency()}; }; /** @@ -90,6 +97,7 @@ void quicksim(const Lyt& lyt, const quicksim_params& ps = quicksim_params{}, qui static_assert(has_sidb_technology_v, "Lyt must be an SiDB layout"); quicksim_stats st{}; + st.valid_lyts.reserve(ps.interation_steps); // measure run time (artificial scope) { @@ -118,36 +126,59 @@ void quicksim(const Lyt& lyt, const quicksim_params& ps = quicksim_params{}, qui st.valid_lyts.push_back(charge_distribution_surface{charge_lyt}); } - auto best_energy = std::numeric_limits::max(); - const auto bound = static_cast(std::round(0.6 * static_cast(charge_lyt.num_cells()))); - for (uint64_t z = 0u; z < ps.interation_steps; z++) + // split the iterations among threads + const auto iter_per_thread = std::max( + ps.interation_steps / ps.number_threads, + static_cast(1u)); // If the number of set threads is greater than the number of iterations, the + // number of threads defines how many times QuickSim is repeated. + const auto bound = static_cast(std::round(0.6 * static_cast(charge_lyt.num_cells()))); + + std::vector threads; + std::mutex mutex; // used to control access to shared resources. + + for (uint64_t z = 0u; z < ps.number_threads; z++) { - for (uint64_t i = 0u; i < bound; i++) - { - std::vector index_start{i}; - charge_lyt.set_all_charge_states(sidb_charge_state::NEUTRAL); - charge_lyt.assign_charge_state_by_cell_index(i, sidb_charge_state::NEGATIVE); - charge_lyt.update_local_potential(); - charge_lyt.recompute_system_energy(); - - const auto upper_limit = static_cast(static_cast(charge_lyt.num_cells()) / 1.5); - for (uint64_t num = 0; num < upper_limit; num++) + threads.emplace_back( + [&] { - charge_lyt.adjacent_search(ps.alpha, index_start); - charge_lyt.validity_check(); - - if (charge_lyt.is_physically_valid() && (charge_lyt.get_system_energy() <= best_energy)) + charge_distribution_surface charge_lyt_copy{charge_lyt}; + for (uint64_t l = 0u; l < iter_per_thread; l++) { - st.valid_lyts.push_back(charge_distribution_surface{charge_lyt}); + for (uint64_t i = 0u; i < bound; i++) + { + std::vector index_start{i}; + charge_lyt_copy.set_all_charge_states(sidb_charge_state::NEUTRAL); + charge_lyt_copy.assign_charge_state_by_cell_index(i, sidb_charge_state::NEGATIVE); + charge_lyt_copy.update_local_potential(); + charge_lyt_copy.set_system_energy_to_zero(); + + const auto upper_limit = + static_cast(static_cast(charge_lyt_copy.num_cells()) / 1.5); + for (uint64_t num = 0; num < upper_limit; num++) + { + charge_lyt_copy.adjacent_search(ps.alpha, index_start); + charge_lyt_copy.validity_check(); + + if (charge_lyt_copy.is_physically_valid()) + { + std::lock_guard lock(mutex); + st.valid_lyts.push_back(charge_distribution_surface{charge_lyt_copy}); + } + } + } } - } - } + }); } - } - if (pst) - { - *pst = st; + for (auto& thread : threads) + { + thread.join(); + } + + if (pst) + { + *pst = st; + } } } diff --git a/include/fiction/technology/charge_distribution_surface.hpp b/include/fiction/technology/charge_distribution_surface.hpp index af1799bd9..a179ce0f4 100644 --- a/include/fiction/technology/charge_distribution_surface.hpp +++ b/include/fiction/technology/charge_distribution_surface.hpp @@ -509,6 +509,13 @@ class charge_distribution_surface : public Lyt return std::nullopt; } + /** + * Sets the electrostatic system energy to zero. Can be used if only one SiDB is charged. + */ + void set_system_energy_to_zero() noexcept + { + strg->system_energy = 0.0; + } /** * Calculates the system's total electrostatic potential energy and stores it in the storage. */ From 298f7f3a3599fba81e9137ca3d613420d822c435 Mon Sep 17 00:00:00 2001 From: Marcel Walter Date: Wed, 22 Feb 2023 12:04:28 +0100 Subject: [PATCH 2/9] :art: Incorporated small changes to the code structure --- .../simulation/sidb/is_ground_state.hpp | 12 ++-- .../algorithms/simulation/sidb/quicksim.hpp | 61 +++++++++++-------- .../simulation/sidb/time_to_solution.hpp | 10 +-- .../charge_distribution_surface.hpp | 5 +- 4 files changed, 50 insertions(+), 38 deletions(-) diff --git a/include/fiction/algorithms/simulation/sidb/is_ground_state.hpp b/include/fiction/algorithms/simulation/sidb/is_ground_state.hpp index 6da5e408c..0a8a49a5e 100644 --- a/include/fiction/algorithms/simulation/sidb/is_ground_state.hpp +++ b/include/fiction/algorithms/simulation/sidb/is_ground_state.hpp @@ -16,15 +16,13 @@ namespace fiction { /** - * This function checks if the ground state is found by the *quicksim* algorithm. + * This function checks if the ground state is found by the *QuickSim* algorithm. * * @tparam Lyt Cell-level layout type. - * @param quicksim_results All found physically valid charge distribution surfaces obtained by the quicksim algorithm - * (quicksim). - * @param exhaustive_results All valid charge distribution surfaces determined by ExGS - * (exhaustive_ground_state_simulation). - * @return Returns `true` if the relative difference between the lowest energies of the two sets is less than 0.00001, - * `false` otherwise. + * @param quicksim_results All found physically valid charge distribution surfaces obtained by the *QuickSim* algorithm. + * @param exhaustive_results All valid charge distribution surfaces determined by ExGS. + * @return Returns `true` if the relative difference between the lowest energies of the two sets is less than \f$ + * 0.00001 \f$, `false` otherwise. */ template [[nodiscard]] bool is_ground_state(const quicksim_stats& quicksim_results, diff --git a/include/fiction/algorithms/simulation/sidb/quicksim.hpp b/include/fiction/algorithms/simulation/sidb/quicksim.hpp index d668040b6..73d864150 100644 --- a/include/fiction/algorithms/simulation/sidb/quicksim.hpp +++ b/include/fiction/algorithms/simulation/sidb/quicksim.hpp @@ -26,7 +26,7 @@ namespace fiction { /** - * This struct stores the parameters for the *quicksim* algorithm. + * This struct stores the parameters for the *QuickSim* algorithm. */ struct quicksim_params { @@ -39,48 +39,59 @@ struct quicksim_params */ uint64_t interation_steps{80}; /** - * Alpha parameter for the *quicksim* algorithm (should be reduced if no result is found). + * `alpha` parameter for the *QuickSim* algorithm (should be reduced if no result is found). */ double alpha{0.7}; - /** - * Number of spawning threads. + * Number of threads to spawn. By default the number of threads is set to the number of available hardware threads. */ uint64_t number_threads{std::thread::hardware_concurrency()}; }; /** - * This struct stores the simulation runtime and all physically valid charge layouts gained by the quicksim algorithm. + * This struct stores the simulation runtime and all physically valid charge layouts gained by the *QuickSim* algorithm. * * @paramt Lyt Cell-level layout type. */ template struct quicksim_stats { - mockturtle::stopwatch<>::duration time_total{0}; + /** + * Total simulation runtime. + */ + mockturtle::stopwatch<>::duration time_total{0}; + /** + * Vector of all physically valid charge layouts. + */ std::vector> valid_lyts{}; - + /** + * Report the simulation statistics in a human-readable fashion. + * + * @param out Output stream to write to. + */ void report(std::ostream& out = std::cout) { - out << fmt::format("total time = {:.2f} secs\n", mockturtle::to_seconds(time_total)); + out << fmt::format("[i] total runtime: {:.2f} secs\n", mockturtle::to_seconds(time_total)); + if (!energy_distribution(valid_lyts).empty()) { for (auto [energy, count] : energy_distribution(valid_lyts)) { - out << fmt::format("[i] the lowest state energy is = {:.4f} \n", minimum_energy(valid_lyts)); - out << fmt::format("energy: {} | occurance: {} \n", energy, count); + out << fmt::format("[i] lowest energy state: {:.4f} meV \n", minimum_energy(valid_lyts)); + out << fmt::format("[i] energy: {} | occurrence: {} \n", energy, count); } } else { std::cout << "no state found" << std::endl; } + std::cout << "_____________________________________________________ \n"; } }; /** - * The *quicksim* algorithm is an electrostatic ground state simulation algorithm for SiDB layouts. It determines + * The *QuickSim* algorithm is an electrostatic ground state simulation algorithm for SiDB layouts. It determines * physically valid charge configurations (with minimal energy) of a given (already initialized) charge distribution * layout. Depending on the simulation parameters, the ground state is found with a certain probability after one run. * @@ -108,8 +119,6 @@ void quicksim(const Lyt& lyt, const quicksim_params& ps = quicksim_params{}, qui // set the given physical parameters charge_lyt.set_physical_parameters(ps.phys_params); - std::vector> result{}; - charge_lyt.set_all_charge_states(sidb_charge_state::NEUTRAL); charge_lyt.update_after_charge_change(); @@ -127,24 +136,27 @@ void quicksim(const Lyt& lyt, const quicksim_params& ps = quicksim_params{}, qui } // split the iterations among threads - const auto iter_per_thread = std::max( - ps.interation_steps / ps.number_threads, - static_cast(1u)); // If the number of set threads is greater than the number of iterations, the - // number of threads defines how many times QuickSim is repeated. + const auto iter_per_thread = + std::max(ps.interation_steps / ps.number_threads, + uint64_t{1}); // If the number of set threads is greater than the number of iterations, the + // number of threads defines how many times QuickSim is repeated + const auto bound = static_cast(std::round(0.6 * static_cast(charge_lyt.num_cells()))); - std::vector threads; - std::mutex mutex; // used to control access to shared resources. + std::vector threads{}; + threads.reserve(ps.number_threads); + std::mutex mutex{}; // used to control access to shared resources - for (uint64_t z = 0u; z < ps.number_threads; z++) + for (uint64_t z = 0ul; z < ps.number_threads; z++) { threads.emplace_back( [&] { charge_distribution_surface charge_lyt_copy{charge_lyt}; - for (uint64_t l = 0u; l < iter_per_thread; l++) + + for (uint64_t l = 0ul; l < iter_per_thread; ++l) { - for (uint64_t i = 0u; i < bound; i++) + for (uint64_t i = 0ul; i < bound; ++i) { std::vector index_start{i}; charge_lyt_copy.set_all_charge_states(sidb_charge_state::NEUTRAL); @@ -154,14 +166,15 @@ void quicksim(const Lyt& lyt, const quicksim_params& ps = quicksim_params{}, qui const auto upper_limit = static_cast(static_cast(charge_lyt_copy.num_cells()) / 1.5); - for (uint64_t num = 0; num < upper_limit; num++) + + for (uint64_t num = 0ul; num < upper_limit; num++) { charge_lyt_copy.adjacent_search(ps.alpha, index_start); charge_lyt_copy.validity_check(); if (charge_lyt_copy.is_physically_valid()) { - std::lock_guard lock(mutex); + const std::lock_guard lock{mutex}; st.valid_lyts.push_back(charge_distribution_surface{charge_lyt_copy}); } } diff --git a/include/fiction/algorithms/simulation/sidb/time_to_solution.hpp b/include/fiction/algorithms/simulation/sidb/time_to_solution.hpp index 01dc058da..e8f5258be 100644 --- a/include/fiction/algorithms/simulation/sidb/time_to_solution.hpp +++ b/include/fiction/algorithms/simulation/sidb/time_to_solution.hpp @@ -26,7 +26,7 @@ namespace fiction /** * This struct stores the time-to-solution, the simulation accuracy and the average single simulation runtime of - * quicksim (see quicksim.hpp). + * *QuickSim* (see quicksim.hpp). * */ struct time_to_solution_stats @@ -61,15 +61,15 @@ struct time_to_solution_stats } }; /** - * This function determines the time-to-solution (TTS) and the accuracy (acc) of the *quicksim* algorithm. + * This function determines the time-to-solution (TTS) and the accuracy (acc) of the *QuickSim* algorithm. * * @tparam Lyt Cell-level layout type. * @param lyt Layout that is used for the simulation. * @param sidb_params Physical SiDB parameters which are used for the simulation. * @param ps Pointer to a struct where the results (time_to_solution, acc, single runtime) are stored. - * @param repetitions Number of repetitions to determine the simulation accuracy (repetitions = 100 ==> accuracy is - * precise to 1%). - * @param confidence_level The time-to-solution also depends one the given confidence level which can be set here. + * @param repetitions Number of repetitions to determine the simulation accuracy (`repetitions = 100` means that + * accuracy is precise to 1%). + * @param confidence_level The time-to-solution also depends on the given confidence level which can be set here. */ template void sim_acc_tts(const Lyt& lyt, const quicksim_params& quicksim_params, time_to_solution_stats* ps = nullptr, diff --git a/include/fiction/technology/charge_distribution_surface.hpp b/include/fiction/technology/charge_distribution_surface.hpp index a179ce0f4..8745c7a4f 100644 --- a/include/fiction/technology/charge_distribution_surface.hpp +++ b/include/fiction/technology/charge_distribution_surface.hpp @@ -713,15 +713,16 @@ class charge_distribution_surface : public Lyt this->index_to_charge_distribution(); } /** - * This function is used for the *quicksim* algorithm (see quicksim.hpp). It gets a vector with indices representing + * This function is used for the *QuickSim* algorithm (see quicksim.hpp). It gets a vector with indices representing * negatively charged SiDBs as input. Afterward, a distant and a neutrally charged SiDB is localized using a min-max - * diversity algorithm. This selected SiDB is set to "negativ" and the index is added to the input vector such that + * diversity algorithm. This selected SiDB is set to "negative" and the index is added to the input vector such that * the next iteration works correctly. * * @param alpha A parameter for the algorithm (default: 0.7). * @param negative_indices Vector of SiDBs indices that are already negatively charged (double occupied). */ void adjacent_search(const double alpha, std::vector& negative_indices) noexcept + { double dist_max = 0; const auto reserve_size = this->num_cells() - negative_indices.size(); From b2dfe419fa28f7a69a9cb1034582742c37af48ec Mon Sep 17 00:00:00 2001 From: Marcel Walter Date: Wed, 22 Feb 2023 12:04:48 +0100 Subject: [PATCH 3/9] :bug: Fixed a potential bug in runtime measurement --- include/fiction/algorithms/simulation/sidb/quicksim.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/fiction/algorithms/simulation/sidb/quicksim.hpp b/include/fiction/algorithms/simulation/sidb/quicksim.hpp index 73d864150..b24b0b16b 100644 --- a/include/fiction/algorithms/simulation/sidb/quicksim.hpp +++ b/include/fiction/algorithms/simulation/sidb/quicksim.hpp @@ -187,11 +187,11 @@ void quicksim(const Lyt& lyt, const quicksim_params& ps = quicksim_params{}, qui { thread.join(); } + } - if (pst) - { - *pst = st; - } + if (pst) + { + *pst = st; } } From c1e47abce3669e8e5d032607820f4aabad7d3633 Mon Sep 17 00:00:00 2001 From: Drewniok Date: Wed, 22 Feb 2023 18:16:36 +0100 Subject: [PATCH 4/9] :white_check_mark: test for varying number of threads --- test/algorithms/simulation/sidb/quicksim.cpp | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/algorithms/simulation/sidb/quicksim.cpp b/test/algorithms/simulation/sidb/quicksim.cpp index cb78f05ab..52eb78cf9 100644 --- a/test/algorithms/simulation/sidb/quicksim.cpp +++ b/test/algorithms/simulation/sidb/quicksim.cpp @@ -74,4 +74,47 @@ TEMPLATE_TEST_CASE( CHECK(!it.charge_exists(sidb_charge_state::POSITIVE)); } } + + SECTION("varying thread counts") + { + TestType lyt{{20, 10}}; + + lyt.assign_cell_type({1, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({3, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({4, 3, 0}, TestType::cell_type::NORMAL); + + lyt.assign_cell_type({6, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({7, 3, 0}, TestType::cell_type::NORMAL); + + lyt.assign_cell_type({6, 10, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({7, 10, 0}, TestType::cell_type::NORMAL); + + quicksim_stats quicksimstats{}; + const sidb_simulation_parameters params{2, -0.30}; + const struct quicksim_params quicksim_params + { + params, 80, 0.7, 1 + }; + quicksim(lyt, quicksim_params, &quicksimstats); + CHECK(!quicksimstats.valid_lyts.empty()); + CHECK(quicksimstats.time_total.count() > 0); + + quicksim_stats quicksimstats_two_threads{}; + const struct quicksim_params quicksim_params_two_threads + { + params, 80, 0.7, 2 + }; + quicksim(lyt, quicksim_params_two_threads, &quicksimstats_two_threads); + CHECK(!quicksimstats_two_threads.valid_lyts.empty()); + CHECK(quicksimstats_two_threads.time_total.count() > 0); + + quicksim_stats quicksimstats_100_threads{}; + const struct quicksim_params quicksim_params_100_threads + { + params, 80, 0.7, 100 + }; + quicksim(lyt, quicksim_params_100_threads, &quicksimstats_100_threads); + CHECK(!quicksimstats_100_threads.valid_lyts.empty()); + CHECK(quicksimstats_100_threads.time_total.count() > 0); + } } From 9f72672fe08f9eb6bd8f3e386a3bc39213a4e765 Mon Sep 17 00:00:00 2001 From: Drewniok Date: Thu, 23 Feb 2023 09:49:56 +0100 Subject: [PATCH 5/9] :white_check_mark: single sections for varying number of threads and test for zero threads added --- test/algorithms/simulation/sidb/quicksim.cpp | 78 +++++++++++++++++--- 1 file changed, 67 insertions(+), 11 deletions(-) diff --git a/test/algorithms/simulation/sidb/quicksim.cpp b/test/algorithms/simulation/sidb/quicksim.cpp index 52eb78cf9..067dac87c 100644 --- a/test/algorithms/simulation/sidb/quicksim.cpp +++ b/test/algorithms/simulation/sidb/quicksim.cpp @@ -75,7 +75,31 @@ TEMPLATE_TEST_CASE( } } - SECTION("varying thread counts") + SECTION("zero threads") + { + TestType lyt{{20, 10}}; + + lyt.assign_cell_type({1, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({3, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({4, 3, 0}, TestType::cell_type::NORMAL); + + lyt.assign_cell_type({6, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({7, 3, 0}, TestType::cell_type::NORMAL); + + lyt.assign_cell_type({6, 10, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({7, 10, 0}, TestType::cell_type::NORMAL); + + quicksim_stats quicksimstats{}; + const sidb_simulation_parameters params{2, -0.30}; + const struct quicksim_params quicksim_params + { + params, 80, 0.7, 0 + }; + quicksim(lyt, quicksim_params, &quicksimstats); + CHECK(quicksimstats.valid_lyts.empty()); + } + + SECTION("one thread") { TestType lyt{{20, 10}}; @@ -98,23 +122,55 @@ TEMPLATE_TEST_CASE( quicksim(lyt, quicksim_params, &quicksimstats); CHECK(!quicksimstats.valid_lyts.empty()); CHECK(quicksimstats.time_total.count() > 0); + } + + SECTION("two threads") + { + TestType lyt{{20, 10}}; + + lyt.assign_cell_type({1, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({3, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({4, 3, 0}, TestType::cell_type::NORMAL); + + lyt.assign_cell_type({6, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({7, 3, 0}, TestType::cell_type::NORMAL); + + lyt.assign_cell_type({6, 10, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({7, 10, 0}, TestType::cell_type::NORMAL); - quicksim_stats quicksimstats_two_threads{}; - const struct quicksim_params quicksim_params_two_threads + quicksim_stats quicksimstats{}; + const sidb_simulation_parameters params{2, -0.30}; + const struct quicksim_params quicksim_params { params, 80, 0.7, 2 }; - quicksim(lyt, quicksim_params_two_threads, &quicksimstats_two_threads); - CHECK(!quicksimstats_two_threads.valid_lyts.empty()); - CHECK(quicksimstats_two_threads.time_total.count() > 0); + quicksim(lyt, quicksim_params, &quicksimstats); + CHECK(!quicksimstats.valid_lyts.empty()); + CHECK(quicksimstats.time_total.count() > 0); + } - quicksim_stats quicksimstats_100_threads{}; - const struct quicksim_params quicksim_params_100_threads + SECTION("two threads") + { + TestType lyt{{20, 10}}; + + lyt.assign_cell_type({1, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({3, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({4, 3, 0}, TestType::cell_type::NORMAL); + + lyt.assign_cell_type({6, 3, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({7, 3, 0}, TestType::cell_type::NORMAL); + + lyt.assign_cell_type({6, 10, 0}, TestType::cell_type::NORMAL); + lyt.assign_cell_type({7, 10, 0}, TestType::cell_type::NORMAL); + + quicksim_stats quicksimstats{}; + const sidb_simulation_parameters params{2, -0.30}; + const struct quicksim_params quicksim_params { params, 80, 0.7, 100 }; - quicksim(lyt, quicksim_params_100_threads, &quicksimstats_100_threads); - CHECK(!quicksimstats_100_threads.valid_lyts.empty()); - CHECK(quicksimstats_100_threads.time_total.count() > 0); + quicksim(lyt, quicksim_params, &quicksimstats); + CHECK(!quicksimstats.valid_lyts.empty()); + CHECK(quicksimstats.time_total.count() > 0); } } From a7b6a98819abf8d5f00ed1d8aa005c32ce4bb356 Mon Sep 17 00:00:00 2001 From: Drewniok Date: Thu, 23 Feb 2023 09:50:27 +0100 Subject: [PATCH 6/9] :white_check_mark: single sections for varying number of threads and test for zero threads added --- test/algorithms/simulation/sidb/quicksim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/algorithms/simulation/sidb/quicksim.cpp b/test/algorithms/simulation/sidb/quicksim.cpp index 067dac87c..e7f507fba 100644 --- a/test/algorithms/simulation/sidb/quicksim.cpp +++ b/test/algorithms/simulation/sidb/quicksim.cpp @@ -149,7 +149,7 @@ TEMPLATE_TEST_CASE( CHECK(quicksimstats.time_total.count() > 0); } - SECTION("two threads") + SECTION("100 threads") { TestType lyt{{20, 10}}; From 6f537882a95cc69c7763d14d658b7b6297033078 Mon Sep 17 00:00:00 2001 From: Drewniok Date: Thu, 23 Feb 2023 10:55:10 +0100 Subject: [PATCH 7/9] :white_check_mark: struct removed --- test/algorithms/simulation/sidb/quicksim.cpp | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/test/algorithms/simulation/sidb/quicksim.cpp b/test/algorithms/simulation/sidb/quicksim.cpp index e7f507fba..0539c6d62 100644 --- a/test/algorithms/simulation/sidb/quicksim.cpp +++ b/test/algorithms/simulation/sidb/quicksim.cpp @@ -91,10 +91,7 @@ TEMPLATE_TEST_CASE( quicksim_stats quicksimstats{}; const sidb_simulation_parameters params{2, -0.30}; - const struct quicksim_params quicksim_params - { - params, 80, 0.7, 0 - }; + const quicksim_params quicksim_params{params, 80, 0.7, 0}; quicksim(lyt, quicksim_params, &quicksimstats); CHECK(quicksimstats.valid_lyts.empty()); } @@ -115,10 +112,7 @@ TEMPLATE_TEST_CASE( quicksim_stats quicksimstats{}; const sidb_simulation_parameters params{2, -0.30}; - const struct quicksim_params quicksim_params - { - params, 80, 0.7, 1 - }; + const quicksim_params quicksim_params{params, 80, 0.7, 1}; quicksim(lyt, quicksim_params, &quicksimstats); CHECK(!quicksimstats.valid_lyts.empty()); CHECK(quicksimstats.time_total.count() > 0); @@ -140,10 +134,7 @@ TEMPLATE_TEST_CASE( quicksim_stats quicksimstats{}; const sidb_simulation_parameters params{2, -0.30}; - const struct quicksim_params quicksim_params - { - params, 80, 0.7, 2 - }; + const quicksim_params quicksim_params{params, 80, 0.7, 2}; quicksim(lyt, quicksim_params, &quicksimstats); CHECK(!quicksimstats.valid_lyts.empty()); CHECK(quicksimstats.time_total.count() > 0); @@ -165,10 +156,7 @@ TEMPLATE_TEST_CASE( quicksim_stats quicksimstats{}; const sidb_simulation_parameters params{2, -0.30}; - const struct quicksim_params quicksim_params - { - params, 80, 0.7, 100 - }; + const quicksim_params quicksim_params{params, 80, 0.7, 100}; quicksim(lyt, quicksim_params, &quicksimstats); CHECK(!quicksimstats.valid_lyts.empty()); CHECK(quicksimstats.time_total.count() > 0); From cca55afb23861bf22707fcc994f22ce8daa9517b Mon Sep 17 00:00:00 2001 From: Drewniok Date: Thu, 23 Feb 2023 12:18:39 +0100 Subject: [PATCH 8/9] :bug: If the number of threads is initially set to zero, the simulation is run with one thread. --- include/fiction/algorithms/simulation/sidb/quicksim.hpp | 9 ++++++--- test/algorithms/simulation/sidb/quicksim.cpp | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/fiction/algorithms/simulation/sidb/quicksim.hpp b/include/fiction/algorithms/simulation/sidb/quicksim.hpp index b24b0b16b..a459d5a5a 100644 --- a/include/fiction/algorithms/simulation/sidb/quicksim.hpp +++ b/include/fiction/algorithms/simulation/sidb/quicksim.hpp @@ -135,19 +135,22 @@ void quicksim(const Lyt& lyt, const quicksim_params& ps = quicksim_params{}, qui st.valid_lyts.push_back(charge_distribution_surface{charge_lyt}); } + // If the number of threads is initially set to zero, the simulation is run with one thread. + uint64_t num_threads = std::max(ps.number_threads, uint64_t{1}); + // split the iterations among threads const auto iter_per_thread = - std::max(ps.interation_steps / ps.number_threads, + std::max(ps.interation_steps / num_threads, uint64_t{1}); // If the number of set threads is greater than the number of iterations, the // number of threads defines how many times QuickSim is repeated const auto bound = static_cast(std::round(0.6 * static_cast(charge_lyt.num_cells()))); std::vector threads{}; - threads.reserve(ps.number_threads); + threads.reserve(num_threads); std::mutex mutex{}; // used to control access to shared resources - for (uint64_t z = 0ul; z < ps.number_threads; z++) + for (uint64_t z = 0ul; z < num_threads; z++) { threads.emplace_back( [&] diff --git a/test/algorithms/simulation/sidb/quicksim.cpp b/test/algorithms/simulation/sidb/quicksim.cpp index 0539c6d62..1df72e093 100644 --- a/test/algorithms/simulation/sidb/quicksim.cpp +++ b/test/algorithms/simulation/sidb/quicksim.cpp @@ -93,7 +93,8 @@ TEMPLATE_TEST_CASE( const sidb_simulation_parameters params{2, -0.30}; const quicksim_params quicksim_params{params, 80, 0.7, 0}; quicksim(lyt, quicksim_params, &quicksimstats); - CHECK(quicksimstats.valid_lyts.empty()); + CHECK(!quicksimstats.valid_lyts.empty()); + CHECK(quicksimstats.time_total.count() > 0); } SECTION("one thread") From d5240bd5f9ae220b9dff73be123a8265defa53b9 Mon Sep 17 00:00:00 2001 From: Drewniok Date: Thu, 23 Feb 2023 13:43:20 +0100 Subject: [PATCH 9/9] :art: added const keyword and short description. --- include/fiction/algorithms/simulation/sidb/quicksim.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/fiction/algorithms/simulation/sidb/quicksim.hpp b/include/fiction/algorithms/simulation/sidb/quicksim.hpp index a459d5a5a..83a0753e5 100644 --- a/include/fiction/algorithms/simulation/sidb/quicksim.hpp +++ b/include/fiction/algorithms/simulation/sidb/quicksim.hpp @@ -136,7 +136,7 @@ void quicksim(const Lyt& lyt, const quicksim_params& ps = quicksim_params{}, qui } // If the number of threads is initially set to zero, the simulation is run with one thread. - uint64_t num_threads = std::max(ps.number_threads, uint64_t{1}); + const uint64_t num_threads = std::max(ps.number_threads, uint64_t{1}); // split the iterations among threads const auto iter_per_thread = @@ -144,7 +144,8 @@ void quicksim(const Lyt& lyt, const quicksim_params& ps = quicksim_params{}, qui uint64_t{1}); // If the number of set threads is greater than the number of iterations, the // number of threads defines how many times QuickSim is repeated - const auto bound = static_cast(std::round(0.6 * static_cast(charge_lyt.num_cells()))); + // Only 60 % of all cells are used as the negatively charged cell in the first iteration step. + const auto upper_bound = static_cast(std::round(0.6 * static_cast(charge_lyt.num_cells()))); std::vector threads{}; threads.reserve(num_threads); @@ -159,7 +160,7 @@ void quicksim(const Lyt& lyt, const quicksim_params& ps = quicksim_params{}, qui for (uint64_t l = 0ul; l < iter_per_thread; ++l) { - for (uint64_t i = 0ul; i < bound; ++i) + for (uint64_t i = 0ul; i < upper_bound; ++i) { std::vector index_start{i}; charge_lyt_copy.set_all_charge_states(sidb_charge_state::NEUTRAL);