27 #include "benchmark/benchmark.h" 33 template <std::
size_t I>
34 struct VariantAlternative {
38 template <
class Indices>
39 struct VariantOfAlternativesImpl;
41 template <std::size_t... Indices>
46 template <std::
size_t NumAlternatives>
47 using VariantOfAlternatives =
typename VariantOfAlternativesImpl<
53 void Ignore(T...) noexcept {}
56 Empty DoNotOptimizeAndReturnEmpty(T&&
arg) noexcept {
57 benchmark::DoNotOptimize(
arg);
61 struct VisitorApplier {
64 void operator()(T&&... args)
const noexcept {
65 Ignore(DoNotOptimizeAndReturnEmpty(args)...);
69 template <
class... Vars>
70 void operator()(
const Vars&... vars)
const noexcept {
75 template <std::size_t NumIndices, std::size_t CurrIndex = NumIndices - 1>
76 struct MakeWithIndex {
77 using Variant = VariantOfAlternatives<NumIndices>;
79 static Variant Run(std::size_t index) {
80 return index == CurrIndex
82 : MakeWithIndex<NumIndices, CurrIndex - 1>::Run(index);
86 template <std::
size_t NumIndices>
87 struct MakeWithIndex<NumIndices, 0> {
88 using Variant = VariantOfAlternatives<NumIndices>;
90 static Variant Run(std::size_t ) {
return Variant(); }
93 template <std::
size_t NumIndices,
class Dimensions>
94 struct MakeVariantTuple;
96 template <
class T, std::size_t >
99 template <std::
size_t NumIndices>
100 VariantOfAlternatives<NumIndices> MakeVariant(std::size_t dimension,
102 return dimension == 0
103 ? MakeWithIndex<NumIndices>::Run(index % NumIndices)
104 : MakeVariant<NumIndices>(dimension - 1, index / NumIndices);
107 template <std::size_t NumIndices, std::size_t... Dimensions>
110 std::tuple<always_t<VariantOfAlternatives<NumIndices>, Dimensions>...>;
112 static VariantTuple Run(
int index) {
113 return std::make_tuple(MakeVariant<NumIndices>(Dimensions, index)...);
117 constexpr std::size_t integral_pow(std::size_t base, std::size_t
power) {
118 return power == 0 ? 1 : base * integral_pow(base, power - 1);
121 template <std::
size_t End, std::
size_t I = 0>
122 struct VisitTestBody {
123 template <
class Vars,
class State>
124 static bool Run(Vars& vars, State& state) {
125 if (state.KeepRunning()) {
127 return VisitTestBody<End, I + 1>::Run(vars, state);
133 template <std::
size_t End>
134 struct VisitTestBody<End, End> {
135 template <
class Vars,
class State>
136 static bool Run(Vars& , State& ) {
142 template <std::
size_t NumIndices, std::
size_t NumDimensions = 1>
143 void BM_RedundantVisit(benchmark::State& state) {
145 MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>::
146 Run(static_cast<std::size_t>(state.range(0)));
148 for (
auto _ : state) {
149 benchmark::DoNotOptimize(vars);
155 template <std::
size_t NumIndices, std::
size_t NumDimensions = 1>
156 void BM_Visit(benchmark::State& state) {
157 constexpr std::size_t num_possibilities =
158 integral_pow(NumIndices, NumDimensions);
160 using VariantTupleMaker =
161 MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>;
162 using Tuple =
typename VariantTupleMaker::VariantTuple;
164 Tuple vars[num_possibilities];
165 for (std::size_t
i = 0;
i < num_possibilities; ++
i)
166 vars[
i] = VariantTupleMaker::Run(
i);
168 while (VisitTestBody<num_possibilities>::Run(vars, state)) {
176 BENCHMARK_TEMPLATE(BM_Visit, 1);
177 BENCHMARK_TEMPLATE(BM_Visit, 2);
178 BENCHMARK_TEMPLATE(BM_Visit, 3);
179 BENCHMARK_TEMPLATE(BM_Visit, 4);
180 BENCHMARK_TEMPLATE(BM_Visit, 5);
181 BENCHMARK_TEMPLATE(BM_Visit, 6);
182 BENCHMARK_TEMPLATE(BM_Visit, 7);
183 BENCHMARK_TEMPLATE(BM_Visit, 8);
184 BENCHMARK_TEMPLATE(BM_Visit, 16);
185 BENCHMARK_TEMPLATE(BM_Visit, 32);
186 BENCHMARK_TEMPLATE(BM_Visit, 64);
189 BENCHMARK_TEMPLATE(BM_Visit, 1, 2);
190 BENCHMARK_TEMPLATE(BM_Visit, 2, 2);
191 BENCHMARK_TEMPLATE(BM_Visit, 3, 2);
192 BENCHMARK_TEMPLATE(BM_Visit, 4, 2);
193 BENCHMARK_TEMPLATE(BM_Visit, 5, 2);
196 BENCHMARK_TEMPLATE(BM_Visit, 1, 3);
197 BENCHMARK_TEMPLATE(BM_Visit, 2, 3);
198 BENCHMARK_TEMPLATE(BM_Visit, 3, 3);
201 BENCHMARK_TEMPLATE(BM_Visit, 1, 4);
202 BENCHMARK_TEMPLATE(BM_Visit, 2, 4);
208 BENCHMARK_TEMPLATE(BM_RedundantVisit, 1)->Arg(0);
209 BENCHMARK_TEMPLATE(BM_RedundantVisit, 2)->DenseRange(0, 1);
210 BENCHMARK_TEMPLATE(BM_RedundantVisit, 8)->DenseRange(0, 7);
213 BENCHMARK_TEMPLATE(BM_RedundantVisit, 1, 2)->Arg(0);
214 BENCHMARK_TEMPLATE(BM_RedundantVisit, 2, 2)
215 ->DenseRange(0, integral_pow(2, 2) - 1);
216 BENCHMARK_TEMPLATE(BM_RedundantVisit, 4, 2)
217 ->DenseRange(0, integral_pow(4, 2) - 1);
make_integer_sequence< size_t, N > make_index_sequence
integer_sequence< size_t, Ints... > index_sequence
auto apply(Functor &&functor, Tuple &&t) -> decltype(utility_internal::apply_helper(absl::forward< Functor >(functor), absl::forward< Tuple >(t), absl::make_index_sequence< std::tuple_size< typename std::remove_reference< Tuple >::type >::value >
variant_internal::VisitResult< Visitor, Variants... > visit(Visitor &&vis, Variants &&... vars)
void(*)(utility_internal::InPlaceIndexTag< I >) in_place_index_t