thesis version

This commit is contained in:
2021-05-10 18:14:24 +02:00
commit caf2a692f9
281 changed files with 73182 additions and 0 deletions

View File

@ -0,0 +1,106 @@
#ifndef ROSA_BENCH_GRASPELS_BAD_GRASPELS_H
#define ROSA_BENCH_GRASPELS_BAD_GRASPELS_H
#include <alsk/alsk.h>
namespace rosa {
/* GRASP
* loop
* * s = init()
* * s = ls(s)
* * best = select(s, best)
* ----
* return best
*/
template<typename Init, typename LS, typename Select>
using SkelNRGraspStructure =
alsk::S<alsk::FarmSel,
alsk::S<alsk::Serial, Init, LS>,
Select
>;
template<typename Problem, typename Solution, typename RNG>
using SkelNRGraspLinks =
alsk::L<alsk::FarmSel, Solution(Problem const&, RNG&),
alsk::L<alsk::Serial, alsk::arg::R<1>(alsk::arg::P<0>, alsk::arg::P<1>),
Solution(alsk::arg::P<0>, alsk::arg::P<1>),
Solution(alsk::arg::R<0> const&, alsk::arg::P<1>)
>,
Solution(Solution const&, Solution const&)
>;
/* *** */
template<
typename Problem, typename Solution, typename RNG,
typename Init, typename LS, typename Select
>
using SkelNRGrasp = alsk::BuildSkeleton<SkelNRGraspStructure, SkelNRGraspLinks>::skeleton<
tmp::Pack<Init, LS, Select>,
tmp::Pack<Problem, Solution, RNG>
>;
}
namespace rosa {
/* ELS
* best = ls(s) -- SEls
* loop -- SElsOuterLoop
* * loop -- SElsInnerLoop
* * * s = mutate(best) -- SElsGen
* * * s = ls(s)
* * * ibest = select(s, ibest)
* * ----
* * best = select(s, best) // with acceptation criteria?
* ----
* return best
*/
template<
typename InitLS, typename Mutate, typename LS,
typename InnerSelect, typename OuterSelect
>
using SkelNRElsStruct =
alsk::S<alsk::Serial,
InitLS,
alsk::S<alsk::IterSel,
alsk::S<alsk::FarmSel,
alsk::S<alsk::Serial,
Mutate, LS
>,
InnerSelect
>,
OuterSelect
>
>;
template<typename Solution, typename RNG>
using SkelNRElsLinks =
alsk::L<alsk::Serial, alsk::arg::R<1>(Solution const&, RNG&),
Solution(alsk::arg::P<0>),
alsk::L<alsk::IterSel, Solution(alsk::arg::R<0> const&, alsk::arg::P<1>),
alsk::L<alsk::FarmSel, Solution(Solution const&, alsk::arg::P<1>),
alsk::L<alsk::Serial, alsk::arg::R<1>(alsk::arg::P<0>, alsk::arg::P<1>),
Solution(alsk::arg::P<0>, alsk::arg::P<1>),
Solution(alsk::arg::R<0> const&)
>,
Solution(Solution const&, Solution const&)
>,
Solution(Solution const&, Solution const&)
>
>;
template<
typename Solution, typename RNG,
typename InitLS, typename Mutate, typename LS,
typename InnerSelect, typename OuterSelect = InnerSelect
>
using SkelNREls = alsk::BuildSkeleton<SkelNRElsStruct, SkelNRElsLinks>::skeleton<
tmp::Pack<InitLS, Mutate, LS, InnerSelect, OuterSelect>,
tmp::Pack<Solution, RNG>
>;
}
#endif

86
bench/graspels/common.h Normal file
View File

