Skip to content

Instantly share code, notes, and snippets.

@Aposhian
Last active April 26, 2022 22:33
Show Gist options
  • Save Aposhian/7374d1af1f4cfdf99750410b14b4d0ac to your computer and use it in GitHub Desktop.
Save Aposhian/7374d1af1f4cfdf99750410b14b4d0ac to your computer and use it in GitHub Desktop.
std::transform benchmarking
#include <benchmark/benchmark.h>
#include <vector>
#include <algorithm>
#include <execution>
struct data {
int a;
int b;
int c;
};
std::vector<int> resizer(std::vector<struct data> input) {
std::vector<int> output(input.size());
std::transform(
input.begin(),
input.end(),
output.begin(),
[](const auto & data) {
return data.a + data.b + data.c;
}
);
return output;
}
std::vector<int> resizer_parallel(std::vector<struct data> input) {
std::vector<int> output(input.size());
std::transform(
std::execution::par_unseq,
input.begin(),
input.end(),
output.begin(),
[](const auto & data) {
return data.a + data.b + data.c;
}
);
return output;
}
std::vector<int> reserver(std::vector<struct data> input) {
std::vector<int> output;
output.reserve(input.size());
std::transform(
input.begin(),
input.end(),
std::back_inserter(output),
[](const auto & data) {
return data.a + data.b + data.c;
}
);
return output;
}
std::vector<int> for_loop(std::vector<struct data> input) {
std::vector<int> output;
for (const auto & data : input) {
output.push_back(data.a + data.b + data.c);
}
return output;
}
std::vector<int> reserve_for_loop(std::vector<struct data> input) {
std::vector<int> output;
output.reserve(input.size());
for (const auto & data : input) {
output.push_back(data.a + data.b + data.c);
}
return output;
}
static constexpr size_t NUM_ELEMENTS = 1000000;
void generate_input(std::vector<struct data> & input) {
input.reserve(NUM_ELEMENTS);
for (int i = 0; i < NUM_ELEMENTS; ++i) {
input[i] = {
.a = rand(),
.b = rand(),
.c = rand()
};
}
}
static void TestResizer(benchmark::State& state) {
std::vector<struct data> input;
generate_input(input);
// Code inside this loop is measured repeatedly
for (auto _ : state) {
benchmark::DoNotOptimize(input);
benchmark::DoNotOptimize(resizer(input));
benchmark::ClobberMemory();
}
}
// Register the function as a benchmark
BENCHMARK(TestResizer);
static void TestReserver(benchmark::State& state) {
// Code before the loop is not measured
std::vector<struct data> input;
generate_input(input);
for (auto _ : state) {
benchmark::DoNotOptimize(input);
benchmark::DoNotOptimize(reserver(input));
benchmark::ClobberMemory();
}
}
BENCHMARK(TestReserver);
static void TestResizerParallel(benchmark::State& state) {
// Code before the loop is not measured
std::vector<struct data> input;
generate_input(input);
for (auto _ : state) {
benchmark::DoNotOptimize(input);
benchmark::DoNotOptimize(resizer_parallel(input));
benchmark::ClobberMemory();
}
}
BENCHMARK(TestResizerParallel);
static void TestForLoop(benchmark::State& state) {
// Code before the loop is not measured
std::vector<struct data> input;
generate_input(input);
for (auto _ : state) {
benchmark::DoNotOptimize(input);
benchmark::DoNotOptimize(for_loop(input));
benchmark::ClobberMemory();
}
}
BENCHMARK(TestForLoop);
static void TestReserveForLoop(benchmark::State& state) {
// Code before the loop is not measured
std::vector<struct data> input;
generate_input(input);
for (auto _ : state) {
benchmark::DoNotOptimize(input);
auto output = reserve_for_loop(input);
benchmark::DoNotOptimize(output);
benchmark::ClobberMemory();
}
}
BENCHMARK(TestReserveForLoop);
BENCHMARK_MAIN();
test:
g++ -std=c++17 -O3 main.cpp -ltbb -lbenchmark -lpthread -o benchmark
./benchmark
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment