benchmark_tuple_vector.cpp
Go to the documentation of this file.
1 // Copyright 2022-2024 Ekumen, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <benchmark/benchmark.h>
16 
17 #include <cstddef>
18 #include <tuple>
19 #include <vector>
20 
21 #include <range/v3/algorithm/transform.hpp>
22 #include <range/v3/iterator/insert_iterators.hpp>
23 #include <range/v3/range/access.hpp>
24 #include <range/v3/view/filter.hpp>
25 #include <range/v3/view/transform.hpp>
26 
28 #include "beluga/primitives.hpp"
30 
31 namespace {
32 
33 constexpr std::size_t kParticleCount = 1'000'000;
34 
35 struct State {
36  double x = 0.;
37  double y = 0.;
38  double theta = 0.;
39 };
40 
41 using Particle = std::tuple<State, beluga::Weight, beluga::Cluster>;
44 
45 struct Arrays {
46  std::vector<State> states;
47  std::vector<double> weights;
48  std::vector<std::size_t> clusters;
49 
50  [[nodiscard]] std::size_t size() const noexcept { return states.size(); }
51 
52  void clear() noexcept {
53  states.clear();
54  weights.clear();
55  clusters.clear();
56  }
57 
58  void reserve(std::size_t new_cap) {
59  states.reserve(new_cap);
60  weights.reserve(new_cap);
61  clusters.reserve(new_cap);
62  }
63 
64  void resize(std::size_t count) {
65  states.resize(count);
66  weights.resize(count);
67  clusters.resize(count);
68  }
69 };
70 
71 double update_weight(const State& state) {
72  return state.x * state.y * state.theta;
73 }
74 
75 void BM_Update_Baseline_StructureOfArrays(benchmark::State& state) {
76  Arrays arrays;
77  arrays.resize(kParticleCount);
78  for (auto _ : state) {
79  for (std::size_t i = 0; i < kParticleCount; ++i) {
80  arrays.weights[i] = update_weight(arrays.states[i]);
81  }
82  }
83 }
84 
85 void BM_Update_Baseline_ArrayOfStructures(benchmark::State& state) {
86  std::vector<Particle> particles;
87  particles.resize(kParticleCount);
88  for (auto _ : state) {
89  for (std::size_t i = 0; i < kParticleCount; ++i) {
90  auto&& particle = particles[i];
91  std::get<1>(particle) = update_weight(std::get<0>(particle));
92  }
93  }
94 }
95 
96 template <class Container>
97 void BM_Update(benchmark::State& state) {
98  auto container = Container{};
99  container.resize(kParticleCount);
100  for (auto _ : state) {
101  auto weights = beluga::views::weights(container);
102  ranges::transform(beluga::views::states(container), ranges::begin(weights), update_weight);
103  }
104 }
105 
106 BENCHMARK(BM_Update_Baseline_StructureOfArrays);
107 BENCHMARK_TEMPLATE(BM_Update, StructureOfArrays);
108 BENCHMARK(BM_Update_Baseline_ArrayOfStructures);
109 BENCHMARK_TEMPLATE(BM_Update, ArrayOfStructures);
110 
111 void BM_PushBack_Baseline_StructureOfArrays(benchmark::State& state) {
112  Arrays arrays;
113  arrays.resize(kParticleCount);
114  Arrays new_arrays;
115  new_arrays.reserve(kParticleCount);
116  for (auto _ : state) {
117  new_arrays.clear();
118  for (std::size_t i = 0; i < kParticleCount; ++i) {
119  new_arrays.states.push_back(State{});
120  new_arrays.weights.push_back(0);
121  new_arrays.clusters.push_back(0);
122  }
123  }
124 }
125 
126 void BM_PushBack_Baseline_ArrayOfStructures(benchmark::State& state) {
127  std::vector<Particle> particles;
128  particles.resize(kParticleCount);
129  std::vector<Particle> new_particles;
130  new_particles.reserve(kParticleCount);
131  for (auto _ : state) {
132  new_particles.clear();
133  for (std::size_t i = 0; i < kParticleCount; ++i) {
134  new_particles.emplace_back(std::get<0>(particles[i]), 0, 0);
135  }
136  }
137 }
138 
139 template <class Container>
140 void BM_PushBack(benchmark::State& state) {
141  auto container = Container{};
142  container.resize(kParticleCount);
143  auto new_container = Container{};
144  new_container.reserve(kParticleCount);
145  for (auto _ : state) {
146  new_container.clear();
147  ranges::transform(beluga::views::states(container), ranges::back_inserter(new_container), [](const State& state) {
148  return std::make_tuple(state, 0, 0);
149  });
150  }
151 }
152 
153 BENCHMARK(BM_PushBack_Baseline_StructureOfArrays);
154 BENCHMARK_TEMPLATE(BM_PushBack, StructureOfArrays);
155 BENCHMARK(BM_PushBack_Baseline_ArrayOfStructures);
156 BENCHMARK_TEMPLATE(BM_PushBack, ArrayOfStructures);
157 
158 void BM_Assign_Baseline_ArrayOfStructures(benchmark::State& state) {
159  std::vector<Particle> particles;
160  particles.resize(kParticleCount);
161  std::vector<Particle> new_particles;
162  new_particles.resize(kParticleCount);
163  for (auto _ : state) {
164  for (std::size_t i = 0; i < kParticleCount; ++i) {
165  new_particles[i] = Particle{std::get<0>(particles[i]), 0, 0};
166  }
167  }
168 }
169 
170 void BM_Assign_Baseline_StructureOfArrays(benchmark::State& state) {
171  Arrays arrays;
172  arrays.resize(kParticleCount);
173  Arrays new_arrays;
174  new_arrays.resize(kParticleCount);
175  for (auto _ : state) {
176  for (std::size_t i = 0; i < kParticleCount; ++i) {
177  new_arrays.states[i] = arrays.states[i];
178  new_arrays.weights[i] = 0;
179  new_arrays.clusters[i] = 0;
180  }
181  }
182 }
183 
184 template <class Container>
185 void BM_Transform(benchmark::State& state) {
186  auto container = Container{};
187  container.resize(kParticleCount);
188  auto new_container = Container{};
189  new_container.resize(kParticleCount);
190  for (auto _ : state) {
191  ranges::transform(beluga::views::states(container), ranges::begin(new_container), [](const State& state) {
192  return std::make_tuple(state, 0, 0);
193  });
194  }
195 }
196 
197 template <class Container>
198 void BM_AssignFromSized(benchmark::State& state) {
199  auto container = Container{};
200  container.resize(kParticleCount);
201  auto new_container = Container{};
202  for (auto _ : state) {
203  new_container.assign_range(
204  beluga::views::states(container) | //
205  ranges::views::transform([](const State& state) { return std::make_tuple(state, 0, 0); }));
206  }
207 }
208 
209 template <class Container>
210 void BM_AssignFromNonSized(benchmark::State& state) {
211  auto container = Container{};
212  container.resize(kParticleCount);
213  auto new_container = Container{};
214  for (auto _ : state) {
215  new_container.assign_range(
216  beluga::views::states(container) | //
217  ranges::views::filter([](auto) { return true; }) | //
218  ranges::views::transform([](const State& state) { return std::make_tuple(state, 0, 0); }));
219  }
220 }
221 
222 template <class Container>
223 void BM_AssignFromNonSizedReserved(benchmark::State& state) {
224  auto container = Container{};
225  container.resize(kParticleCount);
226  auto new_container = Container{};
227  new_container.reserve(kParticleCount);
228  for (auto _ : state) {
229  new_container.assign_range(
230  beluga::views::states(container) | //
231  ranges::views::filter([](auto) { return true; }) | //
232  ranges::views::transform([](const State& state) { return std::make_tuple(state, 0, 0); }));
233  }
234 }
235 
236 BENCHMARK(BM_Assign_Baseline_StructureOfArrays);
237 BENCHMARK_TEMPLATE(BM_AssignFromSized, StructureOfArrays);
238 BENCHMARK_TEMPLATE(BM_AssignFromNonSized, StructureOfArrays);
239 BENCHMARK_TEMPLATE(BM_AssignFromNonSizedReserved, StructureOfArrays);
240 BENCHMARK_TEMPLATE(BM_Transform, StructureOfArrays);
241 BENCHMARK(BM_Assign_Baseline_ArrayOfStructures);
242 BENCHMARK_TEMPLATE(BM_Transform, ArrayOfStructures);
243 
244 } // namespace
primitives.hpp
Implementation of library primitives to abstract member access.
beluga::state
constexpr state_detail::state_fn state
Customization point object for accessing the state of a particle.
Definition: primitives.hpp:163
tuple_vector.hpp
Implementation of a tuple of containers.
beluga::Vector
std::vector< T, std::allocator< T > > Vector
Shorthand for a vector with the default allocator.
Definition: tuple_vector.hpp:216
particles.hpp
Implementation of views related to particle ranges.
beluga::TupleVector
Shorthand for a tuple of vectors with the default allocator.
Definition: tuple_vector.hpp:223
beluga::views::weights
constexpr auto weights
Definition: particles.hpp:34
beluga::views::states
constexpr auto states
Definition: particles.hpp:30


beluga
Author(s):
autogenerated on Tue Jul 16 2024 02:59:53