Skip to content

Commit f413538

Browse files
committed
[vector.bool] Optimize copy / move algorithms
1 parent 40e9070 commit f413538

File tree

8 files changed

+1284
-74
lines changed

8 files changed

+1284
-74
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -416,28 +416,28 @@ for how _we_ use it.
416416
To run benchmarks, you'll need to first build the STL, then build the benchmarks:
417417

418418
```cmd
419-
cmake -B out\x64 -S . -G Ninja
420-
cmake --build out\x64
421-
cmake -B out\benchmark -S benchmarks -G Ninja -DSTL_BINARY_DIR=out\x64
422-
cmake --build out\benchmark
419+
cmake -B out\build\x64 -S . -G Ninja
420+
cmake --build out\build\x64
421+
cmake -B out\build\benchmark -S benchmarks -G Ninja -DSTL_BINARY_DIR=out\build\x64
422+
cmake --build out\build\benchmark
423423
```
424424

425425
You can then run your benchmark with:
426426

427427
```cmd
428-
out\benchmark\benchmark-<benchmark-name> --benchmark_out=<file> --benchmark_out_format=csv
428+
out\build\benchmark\benchmark-<benchmark-name> --benchmark_out=<file> --benchmark_out_format=csv
429429
```
430430

431431
And then you can copy this csv file into Excel, or another spreadsheet program. For example:
432432

433433
```cmd
434-
out\bench\benchmarks\benchmark-std_copy --benchmark_out=benchmark-std_copy-results.csv --benchmark_out_format=csv
434+
out\build\benchmarks\benchmark-std_copy --benchmark_out=benchmark-std_copy-results.csv --benchmark_out_format=csv
435435
```
436436

437437
If you want to see all the other flags you can pass, run:
438438

439439
```cmd
440-
out\bench\benchmarks\benchmark-<benchmark-name> --help
440+
out\build\benchmarks\benchmark-<benchmark-name> --help
441441
```
442442

443443
# Editing And Testing The Debugger Visualizer

