diff --git a/src/algorithm/nd_sort.cpp b/src/algorithm/nd_sort.cpp index 3e61677c..a401bb58 100644 --- a/src/algorithm/nd_sort.cpp +++ b/src/algorithm/nd_sort.cpp @@ -188,6 +188,7 @@ namespace gapp::algorithm::dtl const size_t popsize = std::distance(first, last); DominanceMatrix dmat(popsize, popsize /*, MAXIMAL */); + GAPP_BARRIER(); std::for_each(GAPP_EXEC, detail::iota_iterator(0_sz), detail::iota_iterator(first->size()), [&](size_t obj) { FitnessVector fvec(popsize); @@ -211,6 +212,7 @@ namespace gapp::algorithm::dtl }); }); }); + GAPP_BARRIER(); std::for_each(GAPP_EXEC, detail::iota_iterator(0_sz), detail::iota_iterator(popsize), [&](size_t row) noexcept { @@ -225,6 +227,7 @@ namespace gapp::algorithm::dtl } } }); + GAPP_BARRIER(); return dmat; } diff --git a/src/algorithm/nsga3.cpp b/src/algorithm/nsga3.cpp index ed1b6f55..a051abaa 100644 --- a/src/algorithm/nsga3.cpp +++ b/src/algorithm/nsga3.cpp @@ -239,6 +239,7 @@ namespace gapp::algorithm sol_info_.resize(last - first); + GAPP_BARRIER(); std::for_each(GAPP_EXEC, pfirst, plast, [&](const FrontInfo& sol) { const FitnessVector fnorm = normalizeFitnessVec(first[sol.idx], ideal_point_, nadir_point_); @@ -250,6 +251,7 @@ namespace gapp::algorithm sol_info_[sol.idx].ref_idx = std::distance(ref_lines_.begin(), closest); sol_info_[sol.idx].ref_dist = math::perpendicularDistanceSq(*closest, fnorm); }); + GAPP_BARRIER(); } inline bool NSGA3::Impl::nichedCompare(size_t lhs, size_t rhs) const noexcept diff --git a/src/algorithm/reference_lines.cpp b/src/algorithm/reference_lines.cpp index f09c556c..ce39bdb0 100644 --- a/src/algorithm/reference_lines.cpp +++ b/src/algorithm/reference_lines.cpp @@ -182,6 +182,7 @@ namespace gapp::algorithm::reflines std::swap(min_distances[idx], min_distances.back()); min_distances.pop_back(); + GAPP_BARRIER(); /* Calc the distance of each candidate to the closest ref point. */ std::transform(GAPP_EXEC, candidate_points.begin(), candidate_points.end(), min_distances.begin(), min_distances.begin(), [&](const Point& candidate, double current_min) noexcept @@ -189,6 +190,7 @@ namespace gapp::algorithm::reflines const double dist = math::euclideanDistanceSq(candidate, points.back()); return std::min(current_min, dist); }); + GAPP_BARRIER(); } return points; diff --git a/src/core/ga_base.impl.hpp b/src/core/ga_base.impl.hpp index b3eff970..a105fba8 100644 --- a/src/core/ga_base.impl.hpp +++ b/src/core/ga_base.impl.hpp @@ -339,7 +339,9 @@ namespace gapp /* Create and evaluate the initial population of the algorithm. */ num_objectives_ = findNumberOfObjectives(); population_ = generatePopulation(population_size_, std::move(initial_population)); + GAPP_BARRIER(); std::for_each(GAPP_EXEC, population_.begin(), population_.end(), [this](Candidate& sol) { evaluate(sol); }); + GAPP_BARRIER(); fitness_matrix_ = detail::toFitnessMatrix(population_); if (keep_all_optimal_sols_) solutions_ = detail::findParetoFront(population_); @@ -504,6 +506,7 @@ namespace gapp std::vector> child_pairs(num_children / 2); prepareSelections(); + GAPP_BARRIER(); std::generate(GAPP_EXEC, child_pairs.begin(), child_pairs.end(), [this] { @@ -512,12 +515,14 @@ namespace gapp return crossover(parent1, parent2); }); + GAPP_BARRIER(); auto children = detail::flatten(std::move(child_pairs)); /* If the population size is odd, one too many child candidates were generated by the crossovers. */ if (children.size() > population_size_) children.pop_back(); + GAPP_BARRIER(); std::for_each(GAPP_EXEC, children.begin(), children.end(), [this](Candidate& child) { @@ -525,6 +530,7 @@ namespace gapp repair(child); evaluate(child); }); + GAPP_BARRIER(); updatePopulation(std::move(children)); if (keep_all_optimal_sols_) updateOptimalSolutions(solutions_, population_); diff --git a/src/metrics/pop_stats.cpp b/src/metrics/pop_stats.cpp index e96ea1e1..8e802a5f 100644 --- a/src/metrics/pop_stats.cpp +++ b/src/metrics/pop_stats.cpp @@ -154,6 +154,7 @@ namespace gapp::detail const FitnessMatrix front = uniqueSortedParetoFront(fmat); std::atomic hypervolume = 0.0; + GAPP_BARRIER(); std::for_each(GAPP_EXEC, detail::iota_iterator(0_sz), detail::iota_iterator(front.size()), [&](size_t idx) { const auto point = front[idx]; @@ -163,6 +164,7 @@ namespace gapp::detail hypervolume.fetch_add(exclusive_hypervolume, std::memory_order_acq_rel); }); + GAPP_BARRIER(); return hypervolume.load(std::memory_order_acquire); } diff --git a/src/population/population.hpp b/src/population/population.hpp index 1f6cd533..4080e120 100644 --- a/src/population/population.hpp +++ b/src/population/population.hpp @@ -106,6 +106,7 @@ namespace gapp::detail std::vector lhs_state(lhs.size()); std::vector> rhs_state(rhs.size()); + GAPP_BARRIER(); std::for_each(GAPP_EXEC, iota_iterator(0_sz), iota_iterator(lhs.size()), [&](size_t i) noexcept { for (size_t j = 0; j < rhs.size(); j++) @@ -146,6 +147,7 @@ namespace gapp::detail // comp == 0 --> both are OPTIMAL or DOMINATED, can't know } }); + GAPP_BARRIER(); Candidates optimal_solutions; optimal_solutions.reserve(lhs.size() + rhs.size()); diff --git a/src/utility/utility.hpp b/src/utility/utility.hpp index 252b86ba..765a37c3 100644 --- a/src/utility/utility.hpp +++ b/src/utility/utility.hpp @@ -111,6 +111,11 @@ #endif +#include +inline std::atomic_bool global_barrier; +#define GAPP_BARRIER() std::ignore = global_barrier.exchange(true, std::memory_order_acq_rel) + + namespace gapp { constexpr std::size_t operator ""_sz(unsigned long long arg) noexcept