-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathlibfork.cpp
More file actions
105 lines (75 loc) · 3.95 KB
/
libfork.cpp
File metadata and controls
105 lines (75 loc) · 3.95 KB
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <benchmark/benchmark.h>
#include "libfork_benchmark/common.hpp"
#include "libfork_benchmark/fib/fib.hpp"
import std;
import libfork;
// === Coroutine
namespace {
struct fib {
template <lf::worker_context Context>
static auto operator()(lf::env<Context>, std::int64_t n) -> lf::task<std::int64_t, Context> {
if (n < 2) {
co_return n;
}
std::int64_t lhs = 0;
std::int64_t rhs = 0;
auto sc = co_await lf::scope();
co_await sc.fork(&rhs, fib{}, n - 2);
co_await sc.call(&lhs, fib{}, n - 1);
co_await sc.join();
co_return lhs + rhs;
}
};
template <lf::scheduler Sch>
void run(benchmark::State &state) {
std::int64_t n = state.range(0);
std::int64_t expect = fib_ref(n);
state.counters["n"] = static_cast<double>(n);
state.counters["p"] = static_cast<double>(thread_count<Sch>(state));
state.SetComplexityN(static_cast<benchmark::IterationCount>(thread_count<Sch>(state)));
Sch scheduler = make_scheduler<Sch>(state);
for (auto _ : state) {
benchmark::DoNotOptimize(n);
lf::receiver recv = lf::schedule(scheduler, fib{}, n);
std::int64_t return_value = std::move(recv).get();
CHECK_RESULT(return_value, expect);
benchmark::DoNotOptimize(return_value);
}
}
} // namespace
#define BENCH_ONE(mode, ...) \
BENCHMARK_TEMPLATE(run, __VA_ARGS__) \
->Name(#mode "/libfork/fib/" #__VA_ARGS__) \
->Arg(fib_##mode) \
->UseRealTime();
#define BENCH_ALL(...) BENCH_ONE(test, __VA_ARGS__) BENCH_ONE(base, __VA_ARGS__)
template <typename Stack, template <typename> typename Adaptor>
using real_context = lf::mono_context<Stack, Adaptor>;
template <typename Stack, template <typename> typename Adaptor>
using poly_context = lf::derived_poly_context<Stack, Adaptor>;
using lf::adapt_deque;
using lf::adapt_vector;
using lf::inline_scheduler;
using lf::adaptor_stack;
using lf::geometric_stack;
BENCH_ALL(inline_scheduler<real_context<adaptor_stack<>, adapt_vector>>)
BENCH_ALL(inline_scheduler<poly_context<adaptor_stack<>, adapt_vector>>)
BENCH_ALL(inline_scheduler<real_context<geometric_stack<>, adapt_vector>>)
BENCH_ALL(inline_scheduler<poly_context<geometric_stack<>, adapt_vector>>)
BENCH_ALL(inline_scheduler<real_context<geometric_stack<>, adapt_deque>>)
BENCH_ALL(inline_scheduler<poly_context<geometric_stack<>, adapt_deque>>)
#define BENCH_ONE_MT(mode, ...) \
BENCHMARK_TEMPLATE(run, __VA_ARGS__) \
->Name(#mode "/libfork/fib/" #__VA_ARGS__) \
->Apply([](benchmark::Benchmark *b) -> void { \
bench_thread_args(b, [](benchmark::Benchmark *b, unsigned t) { \
b->Args({fib_##mode, static_cast<std::int64_t>(t)}); \
}); \
}) \
->Complexity([](benchmark::IterationCount n) -> double { \
return 1.0 / static_cast<double>(n); \
}) \
->UseRealTime();
#define BENCH_ALL_MT(...) BENCH_ONE_MT(test, __VA_ARGS__) BENCH_ONE_MT(base, __VA_ARGS__)
BENCH_ALL_MT(mono_busy_pool)
BENCH_ALL_MT(poly_busy_pool)