-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbool_returned_prevents_vectorization.bench.cpp
125 lines (105 loc) · 2.82 KB
/
bool_returned_prevents_vectorization.bench.cpp
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <benchmark/benchmark.h>
#include <random>
#include <ctime>
#include <vector>
const std::size_t SIZE = 1 << 20;
const auto test_vec = []()
{
std::vector<int> vec;
vec.reserve(SIZE);
std::srand(std::time(0));
for(std::size_t i = 0; i < SIZE; ++i)
{
vec.push_back(std::rand());
}
return vec;
}();
template<typename _Predicate>
struct _Iter_pred_auto
{
_Predicate _M_pred;
_GLIBCXX20_CONSTEXPR
explicit _Iter_pred_auto(_Predicate __pred)
: _M_pred(_GLIBCXX_MOVE(__pred))
{
}
// RETURNS THE ORIGINAL TYPE OF THE LAMBDA
template<typename _Iterator>
_GLIBCXX20_CONSTEXPR auto operator()(_Iterator __it) const
{
return _M_pred(*__it);
}
};
template<typename _Predicate>
struct _Iter_pred_bool
{
_Predicate _M_pred;
_GLIBCXX20_CONSTEXPR
explicit _Iter_pred_bool(_Predicate __pred)
: _M_pred(_GLIBCXX_MOVE(__pred))
{
}
// IGNORES THE ORIGINAL TYPE RETURNED BY THE LAMBDA
template<typename _Iterator>
_GLIBCXX20_CONSTEXPR bool operator()(_Iterator __it) const
{
return bool(_M_pred(*__it));
}
};
const auto is_even_int = [](const int el) -> int
{
return el % 2 == 0;
};
template<typename It>
auto mcount_if(It first, const It last, const auto pred)
{
typename std::iterator_traits<It>::difference_type result = 0;
for(; first != last; ++first)
{
if(pred(first))
{
++result;
}
}
return result;
}
auto version1(const std::vector<int>& vec)
{
return mcount_if(vec.begin(), vec.end(), _Iter_pred_bool{is_even_int});
}
auto version2(const std::vector<int>& vec)
{
return mcount_if(vec.begin(), vec.end(), _Iter_pred_auto{is_even_int});
}
auto version3(const std::vector<int>& vec)
{
return std::count_if(vec.begin(), vec.end(), is_even_int);
}
static void v_return_bool(benchmark::State& state)
{
for(auto _ : state)
{
const auto tmp = version1(test_vec);
benchmark::DoNotOptimize(tmp);
}
}
static void v_return_auto(benchmark::State& state)
{
for(auto _ : state)
{
const auto tmp = version2(test_vec);
benchmark::DoNotOptimize(tmp);
}
}
static void std_count_if(benchmark::State& state)
{
for(auto _ : state)
{
const auto tmp = version3(test_vec);
benchmark::DoNotOptimize(tmp);
}
}
BENCHMARK(v_return_bool)->Unit(benchmark::kMicrosecond);
BENCHMARK(v_return_auto)->Unit(benchmark::kMicrosecond);
BENCHMARK(std_count_if)->Unit(benchmark::kMicrosecond);
BENCHMARK_MAIN();