Skip to content

Commit

Permalink
[vector.bool] Optimize copy / move algorithms (#3353)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephan T. Lavavej <[email protected]>
  • Loading branch information
miscco and StephanTLavavej authored Sep 21, 2023
1 parent 8f67ece commit f6580c2
Show file tree
Hide file tree
Showing 7 changed files with 1,606 additions and 67 deletions.
4 changes: 4 additions & 0 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,7 @@ add_benchmark(locale_classic src/locale_classic.cpp)
add_benchmark(path_lexically_normal src/path_lexically_normal.cpp)
add_benchmark(random_integer_generation src/random_integer_generation.cpp)
add_benchmark(std_copy src/std_copy.cpp)

add_benchmark(vector_bool_copy src/std/containers/sequences/vector.bool/copy/test.cpp)
add_benchmark(vector_bool_copy_n src/std/containers/sequences/vector.bool/copy_n/test.cpp)
add_benchmark(vector_bool_move src/std/containers/sequences/vector.bool/move/test.cpp)
100 changes: 100 additions & 0 deletions benchmarks/src/std/containers/sequences/vector.bool/copy/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <benchmark/benchmark.h>
//
#include <algorithm>
#include <random>
#include <vector>

using namespace std;

static vector<bool> createRandomVector(const size_t size) {
static mt19937 gen{random_device{}()};
vector<bool> result(size);
generate_n(result.begin(), size, [] { return bernoulli_distribution{0.5}(gen); });
return result;
}

static void copy_block_aligned(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
copy(source.cbegin(), source.cend(), dest.begin());
}
}

static void copy_source_misaligned(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
copy(source.cbegin() + 1, source.cend(), dest.begin());
}
}

static void copy_dest_misaligned(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
copy(source.cbegin(), source.cend() - 1, dest.begin() + 1);
}
}

// Special benchmark for matching char alignment
static void copy_matching_alignment(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
copy(source.cbegin() + 5, source.cend(), dest.begin() + 5);
}
}

// Special benchmarks for single block corner case
static void copy_both_single_blocks(benchmark::State& state) {
const vector<bool> source = createRandomVector(50);
vector<bool> dest(50, false);

const size_t length = 20;
for (auto _ : state) {
copy(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 5);
}
}

static void copy_source_single_block(benchmark::State& state) {
const vector<bool> source = createRandomVector(50);
vector<bool> dest(50, false);

const size_t length = 20;
for (auto _ : state) {
copy(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 25);
}
}

static void copy_dest_single_block(benchmark::State& state) {
const vector<bool> source = createRandomVector(50);
vector<bool> dest(50, false);

const size_t length = 20;
for (auto _ : state) {
copy(source.cbegin() + 25, source.cbegin() + 25 + length, dest.begin() + 5);
}
}

BENCHMARK(copy_block_aligned)->RangeMultiplier(64)->Range(64, 64 << 10);
BENCHMARK(copy_source_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
BENCHMARK(copy_dest_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
BENCHMARK(copy_matching_alignment)->RangeMultiplier(64)->Range(64, 64 << 10);

BENCHMARK(copy_both_single_blocks);
BENCHMARK(copy_source_single_block);
BENCHMARK(copy_dest_single_block);

BENCHMARK_MAIN();
100 changes: 100 additions & 0 deletions benchmarks/src/std/containers/sequences/vector.bool/copy_n/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <benchmark/benchmark.h>
//
#include <algorithm>
#include <random>
#include <vector>

using namespace std;

static vector<bool> createRandomVector(const size_t size) {
static mt19937 gen{random_device{}()};
vector<bool> result(size);
generate_n(result.begin(), size, [] { return bernoulli_distribution{0.5}(gen); });
return result;
}

static void copy_n_block_aligned(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
copy_n(source.cbegin(), size, dest.begin());
}
}

static void copy_n_source_misaligned(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
copy_n(source.cbegin() + 1, size - 1, dest.begin());
}
}

static void copy_n_dest_misaligned(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
copy_n(source.cbegin(), size - 1, dest.begin() + 1);
}
}

// Special benchmark for matching char alignment
static void copy_n_matching_alignment(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
copy_n(source.cbegin() + 5, size - 5, dest.begin() + 5);
}
}

// Special benchmarks for single block corner case
static void copy_n_both_single_blocks(benchmark::State& state) {
const vector<bool> source = createRandomVector(50);
vector<bool> dest(50, false);

const size_t length = 20;
for (auto _ : state) {
copy_n(source.cbegin() + 5, length, dest.begin() + 5);
}
}

static void copy_n_source_single_block(benchmark::State& state) {
const vector<bool> source = createRandomVector(50);
vector<bool> dest(50, false);

const size_t length = 20;
for (auto _ : state) {
copy_n(source.cbegin() + 5, length, dest.begin() + 25);
}
}

static void copy_n_dest_single_block(benchmark::State& state) {
const vector<bool> source = createRandomVector(50);
vector<bool> dest(50, false);

const size_t length = 20;
for (auto _ : state) {
copy_n(source.cbegin() + 25, length, dest.begin() + 5);
}
}

BENCHMARK(copy_n_block_aligned)->RangeMultiplier(64)->Range(64, 64 << 10);
BENCHMARK(copy_n_source_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
BENCHMARK(copy_n_dest_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
BENCHMARK(copy_n_matching_alignment)->RangeMultiplier(64)->Range(64, 64 << 10);

BENCHMARK(copy_n_both_single_blocks);
BENCHMARK(copy_n_source_single_block);
BENCHMARK(copy_n_dest_single_block);

BENCHMARK_MAIN();
100 changes: 100 additions & 0 deletions benchmarks/src/std/containers/sequences/vector.bool/move/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <benchmark/benchmark.h>
//
#include <algorithm>
#include <random>
#include <vector>

using namespace std;

static vector<bool> createRandomVector(const size_t size) {
static mt19937 gen{random_device{}()};
vector<bool> result(size);
generate_n(result.begin(), size, [] { return bernoulli_distribution{0.5}(gen); });
return result;
}

static void move_block_aligned(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
move(source.cbegin(), source.cend(), dest.begin());
}
}

static void move_source_misaligned(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
move(source.cbegin() + 1, source.cend(), dest.begin());
}
}

static void move_dest_misaligned(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
move(source.cbegin(), source.cend() - 1, dest.begin() + 1);
}
}

// Special benchmark for matching char alignment
static void move_matching_alignment(benchmark::State& state) {
const auto size = state.range(0);
const vector<bool> source = createRandomVector(size);
vector<bool> dest(size, false);

for (auto _ : state) {
move(source.cbegin() + 5, source.cend(), dest.begin() + 5);
}
}

// Special benchmarks for single block corner case
static void move_both_single_blocks(benchmark::State& state) {
const vector<bool> source = createRandomVector(50);
vector<bool> dest(50, false);

const size_t length = 20;
for (auto _ : state) {
move(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 5);
}
}

static void move_source_single_block(benchmark::State& state) {
const vector<bool> source = createRandomVector(50);
vector<bool> dest(50, false);

const size_t length = 20;
for (auto _ : state) {
move(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 25);
}
}

static void move_dest_single_block(benchmark::State& state) {
const vector<bool> source = createRandomVector(50);
vector<bool> dest(50, false);

const size_t length = 20;
for (auto _ : state) {
move(source.cbegin() + 25, source.cbegin() + 25 + length, dest.begin() + 5);
}
}

BENCHMARK(move_block_aligned)->RangeMultiplier(64)->Range(64, 64 << 10);
BENCHMARK(move_source_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
BENCHMARK(move_dest_misaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
BENCHMARK(move_matching_alignment)->RangeMultiplier(64)->Range(64, 64 << 10);

BENCHMARK(move_both_single_blocks);
BENCHMARK(move_source_single_block);
BENCHMARK(move_dest_single_block);

BENCHMARK_MAIN();
Loading

0 comments on commit f6580c2

Please sign in to comment.