rosa/inc/alsk/executor/impl/staticpoolid.h
2021-05-10 18:14:24 +02:00

111 lines
3.1 KiB
C++

#ifndef ALSK_ALSK_EXECUTOR_IMPL_STATICPOOLID_H
#define ALSK_ALSK_EXECUTOR_IMPL_STATICPOOLID_H
#include <algorithm>
#include <cmath>
#include <future>
#include <list>
#include <set>
#include <vector>
#include "../executorbase.h"
#include "../executorstate.h"
#include "../../skeleton/traits.h"
#include "../utility/staticpool.h"
namespace alsk {
namespace exec {
template<typename S>
struct StaticPoolId: ExecutorBase {
using Tag = alsk::tag::Parallel;
private:
template<typename Impl>
void buildSplit(Impl& impl) {
typename Impl::State& state = impl.state;
auto& split = state.executor.split;
split.clear();
split.insert(0);
auto const n = static_cast<double>(state.executor.upperId);
for(auto cores: repeatability.coresList)
for(std::size_t i = 1; i < cores; ++i)
split.insert(std::ceil(n/cores * i));
}
public:
template<typename Impl>
void config(Impl& impl) {
typename Impl::State& state = impl.state;
state.executor.config(cores);
state.executor.upperId = impl.parallelTasksCount();
buildSplit(impl);
}
template<typename Impl>
std::size_t contextIdCount(Impl& impl, std::size_t) {
typename Impl::State& state = impl.state;
return state.executor.split.size();
}
template<typename Impl>
std::size_t contextId(Impl& impl, std::size_t id) { // O(log(n))
typename Impl::State& state = impl.state;
auto& split = state.executor.split;
return std::distance(std::begin(split), split.upper_bound(id)) - 1;
}
template<typename Task, typename Impl, typename BTask, typename Parameters>
void executeParallel(Impl& impl, BTask& task, Parameters const& parameters, std::size_t n) {
std::list<std::future<void>> futures;
typename Impl::State& state = impl.state;
for(std::size_t i = 0; i < n; ++i) {
std::size_t thNum = cores * (impl.id + impl.skeleton.step * i) / state.executor.upperId;
auto thTask = [&, i]{ Task::execute(impl, task, i, Info{}, parameters, std::tuple<>{}); };
futures.emplace_back(state.executor.run(thNum, std::move(thTask)));
}
state.executor.wait(futures);
}
template<typename Value, typename Task, typename Select, typename Impl, typename BTask, typename BSelect, typename Parameters>
Value executeParallelAccumulate(Impl& impl, BTask& task, BSelect& select, Parameters const& parameters, std::size_t n) {
Value best{};
std::vector<Value> bests(n);
std::list<std::future<void>> futures;
typename Impl::State& state = impl.state;
for(std::size_t i = 0; i < n; ++i) {
std::size_t thNum = cores * (impl.id + impl.skeleton.step * i) / state.executor.upperId;
auto thTask = [&, &best = bests[i], i]{ best = Task::execute(impl, task, i, Info{}, parameters, std::tuple<>{}); };
futures.emplace_back(state.executor.run(thNum, std::move(thTask)));
}
state.executor.wait(futures);
if(n) best = std::move(bests[0]);
for(std::size_t i = 1; i < n; ++i)
best = Select::execute(impl, select, i, impl.executorInfo, parameters, std::tuple<>{}, std::move(bests[i]), std::move(best));
return best;
}
};
template<typename S>
struct ExecutorState<StaticPoolId<S>>: util::StaticPool {
std::size_t upperId;
std::set<std::size_t> split;
};
}
}
#endif