#ifndef ALSK_ALSK_EXECUTOR_IMPL_STATICPOOLID_H #define ALSK_ALSK_EXECUTOR_IMPL_STATICPOOLID_H #include #include #include #include #include #include #include "../executorbase.h" #include "../executorstate.h" #include "../../skeleton/traits.h" #include "../utility/staticpool.h" namespace alsk { namespace exec { template struct StaticPoolId: ExecutorBase { using Tag = alsk::tag::Parallel; private: template 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(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 void config(Impl& impl) { typename Impl::State& state = impl.state; state.executor.config(cores); state.executor.upperId = impl.parallelTasksCount(); buildSplit(impl); } template std::size_t contextIdCount(Impl& impl, std::size_t) { typename Impl::State& state = impl.state; return state.executor.split.size(); } template 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 void executeParallel(Impl& impl, BTask& task, Parameters const& parameters, std::size_t n) { std::list> 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 Value executeParallelAccumulate(Impl& impl, BTask& task, BSelect& select, Parameters const& parameters, std::size_t n) { Value best{}; std::vector bests(n); std::list> 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 struct ExecutorState>: util::StaticPool { std::size_t upperId; std::set split; }; } } #endif