Skip to content

Commit 6fe2522

Browse files
sbstndbclaude
andcommitted
Simplify comparison benchmarks code
Reduce code duplication and improve readability: - Add helper functions for xtensor/xarray creation - Add BENCHMARK_LOOP macro to reduce boilerplate - Add REGISTER_BENCHMARK macro for standard sizes - Rename: raw_cpp → std, shorten xtensor variants - Add size 8 to benchmark ranges - Use constexpr for scalar values Changes: - blas1_comparison.cpp: 211 → 197 lines (-14 lines) - Add min_size=8, max_size=16384, multiplier=4 constants - Simpler, more maintainable code 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 9549224 commit 6fe2522

File tree

1 file changed

+119
-133
lines changed

1 file changed

+119
-133
lines changed

benchmark/comparison/blas1_comparison.cpp

Lines changed: 119 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -15,197 +15,183 @@ namespace xt::comparison
1515
{
1616

1717
//========================================================================
18-
// Vector Addition: z = x + y
18+
// Helpers
1919
//========================================================================
2020

21-
// Raw C++ implementation with std::vector
22-
static void add_vector_raw_cpp(benchmark::State& state)
21+
// Benchmark range configuration
22+
constexpr std::size_t min_size = 8;
23+
constexpr std::size_t max_size = 16384;
24+
constexpr std::size_t multiplier = 4;
25+
26+
// Helper to create xtensor vectors
27+
inline auto make_xtensor(std::size_t size, double val)
2328
{
24-
using value_type = double;
25-
using size_type = std::size_t;
26-
27-
const size_type size = state.range(0);
28-
std::vector<value_type> x(size, 1.0);
29-
std::vector<value_type> y(size, 2.0);
30-
std::vector<value_type> z(size);
31-
32-
for (auto _ : state)
33-
{
34-
for (size_type i = 0; i < size; ++i)
35-
{
36-
z[i] = x[i] + y[i];
37-
}
38-
benchmark::DoNotOptimize(z.data());
39-
}
29+
return xt::xtensor<double, 1>::from_shape({size}) * val;
4030
}
4131

42-
// xtensor implementation with xarray
43-
static void add_vector_xtensor_xarray(benchmark::State& state)
32+
inline auto make_xtensor_zeros(std::size_t size)
4433
{
45-
using size_type = std::size_t;
34+
auto c = xt::xtensor<double, 1>::from_shape({size});
35+
c.fill(0);
36+
return c;
37+
}
4638

47-
const size_type size = state.range(0);
48-
xarray<double> x = xt::ones<double>({size});
49-
xarray<double> y = 2.0 * xt::ones<double>({size});
50-
xarray<double> z;
39+
// Helper to create xarray
40+
inline auto make_xarray(std::size_t size, double val)
41+
{
42+
return xt::xarray<double>::from_shape({size}) * val;
43+
}
5144

52-
for (auto _ : state)
53-
{
54-
z = x + y;
55-
benchmark::DoNotOptimize(z.data());
45+
// Macro for benchmark loop (reduces boilerplate)
46+
#define BENCHMARK_LOOP(state, container, ...) \
47+
for (auto _ : state) { \
48+
__VA_ARGS__; \
49+
benchmark::DoNotOptimize(container.data()); \
5650
}
57-
}
5851

59-
// xtensor implementation with xtensor (fixed size)
60-
static void add_vector_xtensor_xtensor(benchmark::State& state)
52+
// Macro for registering benchmarks with standard sizes
53+
#define REGISTER_BENCHMARK(func) \
54+
BENCHMARK(func)->Range(min_size, max_size)->RangeMultiplier(multiplier)
55+
56+
//========================================================================
57+
// Vector Addition: z = x + y
58+
//========================================================================
59+
60+
static void add_vector_std(benchmark::State& state)
6161
{
62-
using size_type = std::size_t;
62+
const std::size_t size = state.range(0);
63+
std::vector<double> x(size, 1.0);
64+
std::vector<double> y(size, 2.0);
65+
std::vector<double> z(size);
66+
67+
BENCHMARK_LOOP(state, z,
68+
for (std::size_t i = 0; i < size; ++i)
69+
z[i] = x[i] + y[i];
70+
);
71+
}
6372

64-
const size_type size = state.range(0);
65-
xtensor<double, 1> x = xt::ones<double>({size});
66-
xtensor<double, 1> y = 2.0 * xt::ones<double>({size});
67-
xtensor<double, 1> z;
73+
static void add_vector_xarray(benchmark::State& state)
74+
{
75+
const std::size_t size = state.range(0);
76+
auto x = make_xarray(size, 1.0);
77+
auto y = make_xarray(size, 2.0);
78+
xt::xarray<double> z;
6879

69-
for (auto _ : state)
70-
{
80+
BENCHMARK_LOOP(state, z,
7181
z = x + y;
72-
benchmark::DoNotOptimize(z.data());
73-
}
82+
);
7483
}
7584

76-
// xtensor with noalias (avoids temporary allocation)
77-
static void add_vector_xtensor_noalias(benchmark::State& state)
85+
static void add_vector_xtensor(benchmark::State& state)
7886
{
79-
using size_type = std::size_t;
87+
const std::size_t size = state.range(0);
88+
auto x = make_xtensor(size, 1.0);
89+
auto y = make_xtensor(size, 2.0);
90+
xt::xtensor<double, 1> z;
8091

81-
const size_type size = state.range(0);
82-
xtensor<double, 1> x = xt::ones<double>({size});
83-
xtensor<double, 1> y = 2.0 * xt::ones<double>({size});
84-
xtensor<double, 1> z = xt::zeros<double>({size});
92+
BENCHMARK_LOOP(state, z,
93+
z = x + y;
94+
);
95+
}
8596

86-
for (auto _ : state)
87-
{
97+
static void add_vector_noalias(benchmark::State& state)
98+
{
99+
const std::size_t size = state.range(0);
100+
auto x = make_xtensor(size, 1.0);
101+
auto y = make_xtensor(size, 2.0);
102+
auto z = make_xtensor_zeros(size);
103+
104+
BENCHMARK_LOOP(state, z,
88105
xt::noalias(z) = x + y;
89-
benchmark::DoNotOptimize(z.data());
90-
}
106+
);
91107
}
92108

93109
//========================================================================
94-
// Scalar Addition: z = x + a (add_scalar)
110+
// Scalar Addition: z = x + a
95111
//========================================================================
96112

97-
// Raw C++
98-
static void add_scalar_raw_cpp(benchmark::State& state)
113+
static void add_scalar_std(benchmark::State& state)
99114
{
100-
using value_type = double;
101-
using size_type = std::size_t;
102-
103-
const size_type size = state.range(0);
104-
const value_type a = 5.0;
105-
std::vector<value_type> x(size, 1.0);
106-
std::vector<value_type> z(size);
107-
108-
for (auto _ : state)
109-
{
110-
for (size_type i = 0; i < size; ++i)
111-
{
115+
const std::size_t size = state.range(0);
116+
constexpr double a = 5.0;
117+
std::vector<double> x(size, 1.0);
118+
std::vector<double> z(size);
119+
120+
BENCHMARK_LOOP(state, z,
121+
for (std::size_t i = 0; i < size; ++i)
112122
z[i] = x[i] + a;
113-
}
114-
benchmark::DoNotOptimize(z.data());
115-
}
123+
);
116124
}
117125

118-
// xtensor
119126
static void add_scalar_xtensor(benchmark::State& state)
120127
{
121-
using size_type = std::size_t;
128+
const std::size_t size = state.range(0);
129+
constexpr double a = 5.0;
130+
auto x = make_xtensor(size, 1.0);
131+
xt::xtensor<double, 1> z;
122132

123-
const size_type size = state.range(0);
124-
const double a = 5.0;
125-
xtensor<double, 1> x = xt::ones<double>({size});
126-
xtensor<double, 1> z;
127-
128-
for (auto _ : state)
129-
{
133+
BENCHMARK_LOOP(state, z,
130134
z = x + a;
131-
benchmark::DoNotOptimize(z.data());
132-
}
135+
);
133136
}
134137

135-
// xtensor with noalias
136-
static void add_scalar_xtensor_noalias(benchmark::State& state)
138+
static void add_scalar_noalias(benchmark::State& state)
137139
{
138-
using size_type = std::size_t;
140+
const std::size_t size = state.range(0);
141+
constexpr double a = 5.0;
142+
auto x = make_xtensor(size, 1.0);
143+
auto z = make_xtensor_zeros(size);
139144

140-
const size_type size = state.range(0);
141-
const double a = 5.0;
142-
xtensor<double, 1> x = xt::ones<double>({size});
143-
xtensor<double, 1> z = xt::zeros<double>({size});
144-
145-
for (auto _ : state)
146-
{
145+
BENCHMARK_LOOP(state, z,
147146
xt::noalias(z) = x + a;
148-
benchmark::DoNotOptimize(z.data());
149-
}
147+
);
150148
}
151149

152150
//========================================================================
153151
// Scalar Multiplication: y = a * x
154152
//========================================================================
155153

156-
// Raw C++
157-
static void mul_scalar_raw_cpp(benchmark::State& state)
154+
static void mul_scalar_std(benchmark::State& state)
158155
{
159-
using value_type = double;
160-
using size_type = std::size_t;
161-
162-
const size_type size = state.range(0);
163-
const value_type a = 2.5;
164-
std::vector<value_type> x(size, 1.0);
165-
std::vector<value_type> y(size);
166-
167-
for (auto _ : state)
168-
{
169-
for (size_type i = 0; i < size; ++i)
170-
{
156+
const std::size_t size = state.range(0);
157+
constexpr double a = 2.5;
158+
std::vector<double> x(size, 1.0);
159+
std::vector<double> y(size);
160+
161+
BENCHMARK_LOOP(state, y,
162+
for (std::size_t i = 0; i < size; ++i)
171163
y[i] = a * x[i];
172-
}
173-
benchmark::DoNotOptimize(y.data());
174-
}
164+
);
175165
}
176166

177-
// xtensor
178167
static void mul_scalar_xtensor(benchmark::State& state)
179168
{
180-
using size_type = std::size_t;
169+
const std::size_t size = state.range(0);
170+
constexpr double a = 2.5;
171+
auto x = make_xtensor(size, 1.0);
172+
xt::xtensor<double, 1> y;
181173

182-
const size_type size = state.range(0);
183-
const double a = 2.5;
184-
xtensor<double, 1> x = xt::ones<double>({size});
185-
xtensor<double, 1> y;
186-
187-
for (auto _ : state)
188-
{
174+
BENCHMARK_LOOP(state, y,
189175
y = a * x;
190-
benchmark::DoNotOptimize(y.data());
191-
}
176+
);
192177
}
193178

194179
//========================================================================
195-
// Register benchmarks with different sizes
180+
// Register benchmarks
196181
//========================================================================
197182

198-
// Vector sizes to test: 64, 256, 1024, 4096, 16384
199-
BENCHMARK(add_vector_raw_cpp)->Range(64, 16384)->RangeMultiplier(4);
200-
BENCHMARK(add_vector_xtensor_xarray)->Range(64, 16384)->RangeMultiplier(4);
201-
BENCHMARK(add_vector_xtensor_xtensor)->Range(64, 16384)->RangeMultiplier(4);
202-
BENCHMARK(add_vector_xtensor_noalias)->Range(64, 16384)->RangeMultiplier(4);
183+
// Vector + Vector
184+
REGISTER_BENCHMARK(add_vector_std);
185+
REGISTER_BENCHMARK(add_vector_xarray);
186+
REGISTER_BENCHMARK(add_vector_xtensor);
187+
REGISTER_BENCHMARK(add_vector_noalias);
203188

204-
BENCHMARK(add_scalar_raw_cpp)->Range(64, 16384)->RangeMultiplier(4);
205-
BENCHMARK(add_scalar_xtensor)->Range(64, 16384)->RangeMultiplier(4);
206-
BENCHMARK(add_scalar_xtensor_noalias)->Range(64, 16384)->RangeMultiplier(4);
189+
// Scalar operations
190+
REGISTER_BENCHMARK(add_scalar_std);
191+
REGISTER_BENCHMARK(add_scalar_xtensor);
192+
REGISTER_BENCHMARK(add_scalar_noalias);
207193

208-
BENCHMARK(mul_scalar_raw_cpp)->Range(64, 16384)->RangeMultiplier(4);
209-
BENCHMARK(mul_scalar_xtensor)->Range(64, 16384)->RangeMultiplier(4);
194+
REGISTER_BENCHMARK(mul_scalar_std);
195+
REGISTER_BENCHMARK(mul_scalar_xtensor);
210196

211197
}

0 commit comments

Comments
 (0)