This repository was archived by the owner on Jun 8, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathschedulers.hpp
84 lines (69 loc) · 3.26 KB
/
schedulers.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//
// Created by Hippolyte Barraud on 10/03/2018.
//
#ifndef MEM_BANDWIDTH_SCHEDULERS_HPP
#define MEM_BANDWIDTH_SCHEDULERS_HPP
#include <memory>
#include <chrono>
#include <numeric>
#include <algorithm>
#include <future>
#include <vector>
#include <iostream>
#include <random>
#include "threadpool.hpp"
#define CONCURENCY std::thread::hardware_concurrency()
struct serial_scheduler {
static constexpr auto name = "Single threaded serial scheduler";
struct allocator {
template<typename Vec>
static auto alloc() {
return std::make_unique<std::tuple<Vec, Vec, Vec>>();
}
};
template<typename TNum, typename Vec, template<class, class> typename Kernel, typename Arg = decltype(allocator::template alloc<Vec>())>
static inline auto schedule(Arg &arg) {
auto start = std::chrono::high_resolution_clock::now();
Kernel<Vec, TNum>::run(std::get<0>(*arg), std::get<1>(*arg), std::get<2>(*arg));
return std::chrono::high_resolution_clock::now() - start;
}
template<class TNum, size_t ElementCount, template<class, class> typename Kernel, typename Vec>
static double result(int64_t delta) {
return static_cast<double>((ElementCount) * Kernel<Vec, TNum>::bytes_per_iter) / delta;
}
};
struct parallel_scheduler {
static constexpr auto name = "Multi threaded parallel scheduler";
static std::unique_ptr<thread_pool> pool;
struct allocator {
template<typename Vec>
static auto alloc() {
std::vector<std::unique_ptr<std::tuple<Vec, Vec, Vec>>> ret(CONCURENCY);
std::generate(ret.begin(), ret.end(), []() { return std::make_unique<std::tuple<Vec, Vec, Vec>>(); });
return ret;
}
};
template<typename TNum, typename Vec, template<class, class> typename Kernel, typename Arg = decltype(allocator::template alloc<Vec>())>
static inline auto schedule(Arg &arg) {
std::vector<std::future<std::chrono::nanoseconds>> res(CONCURENCY);
std::vector<std::chrono::nanoseconds> resval(CONCURENCY);
std::transform(arg.begin(), arg.end(), res.begin(), [] (auto &ptr) {
return pool->submit([ &ptr]() { return serial_scheduler::template schedule<TNum, Vec, Kernel>(ptr); });
});
std::transform(res.begin(), res.end(), resval.begin(), [](auto &future) { return future.get(); });
return *std::max_element(resval.begin(), resval.end());
}
template<class TNum, size_t ElementCount, template<class, class> typename Kernel, typename Vec>
static double result(int64_t delta) {
return static_cast<double>((ElementCount * CONCURENCY) * Kernel<Vec, TNum>::bytes_per_iter) / delta;
}
};
std::unique_ptr<thread_pool> parallel_scheduler::pool = std::make_unique<thread_pool>(CONCURENCY);
template<typename Scheduler, class TNum, size_t Size, template<class, class> typename Kernel, size_t ElementCount = Size / sizeof(TNum) / 3,
typename Vec = typename std::array<TNum, ElementCount>>
double time_execution() {
static thread_local auto arg = Scheduler::allocator::template alloc<Vec>();
auto delta = Scheduler::template schedule<TNum, Vec, Kernel>(arg);
return Scheduler::template result<TNum, ElementCount, Kernel, Vec>(delta.count());
}
#endif //MEM_BANDWIDTH_SCHEDULERS_HPP