benchmarks/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,7 @@ endfunction()
108108
add_benchmark(locale_classic src/locale_classic.cpp)
109109
add_benchmark(random_integer_generation src/random_integer_generation.cpp)
110110
add_benchmark(std_copy src/std_copy.cpp)
111+
112+
add_benchmark(vector_bool_copy src/std/containers/sequences/vector.bool/copy/test.cpp)
113+
add_benchmark(vector_bool_copy_n src/std/containers/sequences/vector.bool/copy_n/test.cpp)
114+
add_benchmark(vector_bool_move src/std/containers/sequences/vector.bool/move/test.cpp)
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <benchmark/benchmark.h>
5+
//
6+
#include <algorithm>
7+
#include <functional>
8+
#include <random>
9+
#include <vector>
10+
11+
using namespace std;
12+
13+
inline static vector<bool> createRandomVector(const size_t size) {
14+
static random_device rd;
15+
static mt19937 gen{random_device{}()};
16+
vector<bool> result(size);
17+
generate_n(result.begin(), size, [] { return bernoulli_distribution{0.5}(gen); });
18+
return result;
19+
}
20+
21+
static void copy_block_aligned(benchmark::State& state) {
22+
const vector<bool> source = createRandomVector(state.range(0));
23+
vector<bool> dest(state.range(0), false);
24+
25+
for (auto _ : state) {
26+
copy(source.cbegin(), source.cend(), dest.begin());
27+
}
28+
}
29+
30+
static void copy_source_missaligned(benchmark::State& state) {
31+
const vector<bool> source = createRandomVector(state.range(0));
32+
vector<bool> dest(state.range(0), false);
33+
34+
for (auto _ : state) {
35+
copy(source.cbegin() + 1, source.cend(), dest.begin());
36+
}
37+
}
38+
39+
static void copy_dest_missaligned(benchmark::State& state) {
40+
const vector<bool> source = createRandomVector(state.range(0));
41+
vector<bool> dest(state.range(0), false);
42+
43+
for (auto _ : state) {
44+
copy(source.cbegin(), source.cend() - 1, dest.begin() + 1);
45+
}
46+
}
47+
48+
// Special benchmark for matching char alignment
49+
static void copy_matching_alignment(benchmark::State& state) {
50+
const vector<bool> source = createRandomVector(state.range(0));
51+
vector<bool> dest(state.range(0), false);
52+
53+
for (auto _ : state) {
54+
copy(source.cbegin() + 5, source.cend(), dest.begin() + 5);
55+
}
56+
}
57+
58+
// Special benchmarks for single block corner case
59+
static void copy_both_single_blocks(benchmark::State& state) {
60+
const vector<bool> source = createRandomVector(50);
61+
vector<bool> dest(50, false);
62+
63+
const size_t length = 20;
64+
for (auto _ : state) {
65+
copy(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 5);
66+
}
67+
}
68+
69+
static void copy_source_single_block(benchmark::State& state) {
70+
const vector<bool> source = createRandomVector(50);
71+
vector<bool> dest(50, false);
72+
73+
const size_t length = 20;
74+
for (auto _ : state) {
75+
copy(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 25);
76+
}
77+
}
78+
79+
static void copy_dest_single_block(benchmark::State& state) {
80+
const vector<bool> source = createRandomVector(50);
81+
vector<bool> dest(50, false);
82+
83+
const size_t length = 20;
84+
for (auto _ : state) {
85+
copy(source.cbegin() + 25, source.cbegin() + 25 + length, dest.begin() + 5);
86+
}
87+
}
88+
89+
BENCHMARK(copy_block_aligned)->RangeMultiplier(64)->Range(64, 64 << 10);
90+
BENCHMARK(copy_source_missaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
91+
BENCHMARK(copy_dest_missaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
92+
BENCHMARK(copy_matching_alignment)->RangeMultiplier(64)->Range(64, 64 << 10);
93+
94+
BENCHMARK(copy_both_single_blocks);
95+
BENCHMARK(copy_source_single_block);
96+
BENCHMARK(copy_dest_single_block);
97+
98+
BENCHMARK_MAIN();
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <benchmark/benchmark.h>
5+
//
6+
#include <algorithm>
7+
#include <functional>
8+
#include <random>
9+
#include <vector>
10+
11+
using namespace std;
12+
13+
inline static vector<bool> createRandomVector(const size_t size) {
14+
static random_device rd;
15+
static mt19937 gen{random_device{}()};
16+
vector<bool> result(size);
17+
generate_n(result.begin(), size, [] { return bernoulli_distribution{0.5}(gen); });
18+
return result;
19+
}
20+
21+
static void copy_n_block_aligned(benchmark::State& state) {
22+
const auto size = state.range(0);
23+
const vector<bool> source = createRandomVector(size);
24+
vector<bool> dest(size, false);
25+
26+
for (auto _ : state) {
27+
copy_n(source.cbegin(), size, dest.begin());
28+
}
29+
}
30+
31+
static void copy_n_source_missaligned(benchmark::State& state) {
32+
const auto size = state.range(0);
33+
const vector<bool> source = createRandomVector(size);
34+
vector<bool> dest(size, false);
35+
36+
for (auto _ : state) {
37+
copy_n(source.cbegin() + 1, size - 1, dest.begin());
38+
}
39+
}
40+
41+
static void copy_n_dest_missaligned(benchmark::State& state) {
42+
const auto size = state.range(0);
43+
const vector<bool> source = createRandomVector(size);
44+
vector<bool> dest(size, false);
45+
46+
for (auto _ : state) {
47+
copy_n(source.cbegin(), size - 1, dest.begin() + 1);
48+
}
49+
}
50+
51+
// Special benchmark for matching char alignment
52+
static void copy_n_matching_alignment(benchmark::State& state) {
53+
const auto size = state.range(0);
54+
const vector<bool> source = createRandomVector(size);
55+
vector<bool> dest(size, false);
56+
57+
for (auto _ : state) {
58+
copy_n(source.cbegin() + 5, size - 5, dest.begin() + 5);
59+
}
60+
}
61+
62+
// Special benchmarks for single block corner case
63+
static void copy_n_both_single_blocks(benchmark::State& state) {
64+
const vector<bool> source = createRandomVector(50);
65+
vector<bool> dest(50, false);
66+
67+
const size_t length = 20;
68+
for (auto _ : state) {
69+
copy_n(source.cbegin() + 5, length, dest.begin() + 5);
70+
}
71+
}
72+
73+
static void copy_n_source_single_block(benchmark::State& state) {
74+
const vector<bool> source = createRandomVector(50);
75+
vector<bool> dest(50, false);
76+
77+
const size_t length = 20;
78+
for (auto _ : state) {
79+
copy_n(source.cbegin() + 5, length, dest.begin() + 25);
80+
}
81+
}
82+
83+
static void copy_n_dest_single_block(benchmark::State& state) {
84+
const vector<bool> source = createRandomVector(50);
85+
vector<bool> dest(50, false);
86+
87+
const size_t length = 20;
88+
for (auto _ : state) {
89+
copy_n(source.cbegin() + 25, length, dest.begin() + 5);
90+
}
91+
}
92+
93+
BENCHMARK(copy_n_block_aligned)->RangeMultiplier(64)->Range(64, 64 << 10);
94+
BENCHMARK(copy_n_source_missaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
95+
BENCHMARK(copy_n_dest_missaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
96+
BENCHMARK(copy_n_matching_alignment)->RangeMultiplier(64)->Range(64, 64 << 10);
97+
98+
BENCHMARK(copy_n_both_single_blocks);
99+
BENCHMARK(copy_n_source_single_block);
100+
BENCHMARK(copy_n_dest_single_block);
101+
102+
BENCHMARK_MAIN();
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <benchmark/benchmark.h>
5+
//
6+
#include <algorithm>
7+
#include <functional>
8+
#include <random>
9+
#include <vector>
10+
11+
using namespace std;
12+
13+
inline static vector<bool> createRandomVector(const size_t size) {
14+
static random_device rd;
15+
static mt19937 gen{random_device{}()};
16+
vector<bool> result(size);
17+
generate_n(result.begin(), size, [] { return bernoulli_distribution{0.5}(gen); });
18+
return result;
19+
}
20+
21+
static void move_block_aligned(benchmark::State& state) {
22+
const vector<bool> source = createRandomVector(state.range(0));
23+
vector<bool> dest(state.range(0), false);
24+
25+
for (auto _ : state) {
26+
move(source.cbegin(), source.cend(), dest.begin());
27+
}
28+
}
29+
30+
static void move_source_missaligned(benchmark::State& state) {
31+
const vector<bool> source = createRandomVector(state.range(0));
32+
vector<bool> dest(state.range(0), false);
33+
34+
for (auto _ : state) {
35+
move(source.cbegin() + 1, source.cend(), dest.begin());
36+
}
37+
}
38+
39+
static void move_dest_missaligned(benchmark::State& state) {
40+
const vector<bool> source = createRandomVector(state.range(0));
41+
vector<bool> dest(state.range(0), false);
42+
43+
for (auto _ : state) {
44+
move(source.cbegin(), source.cend() - 1, dest.begin() + 1);
45+
}
46+
}
47+
48+
// Special benchmark for matching char alignment
49+
static void move_matching_alignment(benchmark::State& state) {
50+
const vector<bool> source = createRandomVector(state.range(0));
51+
vector<bool> dest(state.range(0), false);
52+
53+
for (auto _ : state) {
54+
move(source.cbegin() + 5, source.cend(), dest.begin() + 5);
55+
}
56+
}
57+
58+
// Special benchmarks for single block corner case
59+
static void move_both_single_blocks(benchmark::State& state) {
60+
const vector<bool> source = createRandomVector(50);
61+
vector<bool> dest(50, false);
62+
63+
const size_t length = 20;
64+
for (auto _ : state) {
65+
move(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 5);
66+
}
67+
}
68+
69+
static void move_source_single_block(benchmark::State& state) {
70+
const vector<bool> source = createRandomVector(50);
71+
vector<bool> dest(50, false);
72+
73+
const size_t length = 20;
74+
for (auto _ : state) {
75+
move(source.cbegin() + 5, source.cbegin() + 5 + length, dest.begin() + 25);
76+
}
77+
}
78+
79+
static void move_dest_single_block(benchmark::State& state) {
80+
const vector<bool> source = createRandomVector(50);
81+
vector<bool> dest(50, false);
82+
83+
const size_t length = 20;
84+
for (auto _ : state) {
85+
move(source.cbegin() + 25, source.cbegin() + 25 + length, dest.begin() + 5);
86+
}
87+
}
88+
89+
BENCHMARK(move_block_aligned)->RangeMultiplier(64)->Range(64, 64 << 10);
90+
BENCHMARK(move_source_missaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
91+
BENCHMARK(move_dest_missaligned)->RangeMultiplier(64)->Range(64, 64 << 10);
92+
BENCHMARK(move_matching_alignment)->RangeMultiplier(64)->Range(64, 64 << 10);
93+
94+
BENCHMARK(move_both_single_blocks);
95+
BENCHMARK(move_source_single_block);
96+
BENCHMARK(move_dest_single_block);
97+
98+
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)