rosa/bench/graspels/hwv.cpp

189 lines
5.0 KiB
C++

#include "common.h"
auto hwElsGenV(tsp::Solution const& solution, RNG& rng) {
return Descent{}(Move2Opt{}(solution, rng));
}
auto hwElsInner(tsp::Solution const& solution, std::vector<RNG>& rngs, std::size_t id, std::size_t nCore) {
std::size_t n = ELS_GEN;
std::size_t maxThreads = nCore;
std::size_t const nThreads = std::min<std::size_t>(maxThreads, ELS_GEN);
std::vector<std::thread> threads{nThreads-1};
std::size_t const step = n/nThreads;
std::size_t const remainBase = n - step*nThreads;
std::size_t remain = remainBase;
auto run = [&solution,&rngs](tsp::Solution& out, std::size_t id, std::size_t k) {
tsp::Solution best{};
if(k)
best = hwElsGenV(solution, rngs[id]);
for(std::size_t i = 1; i < k; ++i) {
tsp::Solution current = hwElsGenV(solution, rngs[id+i]);
best = selectMin(std::move(best), std::move(current));
}
out = std::move(best);
};
std::size_t start{};
std::vector<tsp::Solution> bests(nThreads);
for(std::size_t i = 0; i < nThreads-1; ++i) {
std::size_t offset = !!remain;
remain -= offset;
threads[i] = std::thread{run, std::ref(bests[i]), id+start, step+offset};
start += step+offset;
}
run(bests[nThreads-1], id+start, step);
for(auto& thread: threads) thread.join();
tsp::Solution best;
// best = *std::min_element(std::begin(solutions), std::end(solutions));
if(nThreads) best = std::move(bests[0]);
for(std::size_t i = 1; i < nThreads; ++i)
best = selectMin(std::move(best), std::move(bests[i]));
return best;
}
auto hwEls(tsp::Solution const& solution, std::vector<RNG>& rngs, std::size_t id, std::size_t nCore) {
tsp::Solution best = Descent{}(solution);
for(std::size_t i = 0; i < ELS_ITER_MAX; ++i) {
tsp::Solution current = hwElsInner(best, rngs, id, nCore);
best = selectMin(std::move(best), std::move(current));
}
return best;
}
auto hwGraspGen(tsp::Problem const& problem, std::vector<RNG>& rngs, std::size_t id, std::size_t nCore = 1) {
return hwEls(rgreedy()(problem, rngs[id]), rngs, id, nCore);
}
/* *** */
auto hwGraspEls(tsp::Problem const& problem, std::vector<RNG>& rngs) {
tsp::Solution best;
auto graspIter = [&](tsp::Problem const& problem, tsp::Solution& s, std::size_t id) {
tsp::Solution cur = hwGraspGen(problem, rngs, id);
s = selectMin(std::move(s), std::move(cur));
};
if(GRASP_N) {
auto graspInit = [&](tsp::Problem const& problem, tsp::Solution& s) {
s = hwGraspGen(problem, rngs, 0);
};
#ifdef SUBTIME
timeit(RUSAGE_THREAD, "[GRASP] ", graspInit, problem, best);
#else
graspInit(problem, best);
#endif
}
for(std::size_t i = 1; i < GRASP_N; ++i) {
#ifdef SUBTIME
timeit(RUSAGE_THREAD, "[GRASP] ", graspIter, problem, best, i*ELS_GEN);
#else
graspIter(problem, best, i*ELS_GEN);
#endif
}
return best;
}
template<std::size_t K>
auto hwGraspElsPar(tsp::Problem const& problem, std::vector<RNG>& rngs) {
std::size_t const n = GRASP_N;
std::size_t const maxThreads = K;
std::size_t const nThreads = std::min<std::size_t>(maxThreads, n);
std::size_t const cores = maxThreads/nThreads;
std::vector<std::thread> threads(nThreads-1);
std::size_t const step = n/nThreads;
std::size_t const remainBase = n - step*nThreads;
std::size_t remain = remainBase;
auto iter0 = [&problem,&rngs](tsp::Solution& best, std::size_t id, std::size_t cores) {
best = hwGraspGen(problem, rngs, id, cores);
};
auto iter = [&problem,&rngs](tsp::Solution& best, std::size_t id, std::size_t cores) {
tsp::Solution current = hwGraspGen(problem, rngs, id, cores);
best = selectMin(std::move(best), std::move(current));
};
auto run = [&](tsp::Solution& out, std::size_t id, std::size_t k, std::size_t cores) {
tsp::Solution best{};
if(k) {
#ifdef SUBTIME
timeit(RUSAGE_THREAD, "[GRASP] ", iter0, best, id*ELS_GEN, cores);
#else
iter0(best, id*ELS_GEN, cores);
#endif
}
for(std::size_t i = 1; i < k; ++i) {
#ifdef SUBTIME
timeit(RUSAGE_THREAD, "[GRASP] ", iter, best, (id+i)*ELS_GEN, cores);
#else
iter(best, (id+1)*ELS_GEN, cores);
#endif
}
out = std::move(best);
};
std::size_t start{};
std::vector<tsp::Solution> bests(nThreads);
for(std::size_t i = 0; i < nThreads-1; ++i) {
std::size_t offset = !!remain;
remain -= offset;
threads[i] = std::thread{run, std::ref(bests[i]), start, step+offset, cores};
start += step+offset;
}
run(bests[nThreads-1], start, step, cores);
for(std::thread& thread: threads) thread.join();
tsp::Solution best;
if(nThreads) best = std::move(bests[0]);
for(std::size_t i = 1; i < nThreads; ++i)
best = selectMin(std::move(best), std::move(bests[i]));
return best;
}
/* *** */
tsp::Solution hw_seq_v(tsp::Problem const& p, RNG& seeder, Arguments const&) {
std::size_t n = GRASP_N * ELS_GEN;
std::vector<RNG> rngs;
rngs.reserve(n);
for(std::size_t i = 0; i < n; ++i)
rngs.emplace_back(seeder());
return hwGraspEls(p, rngs);
}
tsp::Solution hw_par_v(tsp::Problem const& p, RNG& seeder, Arguments const&) {
std::size_t n = GRASP_N * ELS_GEN;
std::vector<RNG> rngs;
rngs.reserve(n);
for(std::size_t i = 0; i < n; ++i)
rngs.emplace_back(seeder());
return hwGraspElsPar<NTHREADS>(p, rngs);
}