112 lines
3.1 KiB
C++
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
|