diff --git a/src/algorithm/nd_sort.cpp b/src/algorithm/nd_sort.cpp index 3e61677c..42f29411 100644 --- a/src/algorithm/nd_sort.cpp +++ b/src/algorithm/nd_sort.cpp @@ -188,8 +188,10 @@ 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) { + GAPP_BARRIER(); FitnessVector fvec(popsize); std::transform(first, last, fvec.begin(), detail::element_at(obj)); @@ -210,10 +212,13 @@ namespace gapp::algorithm::dtl } }); }); + GAPP_BARRIER(); }); + GAPP_BARRIER(); std::for_each(GAPP_EXEC, detail::iota_iterator(0_sz), detail::iota_iterator(popsize), [&](size_t row) noexcept { + GAPP_BARRIER(); dmat(row, row).store(NONMAXIMAL, std::memory_order_relaxed); // diagonal is all nonmax for (size_t col = row + 1; col < popsize; col++) @@ -224,7 +229,9 @@ namespace gapp::algorithm::dtl dmat(col, row).store(NONMAXIMAL, std::memory_order_relaxed); } } + GAPP_BARRIER(); }); + GAPP_BARRIER(); return dmat; } diff --git a/src/algorithm/nsga3.cpp b/src/algorithm/nsga3.cpp index ed1b6f55..a67a6c17 100644 --- a/src/algorithm/nsga3.cpp +++ b/src/algorithm/nsga3.cpp @@ -239,8 +239,10 @@ namespace gapp::algorithm sol_info_.resize(last - first); + GAPP_BARRIER(); std::for_each(GAPP_EXEC, pfirst, plast, [&](const FrontInfo& sol) { + GAPP_BARRIER(); const FitnessVector fnorm = normalizeFitnessVec(first[sol.idx], ideal_point_, nadir_point_); auto idistance = [&](const auto& line) { return std::inner_product(fnorm.begin(), fnorm.end(), line.begin(), 0.0); }; @@ -250,6 +252,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..827bde10 100644 --- a/src/algorithm/reference_lines.cpp +++ b/src/algorithm/reference_lines.cpp @@ -182,13 +182,16 @@ 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 { + GAPP_BARRIER(); 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..0a08a66c 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)); - std::for_each(GAPP_EXEC, population_.begin(), population_.end(), [this](Candidate& sol) { evaluate(sol); }); + GAPP_BARRIER(); + std::for_each(GAPP_EXEC, population_.begin(), population_.end(), [this](Candidate& sol) { GAPP_BARRIER(); evaluate(sol); }); + GAPP_BARRIER(); fitness_matrix_ = detail::toFitnessMatrix(population_); if (keep_all_optimal_sols_) solutions_ = detail::findParetoFront(population_); @@ -504,27 +506,33 @@ namespace gapp std::vector> child_pairs(num_children / 2); prepareSelections(); + GAPP_BARRIER(); std::generate(GAPP_EXEC, child_pairs.begin(), child_pairs.end(), [this] { + GAPP_BARRIER(); const auto& parent1 = select(); const auto& parent2 = select(); 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) { + GAPP_BARRIER(); mutate(child); 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..58f89405 100644 --- a/src/metrics/pop_stats.cpp +++ b/src/metrics/pop_stats.cpp @@ -154,8 +154,10 @@ 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) { + GAPP_BARRIER(); const auto point = front[idx]; const FitnessMatrix rest = { front.begin() + idx + 1, front.end() }; @@ -163,6 +165,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..18523a78 100644 --- a/src/population/population.hpp +++ b/src/population/population.hpp @@ -106,8 +106,10 @@ 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 { + GAPP_BARRIER(); for (size_t j = 0; j < rhs.size(); j++) { const Dominance rhs_state_j = rhs_state[j].load(std::memory_order_acquire); @@ -146,6 +148,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