rosa/bench/graspels/hw.cpp

221 lines
5.2 KiB
C++

#include "common.h"
auto hwElsGen(tsp::Solution const& solution, RNG& rng) {
return Descent{}(Move2Opt{}(solution, rng));
}
#if PARLEV==2
auto hwElsInner(tsp::Solution const& solution, RNG& rng, std::size_t nCore) {
std::size_t const nThreads = std::min<std::size_t>(nCore, ELS_GEN);
std::size_t const step = ELS_GEN/nThreads;
std::size_t remain = ELS_GEN - step*nThreads;
// std::cout << "LEVEL #2 : " << nCore << ";" << nThreads << ";" << step << ";" << remain << std::endl;
std::vector<std::thread> threads{nThreads-1};
std::vector<tsp::Solution> solutions(nThreads);
tsp::Solution best;
/* repeatability at loop level */
std::vector<RNG> rngs(ELS_GEN);
for(std::size_t i = 0; i < ELS_GEN; ++i)
rngs[i].seed(rng());
/* ***** */
std::size_t start{};
for(std::size_t i{}; i < (nThreads-1); ++i) {
std::size_t offset = !!remain;
remain -= offset;
threads[i] = std::thread{
[&,start,i,step=step+offset](auto const& solution) {
tsp::Solution& s = solutions[i];
for(std::size_t j{}; j < step; ++j) {
tsp::Solution cur = hwElsGen(solution, rngs[start+j]);
s = selectMin(std::move(s), std::move(cur));
}
},
std::cref(solution)
};
start += step+offset;
}
{
tsp::Solution& s = solutions[nThreads-1];
for(std::size_t j{}; j < step; ++j) {
tsp::Solution cur = hwElsGen(solution, rngs[start+j]);
s = selectMin(std::move(s), std::move(cur));
}
}
for(auto& thread: threads) thread.join();
best = *std::min_element(std::begin(solutions), std::end(solutions));
return best;
}
#else
auto hwElsInner(tsp::Solution const& solution, RNG& rng, std::size_t) {
tsp::Solution best;
/* repeatability at loop level */
std::vector<RNG> rngs(ELS_GEN);
for(std::size_t i = 0; i < ELS_GEN; ++i)
rngs[i].seed(rng());
/* ***** */
if(ELS_GEN)
best = hwElsGen(solution, rngs[0]);
for(std::size_t i = 1; i < ELS_GEN; ++i) {
tsp::Solution current = hwElsGen(solution, rngs[i]);
best = selectMin(std::move(best), std::move(current));
}
return best;
}
#endif
auto hwEls(tsp::Solution const& solution, RNG& rng, 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, rng, nCore);
best = selectMin(std::move(best), std::move(current));
}
return best;
}
auto hwGraspGen(tsp::Problem const& problem, RNG& rng, std::size_t nCore = 1) {
return hwEls(rgreedy()(problem, rng), rng, nCore);
}
/* *** */
auto hwGraspEls(tsp::Problem const& problem, RNG& rng) {
tsp::Solution best;
/* repeatability at loop level */
std::vector<RNG> rngs(GRASP_N);
for(std::size_t i = 0; i < GRASP_N; ++i)
rngs[i].seed(rng());
/* ***** */
if(GRASP_N)
best = hwGraspGen(problem, rngs[0]);
for(std::size_t i = 1; i < GRASP_N; ++i) {
tsp::Solution current = hwGraspGen(problem, rngs[i]);
best = selectMin(std::move(best), std::move(current));
}
return best;
}
template<std::size_t K>
auto hwGraspElsPar(tsp::Problem const& problem, RNG& rng) {
std::size_t const nThreads = std::min<std::size_t>(K, GRASP_N);
std::size_t const step = GRASP_N/nThreads;
std::size_t const remain = GRASP_N - step*nThreads;
std::size_t cores2a = K/nThreads;
std::size_t cores2b = (remain==0 ? 1 : K/remain);
// std::cout << "LEVEL #1 : " << K << ";" << nThreads << ";" << step << ";" << remain << std::endl;
tsp::Solution best;
std::vector<std::thread> threadsA{nThreads-1};
std::vector<std::thread> threadsB{remain==0 ? 0 : remain-1};
std::vector<tsp::Solution> solutions(nThreads+remain);
/* repeatability at loop level */
std::vector<RNG> rngs(GRASP_N);
for(std::size_t i = 0; i < GRASP_N; ++i)
rngs[i].seed(rng());
/* ***** */
std::size_t start{};
std::size_t i{};
/* Loop A */
for(; i < (nThreads-1); ++i) {
threadsA[i] = std::thread{
[&,start,i,cores2a](auto const& problem) {
tsp::Solution& s = solutions[i];
for(std::size_t j{}; j < step; ++j) {
tsp::Solution cur = hwGraspGen(problem, rngs[start+j],cores2a);
s = selectMin(std::move(s), std::move(cur));
}
},
std::cref(problem)
};
start += step;
}
{
tsp::Solution& s = solutions[i];
for(std::size_t j{}; j < step; ++j) {
tsp::Solution cur = hwGraspGen(problem, rngs[start+j],cores2a);
s = selectMin(std::move(s), std::move(cur));
}
start+=step;
++i;
}
for(auto& thread: threadsA) thread.join();
/* Loop B */
for(; i < nThreads+remain-1; ++i) {
threadsB[i-nThreads] = std::thread{
[&,start,i,cores2b](auto const& problem) {
tsp::Solution& s = solutions[i];
tsp::Solution cur = hwGraspGen(problem, rngs[start],cores2b);
s = selectMin(std::move(s), std::move(cur));
},
std::cref(problem)
};
++start;
}
if (remain>0)
{
tsp::Solution& s = solutions[i];
tsp::Solution cur = hwGraspGen(problem, rngs[start],cores2b);
s = selectMin(std::move(s), std::move(cur));
++start;
++i;
}
for(auto& thread: threadsB) thread.join();
/* Selection */
best = *std::min_element(std::begin(solutions), std::end(solutions));
return best;
}
/* *** */
tsp::Solution hw_seq(tsp::Problem const& p, RNG& rng, Arguments const&) {
return hwGraspEls(p, rng);
}
tsp::Solution hw_par(tsp::Problem const& p, RNG& rng, Arguments const&) {
return hwGraspElsPar<NTHREADS>(p, rng);
}