1+ #include < algorithm>
2+ #include < execution>
3+ #include < vector>
4+
5+ #include < benchmark/benchmark.h>
6+
7+ #include " xsimd_algorithm/stl/max_element.hpp"
8+ #include " xsimd_algorithm/stl/min_element.hpp"
9+
10+ #define BENCH_ARGS ->Arg (kSmall )->Arg(kMedium )->Arg(kLarge )
11+
12+ namespace
13+ {
14+ template <class ForwardIterator >
15+ typename std::iterator_traits<ForwardIterator>::value_type dummy_std_max_value (ForwardIterator first, ForwardIterator last) noexcept
16+ {
17+ auto candidate = std::numeric_limits<typename std::iterator_traits<ForwardIterator>::value_type>::lowest ();
18+ for (; first != last; ++first)
19+ {
20+ if (candidate < *first)
21+ {
22+ candidate = *first;
23+ }
24+ }
25+ return candidate;
26+ }
27+
28+ template <typename T>
29+ std::vector<T> make_input (std::size_t n, T constant)
30+ {
31+ std::vector<T> v (n);
32+ std::fill (v.begin (), v.end (), constant);
33+ return v;
34+ }
35+
36+ template <typename T>
37+ void BM_std_max_element (benchmark::State& state)
38+ {
39+ const auto constant = T { 5 };
40+ auto src = make_input<T>(static_cast <std::size_t >(state.range (0 )), constant);
41+ src[state.range (0 )-1 ] = T { 10 }; // Ensure there is a maximum value at the end
42+
43+ for (auto _ : state)
44+ {
45+ auto result = std::max_element (src.begin (), src.end ());
46+ benchmark::DoNotOptimize (result);
47+ benchmark::ClobberMemory ();
48+ }
49+ state.SetItemsProcessed (state.iterations () * state.range (0 ));
50+ }
51+
52+ template <typename T>
53+ void BM_xsimd_max_element (benchmark::State& state)
54+ {
55+ const auto constant = T { 5 };
56+ auto src = make_input<T>(static_cast <std::size_t >(state.range (0 )), constant);
57+ src[state.range (0 )-1 ] = T { 10 }; // Ensure there is a maximum value at the end
58+ for (auto _ : state)
59+ {
60+ auto result = xsimd::max_element (src.begin (), src.end ());
61+ benchmark::DoNotOptimize (result);
62+ benchmark::ClobberMemory ();
63+ }
64+ state.SetItemsProcessed (state.iterations () * state.range (0 ));
65+ }
66+
67+ template <typename T>
68+ void BM_std_min_element (benchmark::State& state)
69+ {
70+ const auto constant = T { 5 };
71+ auto src = make_input<T>(static_cast <std::size_t >(state.range (0 )), constant);
72+ src[state.range (0 )-1 ] = T { 10 }; // Ensure there is a maximum value at the end
73+
74+ for (auto _ : state)
75+ {
76+ auto result = std::min_element (src.begin (), src.end ());
77+ benchmark::DoNotOptimize (result);
78+ benchmark::ClobberMemory ();
79+ }
80+ state.SetItemsProcessed (state.iterations () * state.range (0 ));
81+ }
82+
83+ template <typename T>
84+ void BM_xsimd_min_element (benchmark::State& state)
85+ {
86+ const auto constant = T { 5 };
87+ auto src = make_input<T>(static_cast <std::size_t >(state.range (0 )), constant);
88+ src[state.range (0 )-1 ] = T { 10 }; // Ensure there is a maximum value at the end
89+ for (auto _ : state)
90+ {
91+ auto result = xsimd::min_element (src.begin (), src.end ());
92+ benchmark::DoNotOptimize (result);
93+ benchmark::ClobberMemory ();
94+ }
95+ state.SetItemsProcessed (state.iterations () * state.range (0 ));
96+ }
97+
98+ static constexpr long long kSmall = 1LL << 12 ;
99+ static constexpr long long kMedium = 1LL << 18 ;
100+ static constexpr long long kLarge = 1LL << 22 ;
101+
102+ // max_element
103+ BENCHMARK_TEMPLATE (BM_std_max_element, float )
104+ BENCH_ARGS ;
105+ BENCHMARK_TEMPLATE (BM_xsimd_max_element, float )
106+ BENCH_ARGS ;
107+
108+ // min_element
109+ BENCHMARK_TEMPLATE (BM_std_min_element, float )
110+ BENCH_ARGS ;
111+ BENCHMARK_TEMPLATE (BM_xsimd_min_element, float )
112+ BENCH_ARGS ;
113+
114+ }
0 commit comments