Skip to content

Commit dc7e2b7

Browse files
committed
Drop ability to zip axii after construction
1 parent 5ebe7fe commit dc7e2b7

File tree

7 files changed

+63
-310
lines changed

7 files changed

+63
-310
lines changed

docs/benchmarks.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,8 @@ using input_types = nvbench::type_list<char, int, unsigned int>;
259259
using output_types = nvbench::type_list<float, double>;
260260
NVBENCH_BENCH_TYPES(benchmark, NVBENCH_TYPE_AXES(input_types, output_types))
261261
.set_type_axes_names({"InputType", "OutputType"})
262-
.add_int64_axis("NumInputs", {1000, 10000, 100000, 200000, 200000, 200000})
263-
.add_float64_axis("Quality", {0.05, 0.1, 0.25, 0.5, 0.75, 1.})
264-
.zip_axes({"NumInputs", "Quality"});
262+
.add_zip_axes(nvbench::int64_axis{"NumInputs", {1000, 10000, 100000, 200000, 200000, 200000}},
263+
nvbench::float64_axis{"Quality", {0.05, 0.1, 0.25, 0.5, 0.75, 1.}});
265264
```
266265
267266
Zipping these two axes reduces the total combinations from 216 to 36, reducing the

nvbench/axes_metadata.cuh

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818

1919
#pragma once
2020

21-
#include <nvbench/iteration_space_base.cuh>
2221
#include <nvbench/float64_axis.cuh>
2322
#include <nvbench/int64_axis.cuh>
23+
#include <nvbench/iteration_space_base.cuh>
2424
#include <nvbench/linear_axis_space.cuh>
2525
#include <nvbench/string_axis.cuh>
2626
#include <nvbench/type_axis.cuh>
@@ -65,30 +65,29 @@ struct axes_metadata
6565

6666
void add_string_axis(std::string name, std::vector<std::string> data);
6767

68-
void add_axis(const axis_base& axis);
68+
void add_axis(const axis_base &axis);
6969

7070
template <typename... Args>
7171
void add_zip_axes(Args &&...args)
7272
{
73-
(this->add_axis(std::forward<Args>(args)), ...);
74-
this->zip_axes({args.get_name()...});
73+
const std::size_t start = this->m_axes.size();
74+
const std::size_t count = sizeof...(Args);
75+
// (this->add_axis(std::forward<Args>(args)), ...);
76+
(m_axes.push_back(args.clone()), ...);
77+
this->add_zip_space(start, count);
7578
}
7679

7780
template <typename... Args>
7881
void add_user_iteration_axes(
7982
std::function<nvbench::make_user_space_signature> make,
8083
Args &&...args)
8184
{
82-
(this->add_axis(std::forward<Args>(args)), ...);
83-
this->user_iteration_axes(std::move(make), {args.get_name()...});
85+
const std::size_t start = this->m_axes.size();
86+
const std::size_t count = sizeof...(Args);
87+
(m_axes.push_back(args.clone()), ...);
88+
this->add_user_iteration_space(std::move(make), start, count);
8489
}
8590

86-
void zip_axes(std::vector<std::string> names);
87-
88-
void
89-
user_iteration_axes(std::function<nvbench::make_user_space_signature> make,
90-
std::vector<std::string> names);
91-
9291
[[nodiscard]] const iteration_space_type &get_type_iteration_space() const
9392
{
9493
return m_type_space;
@@ -136,6 +135,12 @@ private:
136135
std::size_t m_type_axe_count = 0;
137136
iteration_space_type m_type_space;
138137
iteration_space_type m_value_space;
138+
139+
void add_zip_space(std::size_t first_index, std::size_t count);
140+
void add_user_iteration_space(
141+
std::function<nvbench::make_user_space_signature> make,
142+
std::size_t first_index,
143+
std::size_t count);
139144
};
140145

141146
template <typename... TypeAxes>

nvbench/axes_metadata.cxx

Lines changed: 24 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <fmt/ranges.h>
2525

2626
#include <algorithm>
27+
#include <numeric>
2728
#include <stdexcept>
2829
#include <unordered_set>
2930

@@ -117,128 +118,45 @@ catch (std::exception &e)
117118
void axes_metadata::add_float64_axis(std::string name,
118119
std::vector<nvbench::float64_t> data)
119120
{
120-
this->add_axis(nvbench::float64_axis{name,data});
121+
this->add_axis(nvbench::float64_axis{name, data});
121122
}
122123

123124
void axes_metadata::add_int64_axis(std::string name,
124125
std::vector<nvbench::int64_t> data,
125126
nvbench::int64_axis_flags flags)
126127
{
127-
this->add_axis(nvbench::int64_axis{name,data,flags});
128+
this->add_axis(nvbench::int64_axis{name, data, flags});
128129
}
129130

130131
void axes_metadata::add_string_axis(std::string name,
131132
std::vector<std::string> data)
132133
{
133-
this->add_axis(nvbench::string_axis{name,data});
134+
this->add_axis(nvbench::string_axis{name, data});
134135
}
135136

136-
void axes_metadata::add_axis(const axis_base& axis)
137+
void axes_metadata::add_axis(const axis_base &axis)
137138
{
138139
m_value_space.push_back(
139140
std::make_unique<linear_axis_space>(m_axes.size(),
140141
m_axes.size() - m_type_axe_count));
141142
m_axes.push_back(axis.clone());
142143
}
143144

144-
namespace
145+
void axes_metadata::add_zip_space(std::size_t first_index, std::size_t count)
145146
{
146-
std::tuple<std::vector<std::size_t>, std::vector<std::size_t>>
147-
get_axes_indices(std::size_t type_axe_count,
148-
const nvbench::axes_metadata::axes_type &axes,
149-
const std::vector<std::string> &names)
150-
{
151-
std::vector<std::size_t> input_indices;
152-
input_indices.reserve(names.size());
153-
for (auto &n : names)
154-
{
155-
auto iter =
156-
std::find_if(axes.cbegin(), axes.cend(), [&n](const auto &axis) {
157-
return axis->get_name() == n;
158-
});
159-
160-
// iter distance is input_indices
161-
if (iter == axes.cend())
162-
{
163-
NVBENCH_THROW(std::runtime_error,
164-
"Unable to find the axes named ({}).",
165-
n);
166-
}
167-
auto index = std::distance(axes.cbegin(), iter);
168-
input_indices.push_back(index);
169-
}
170-
171-
std::vector<std::size_t> output_indices = input_indices;
172-
for (auto &out : output_indices)
173-
{
174-
out -= type_axe_count;
175-
}
176-
return {std::move(input_indices), std::move(output_indices)};
177-
}
178-
179-
void reset_iteration_space(
180-
nvbench::axes_metadata::iteration_space_type &all_spaces,
181-
const std::vector<std::size_t> &indices_to_remove)
182-
{
183-
// 1. Find all spaces indices that
184-
nvbench::axes_metadata::iteration_space_type reset_space;
185-
nvbench::axes_metadata::iteration_space_type to_filter;
186-
for (auto &space : all_spaces)
187-
{
188-
bool added = false;
189-
for (auto &i : indices_to_remove)
190-
{
191-
if (space->contains(i))
192-
{
193-
// add each item back as linear_axis_space
194-
auto as_linear = space->clone_as_linear();
195-
to_filter.insert(to_filter.end(),
196-
std::make_move_iterator(as_linear.begin()),
197-
std::make_move_iterator(as_linear.end()));
198-
added = true;
199-
break;
200-
}
201-
}
202-
if (!added)
203-
{
204-
// this space doesn't need to be removed
205-
reset_space.push_back(std::move(space));
206-
}
207-
}
208-
209-
for (auto &iter : to_filter)
210-
{
211-
bool to_add = true;
212-
for (auto &i : indices_to_remove)
213-
{
214-
if (iter->contains(i))
215-
{
216-
to_add = false;
217-
break;
218-
}
219-
}
220-
if (to_add)
221-
{
222-
reset_space.push_back(std::move(iter));
223-
break;
224-
}
225-
}
226-
227-
all_spaces = std::move(reset_space);
228-
}
229-
} // namespace
230-
231-
void axes_metadata::zip_axes(std::vector<std::string> names)
232-
{
233-
NVBENCH_THROW_IF((names.size() < 2),
147+
NVBENCH_THROW_IF((count < 2),
234148
std::runtime_error,
235-
"At least two axi names ( {} provided ) need to be provided "
149+
"At least two axi ( {} provided ) need to be provided "
236150
"when using zip_axes.",
237-
names.size());
151+
count);
238152

239153
// compute the numeric indice for each name we have
240-
auto [input_indices,
241-
output_indices] = get_axes_indices(m_type_axe_count, m_axes, names);
154+
std::vector<std::size_t> input_indices(count);
155+
std::vector<std::size_t> output_indices(count);
156+
std::iota(input_indices.begin(), input_indices.end(), first_index);
157+
std::iota(input_indices.begin(),
158+
input_indices.end(),
159+
first_index - m_type_axe_count);
242160

243161
const auto expected_size = m_axes[input_indices[0]]->get_size();
244162
for (auto i : input_indices)
@@ -255,22 +173,24 @@ void axes_metadata::zip_axes(std::vector<std::string> names)
255173
expected_size);
256174
}
257175

258-
// remove any iteration spaces that have axes we need
259-
reset_iteration_space(m_value_space, input_indices);
260-
261176
// add the new tied iteration space
262177
auto tied = std::make_unique<zip_axis_space>(std::move(input_indices),
263178
std::move(output_indices));
264179
m_value_space.push_back(std::move(tied));
265180
}
266181

267-
void axes_metadata::user_iteration_axes(
182+
void axes_metadata::add_user_iteration_space(
268183
std::function<nvbench::make_user_space_signature> make,
269-
std::vector<std::string> names)
184+
std::size_t first_index,
185+
std::size_t count)
270186
{
271187
// compute the numeric indice for each name we have
272-
auto [input_indices,
273-
output_indices] = get_axes_indices(m_type_axe_count, m_axes, names);
188+
std::vector<std::size_t> input_indices(count);
189+
std::vector<std::size_t> output_indices(count);
190+
std::iota(input_indices.begin(), input_indices.end(), first_index);
191+
std::iota(input_indices.begin(),
192+
input_indices.end(),
193+
first_index - m_type_axe_count);
274194

275195
for (auto i : input_indices)
276196
{
@@ -281,9 +201,6 @@ void axes_metadata::user_iteration_axes(
281201
m_axes[i]->get_name());
282202
}
283203

284-
// remove any iteration spaces that have axes we need
285-
reset_iteration_space(m_value_space, input_indices);
286-
287204
auto user_func = make(std::move(input_indices), std::move(output_indices));
288205
m_value_space.push_back(std::move(user_func));
289206
}

nvbench/benchmark_base.cuh

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -280,38 +280,6 @@ struct benchmark_base
280280
/// @}
281281

282282
protected:
283-
284-
/// Move existing Axis to being part of zip axis iteration space.
285-
/// This will remove any existing iteration spaces that the named axis
286-
/// are part of, while restoring all other axis in those spaces to
287-
/// the default linear space
288-
///
289-
/// This is meant to be used only by the option_parser
290-
/// @{
291-
benchmark_base &zip_axes(std::vector<std::string> names)
292-
{
293-
m_axes.zip_axes(std::move(names));
294-
return *this;
295-
}
296-
/// @}
297-
298-
299-
/// Move existing Axis to being part of user axis iteration space.
300-
/// This will remove any existing iteration spaces that the named axis
301-
/// are part of, while restoring all other axis in those spaces to
302-
/// the default linear space
303-
///
304-
/// This is meant to be used only by the option_parser
305-
/// @{
306-
benchmark_base &
307-
user_iteration_axes(std::function<nvbench::make_user_space_signature> make,
308-
std::vector<std::string> names)
309-
{
310-
m_axes.user_iteration_axes(std::move(make), std::move(names));
311-
return *this;
312-
}
313-
/// @}
314-
315283
friend struct nvbench::runner_base;
316284

317285
template <typename BenchmarkType>

nvbench/iteration_space_base.cuh

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,17 @@ namespace nvbench
3636
*
3737
* * user_axis_space is equivalant to a transform iterator.
3838
*
39-
* We don't immediately construct the iterators as the active elements,
40-
* name, etc can be changed before execution. This class allows for
41-
* the deferred iterator creation while keeping the meta data insyc.
39+
* The `nvbench::axes_metadata` stores all axes in a std::vector. To represent
40+
* which axes each space is 'over' we store those indices. We don't store
41+
* the pointers or names for the following reasons:
42+
*
43+
* * The names of an axis can change after being added. The `nvbench::axes_metadata`
44+
* is not aware of the name change, and can't inform this class of it.
45+
*
46+
* * The `nvbench::axes_metadata` can be deep copied, which would invalidate
47+
* any pointers held by this class. By holding onto the index we remove the need
48+
* to do any form of fixup on deep copies of `nvbench::axes_metadata`.
49+
*
4250
*
4351
*/
4452
struct iteration_space_base
@@ -65,15 +73,6 @@ struct iteration_space_base
6573

6674
[[nodiscard]] std::unique_ptr<iteration_space_base> clone() const;
6775

68-
/*!
69-
* Returns a vector of linear spaces one for each axi held.
70-
* This is required when a iteration_space is removed as we need
71-
* to restore all the assoicated axes to default.
72-
*
73-
*/
74-
[[nodiscard]] std::vector<std::unique_ptr<iteration_space_base>>
75-
clone_as_linear() const;
76-
7776
/*!
7877
* Returns the iterator over the @a axis provided
7978
*
@@ -101,24 +100,6 @@ struct iteration_space_base
101100
*/
102101
[[nodiscard]] std::size_t get_active_count(const axes_type &axes) const;
103102

104-
/*!
105-
* Returns if this space was constructed with the input index specified
106-
* by @a input_index.
107-
*
108-
* The `nvbench::axes_metadata` stores all axes in a std::vector. To represent
109-
* which axes each space is 'over' we store those indices. We don't store
110-
* the pointers or names for the following reasons:
111-
*
112-
* * The names of an axis can change after being added. The `nvbench::axes_metadata`
113-
* is not aware of the name change, and can't inform this class of it.
114-
*
115-
* * The `nvbench::axes_metadata` can be deep copied, which would invalidate
116-
* any pointers held by this class. By holding onto the index we remove the need
117-
* to do any form of fixup on deep copies of `nvbench::axes_metadata`.
118-
*
119-
*/
120-
[[nodiscard]] bool contains(std::size_t input_index) const;
121-
122103
protected:
123104
std::vector<std::size_t> m_input_indices;
124105
std::vector<std::size_t> m_output_indices;

0 commit comments

Comments
 (0)