rosa/bench/graspels/tbb.cpp
2021-05-10 18:14:24 +02:00

112 lines
3.1 KiB
C++

#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