@ -0,0 +1,86 @@
#ifndef ROSA_BENCH_GRASPELS_COMMON_H
#define ROSA_BENCH_GRASPELS_COMMON_H
#include <algorithm>
#include <iostream>
#include <random>
#include <thread>
#include <sys/resource.h>
#include <sys/time.h>
#include <alsk/alsk.h>
#include <muscles/descent.h>
#include <muscles/move2opt.h>
#include <muscles/rgreedy.h>
#include <rosa/els.h>
#include <rosa/grasp.h>
#include <tsp/solution.h>
#include <tsp/problem.h>
#include <tsp/tsp.h>
#ifndef DATA_FILE
#define DATA_FILE "../data/qa194"
#endif
#ifndef GRASP_N
#define GRASP_N 2
#endif
#ifndef ELS_ITER_MAX
#define ELS_ITER_MAX 20
#endif
#ifndef ELS_GEN
#define ELS_GEN 10
#endif
#ifndef FUNC
#define FUNC none
#endif
#ifndef NTHREADS
#define NTHREADS 1
#endif
#ifndef SEED
#define SEED std::mt19937::default_seed
#endif
#define STR_(A) #A
#define STR(A) STR_(A)
/* repeatable* */
#define REPRODUCIBLE
using RNG = std::mt19937;
struct Arguments {
std::mt19937::result_type seed;
};
inline tsp::Solution selectMin(tsp::Solution const& a, tsp::Solution const& b) { return a<b? a:b; }
inline auto rgreedy() { return RGreedy<tsp::Solution>{2}; }
inline double tvdiff(struct timeval& b, struct timeval& e) {
return (e.tv_sec - b.tv_sec) + (e.tv_usec - b.tv_usec) / 1e6;
}
template<typename F, typename... Args>
void timeit(int who, std::string const& prefix, F&& f, Args&&... args) {
using Clock = std::chrono::high_resolution_clock;
struct rusage b, e;
auto tp0 = Clock::now();
getrusage(who, &b);
std::forward<F>(f)(std::forward<Args>(args)...);
getrusage(who, &e);
auto tp1 = Clock::now();
std::cout << prefix;
std::cout << "[" << std::this_thread::get_id() << "] ";
std::cout << "time: ";
std::cout << "real " << std::chrono::duration<double>(tp1 - tp0).count() << " ";
std::cout << "user " << tvdiff(b.ru_utime, e.ru_utime) << " ";
std::cout << "sys " << tvdiff(b.ru_stime, e.ru_stime);
std::cout << std::endl;
}
#endif

26
bench/graspels/decl.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef ROSA_BENCH_GRASPELS_DECL_H
#define ROSA_BENCH_GRASPELS_DECL_H
#include "common.h"
tsp::Solution none(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution hwElsGen(tsp::Solution const&, RNG&, Arguments const&);
tsp::Solution hw_seq(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution hw_par(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution hw_seq_v(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution hw_par_v(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution sk_nr_seq(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution sk_nr_par(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution sk_seq(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution sk_par_firstlevel(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution sk_par_staticpool(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution sk_par_dynamicpool(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution sk_par_thread(tsp::Problem const&, RNG&, Arguments const&);
tsp::Solution tbb_par(tsp::Problem const&, RNG&, Arguments const&);
#endif

220
bench/graspels/hw.cpp Normal file
View File

@ -0,0 +1,220 @@
#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);
}

188
bench/graspels/hwv.cpp Normal file
View File

@ -0,0 +1,188 @@
#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);
}

49
bench/graspels/main.cpp Normal file
View File

@ -0,0 +1,49 @@
#include <getopt.h>
#include <sstream>
#include "common.h"
#include "decl.h"
Arguments cli(int argc, char **argv) {
int option_index, option;
struct option long_options[] = {
{"seed", required_argument, 0, 's' },
{0, 0, 0, 0 }
};
Arguments args;
args.seed = SEED;
optind = 0;
while((option = getopt_long(argc, argv,
"" "" "" "s:",
long_options, &option_index)) != -1) {
switch(option) {
case 's': {
std::istringstream iss{optarg};
iss >> args.seed;
} break;
default:;
}
}
return args;
}
int main(int argc, char **argv) {
Arguments args = cli(argc, argv);
tsp::Tsp tspData{DATA_FILE};
tsp::Problem problem{tspData.points()};
RNG rng{args.seed};
std::printf("conf: f: %s, data: %s, grasp: %s, outer: %s, inner: %s, threads: %s, seed: %zu\n",
STR(FUNC), STR(DATA_FILE), STR(GRASP_N), STR(ELS_ITER_MAX), STR(ELS_GEN), STR(NTHREADS), args.seed);
tsp::Solution s;
auto task = [&]{ s = FUNC(problem, rng, args); };
timeit(RUSAGE_SELF, "", task);
std::cout << "result: " << s.value() << std::endl;
}

18
bench/graspels/none.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "common.h"
tsp::Solution none(tsp::Problem const&, RNG&, Arguments const&) {
std::cout << 1+R"(
Options:
- DATA_FILE
- GRASP_N
- ELS_ITER_MAX
- ELS_GEN
- FUNC (mandatory)
Example:
- g++ -Wall -Wextra -O2 -Isrc -Iinc -pthread src/tsp/*.cpp -DFUNC=sk_par2 -DNTHREADS=4 bench/graspels/*.cpp
)";
return {};
}

37
bench/graspels/nrsk.cpp Normal file
View File

@ -0,0 +1,37 @@
#include "bad_graspels.h"
#include "common.h"
using NRELS = rosa::SkelNREls<
tsp::Solution, RNG,
Descent,
Move2Opt, Descent, FN(selectMin)
>;
using NRGRASPxELS = rosa::SkelNRGrasp<
tsp::Problem, tsp::Solution, RNG,
RGreedy<tsp::Solution>, NRELS,
FN(selectMin)
>;
tsp::Solution sk_nr_seq(tsp::Problem const& p, RNG& rng, Arguments const&) {
auto graspEls = alsk::implement<alsk::exec::Sequential, NRGRASPxELS>();
graspEls.executor.repeatability.disabled();
graspEls.skeleton.task.task<0>() = rgreedy();
graspEls.skeleton.task.task<1>().task<1>().n = ELS_ITER_MAX;
graspEls.skeleton.task.task<1>().task<1>().task.n = ELS_GEN;
graspEls.skeleton.n = GRASP_N;
return graspEls(p, rng);
}
tsp::Solution sk_nr_par(tsp::Problem const& p, RNG& rng, Arguments const&) {
auto graspEls = alsk::implement<alsk::exec::FirstLevelNoOpti, NRGRASPxELS>();
graspEls.executor.cores = NTHREADS;
graspEls.executor.repeatability.disabled();
graspEls.skeleton.task.task<0>() = rgreedy();
graspEls.skeleton.task.task<1>().task<1>().n = ELS_ITER_MAX;
graspEls.skeleton.task.task<1>().task<1>().task.n = ELS_GEN;
graspEls.skeleton.n = GRASP_N;
return graspEls(p, rng);
}

74
bench/graspels/sk.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "common.h"
using ELS = rosa::SkelEls<
tsp::Solution,
Descent,
Move2Opt, Descent, FN(selectMin)
>;
using GRASPxELS = rosa::SkelGrasp<
tsp::Problem, tsp::Solution,
RGreedy<tsp::Solution>, ELS,
FN(selectMin)
>;
tsp::Solution sk_seq(tsp::Problem const& p, RNG&, Arguments const& args) {
auto graspEls = alsk::implement<alsk::exec::Sequential, GRASPxELS>();
graspEls.executor.repeatability.upTo(4);
graspEls.state.context.seed = args.seed;
graspEls.executor.cores = 1;
graspEls.skeleton.task.task<0>() = rgreedy();
graspEls.skeleton.task.task<1>().task<1>().n = ELS_ITER_MAX;
graspEls.skeleton.task.task<1>().task<1>().task.n = ELS_GEN;
graspEls.skeleton.n = GRASP_N;
return graspEls(p);
}
tsp::Solution sk_par_firstlevel(tsp::Problem const& p, RNG&, Arguments const& args) {
auto graspEls = alsk::implement<alsk::exec::FirstLevelEqui, GRASPxELS>();
graspEls.executor.repeatability.upTo(4);
graspEls.state.context.seed = args.seed;
graspEls.executor.cores = NTHREADS;
graspEls.skeleton.task.task<0>() = rgreedy();
graspEls.skeleton.task.task<1>().task<1>().n = ELS_ITER_MAX;
graspEls.skeleton.task.task<1>().task<1>().task.n = ELS_GEN;
graspEls.skeleton.n = GRASP_N;
return graspEls(p);
}
tsp::Solution sk_par_staticpool(tsp::Problem const& p, RNG&, Arguments const& args) {
auto graspEls = alsk::implement<alsk::exec::StaticPool, GRASPxELS>();
graspEls.state.context.seed = args.seed;
graspEls.executor.cores = NTHREADS;
graspEls.skeleton.task.task<0>() = rgreedy();
graspEls.skeleton.task.task<1>().task<1>().n = ELS_ITER_MAX;
graspEls.skeleton.task.task<1>().task<1>().task.n = ELS_GEN;
graspEls.skeleton.n = GRASP_N;
return graspEls(p);
}
tsp::Solution sk_par_dynamicpool(tsp::Problem const& p, RNG&, Arguments const& args) {
auto graspEls = alsk::implement<alsk::exec::DynamicPool, GRASPxELS>();
graspEls.state.context.seed = args.seed;
graspEls.executor.cores = NTHREADS;
graspEls.skeleton.task.task<0>() = rgreedy();
graspEls.skeleton.task.task<1>().task<1>().n = ELS_ITER_MAX;
graspEls.skeleton.task.task<1>().task<1>().task.n = ELS_GEN;
graspEls.skeleton.n = GRASP_N;
return graspEls(p);
}
tsp::Solution sk_par_thread(tsp::Problem const& p, RNG&, Arguments const&) {
auto graspEls = alsk::implement<alsk::exec::StaticThread, GRASPxELS>();
graspEls.executor.cores = NTHREADS;
graspEls.skeleton.task.task<0>() = rgreedy();
graspEls.skeleton.task.task<1>().task<1>().n = ELS_ITER_MAX;
graspEls.skeleton.task.task<1>().task<1>().task.n = ELS_GEN;
graspEls.skeleton.n = GRASP_N;
return graspEls(p);
}

111
bench/graspels/tbb.cpp Normal file
View File

@ -0,0 +1,111 @@
#ifdef WITH_TBB
#include <tbb/task_scheduler_init.h>
#include <tbb/flow_graph.h>
#include "common.h"
#include "decl.h"
/* *** */
/* TBB */
auto tbbElsInner(tsp::Solution const& solution, RNG& rng, std::size_t nCore) {
tsp::Solution best;
std::vector<tsp::Solution> solutions(ELS_GEN);
/* repeatability at loop level */
std::vector<RNG> rngs(ELS_GEN);
for(std::size_t i = 0; i < ELS_GEN; ++i)
rngs[i].seed(rng());
/* ***** */
using ElsGenP = std::tuple<tsp::Solution const*, RNG*, tsp::Solution*>;
using ElsGenR = std::tuple<tsp::Solution, tsp::Solution*>;
tbb::flow::graph g;
tbb::flow::function_node<ElsGenP, ElsGenR> fElsGen(g, nCore,
[](ElsGenP t) { return std::make_tuple(hwElsGen(*std::get<0>(t), *std::get<1>(t)), std::get<2>(t)); }
);
tbb::flow::function_node<ElsGenR, bool> fSelectMin(g, nCore,
[](ElsGenR t) { *std::get<1>(t) = (selectMin(std::get<0>(t), *std::get<1>(t))); return true; }
);
tbb::flow::make_edge(fElsGen, fSelectMin);
if(ELS_GEN)
solutions[0] = hwElsGen(solution, rngs[0]);
for(std::size_t i = 1; i < ELS_GEN; ++i)
fElsGen.try_put(std::make_tuple(&solution, &rngs[i], &solutions[i]));
g.wait_for_all();
best = *std::min_element(std::begin(solutions), std::end(solutions));
return best;
}
auto tbbEls(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 = tbbElsInner(best, rng, nCore);
best = selectMin(std::move(best), std::move(current));
}
return best;
}
auto tbbGraspGen(tsp::Problem const& problem, RNG& rng, std::size_t nCore) {
return tbbEls(rgreedy()(problem, rng), rng, nCore);
}
template<std::size_t K>
tsp::Solution tbbGraspElsPar(tsp::Problem const& problem, RNG& rng) {
tsp::Solution best;
std::vector<tsp::Solution> solutions(GRASP_N);
tbb::task_scheduler_init init(K);
/* repeatability at loop level */
std::vector<RNG> rngs(GRASP_N);
for(std::size_t i = 0; i < GRASP_N; ++i)
rngs[i].seed(rng());
/* ***** */
using GraspGenP = std::tuple<tsp::Problem const*, RNG*, unsigned long, tsp::Solution*>;
using GraspGenR = std::tuple<tsp::Solution, tsp::Solution*>;
tbb::flow::graph g;
tbb::flow::function_node<GraspGenP, GraspGenR> fGraspGen(g, K,
[](GraspGenP t) { return std::make_tuple(tbbGraspGen(*std::get<0>(t), *std::get<1>(t), std::get<2>(t)), std::get<3>(t)); }
);
tbb::flow::function_node<GraspGenR, bool> fSelectMin(g, K,
[](GraspGenR t) { *std::get<1>(t) = (selectMin(std::get<0>(t), *std::get<1>(t))); return true; }
);
tbb::flow::make_edge(fGraspGen, fSelectMin);
for(std::size_t i = 0; i < GRASP_N; ++i)
fGraspGen.try_put(std::make_tuple(&problem, &rngs[i], K, &solutions[i]));
g.wait_for_all();
/* Selection */
best = *std::min_element(std::begin(solutions), std::end(solutions));
return best;
}
tsp::Solution tbb_par(tsp::Problem const& p, RNG& rng, Arguments const&) {
return tbbGraspElsPar<NTHREADS>(p, rng);
}
#else
#include "common.h"
tsp::Solution tbb_par(tsp::Problem const&, RNG&, Arguments const&) {
std::clog << "must compile with -ltbb -DWITH_TBB to enable TBB\n";
return {};
}
#endif