Skip to content

Commit 45c89d7

Browse files
authored
Add sal\sar benchmarks (#3)
1 parent f6b4b74 commit 45c89d7

File tree

3 files changed

+133
-15
lines changed

3 files changed

+133
-15
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
cmake_minimum_required(VERSION 3.16)
55
project(bits VERSION 0.1.0 LANGUAGES CXX)
66

7+
set(CMAKE_CXX_STANDARD 20)
8+
set(CXX_EXTENSIONS OFF)
9+
710
add_library(bits INTERFACE)
811
add_library(bits::bits ALIAS bits)
912
add_library(org::ttldtor::bits::bits ALIAS bits)

tests/CMakeLists.txt

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,26 @@
33

44
include(FetchContent)
55
FetchContent_Declare(
6-
doctest
7-
GIT_REPOSITORY https://github.com/doctest/doctest.git
8-
GIT_TAG v2.4.12)
6+
doctest
7+
GIT_REPOSITORY https://github.com/doctest/doctest.git
8+
GIT_TAG v2.4.12)
99
FetchContent_MakeAvailable(doctest)
1010

1111
FetchContent_Declare(
12-
nanobench
13-
GIT_REPOSITORY https://github.com/martinus/nanobench.git
14-
GIT_TAG v4.1.0
15-
GIT_SHALLOW TRUE)
12+
nanobench
13+
GIT_REPOSITORY https://github.com/martinus/nanobench.git
14+
GIT_TAG v4.1.0
15+
GIT_SHALLOW TRUE)
1616
FetchContent_MakeAvailable(nanobench)
1717

1818
add_executable(bits_tests
19-
main.cpp
20-
bits.cpp
19+
main.cpp
20+
bits.cpp
21+
)
22+
23+
set_target_properties(bits_tests PROPERTIES
24+
CXX_STANDARD 20
25+
CXX_EXTENSIONS OFF
2126
)
2227

2328
target_link_libraries(bits_tests PRIVATE bits::bits)
@@ -30,7 +35,22 @@ add_executable(bits_bench
3035
bench.cpp
3136
)
3237

38+
set_target_properties(bits_bench PROPERTIES
39+
CXX_STANDARD 20
40+
CXX_EXTENSIONS OFF
41+
)
42+
3343
target_link_libraries(bits_bench PRIVATE bits::bits nanobench)
3444
target_include_directories(bits_bench PRIVATE ${doctest_SOURCE_DIR})
3545

36-
add_test(NAME bits_bench COMMAND bits_bench)
46+
if (CMAKE_CONFIGURATION_TYPES)
47+
set_property(TARGET bits_bench PROPERTY EXCLUDE_FROM_DEFAULT_BUILD_Debug TRUE)
48+
add_test(NAME bits_bench COMMAND bits_bench)
49+
set_tests_properties(bits_bench PROPERTIES DISABLED "$<CONFIG:Debug>")
50+
else ()
51+
if (CMAKE_BUILD_TYPE STREQUAL "Release")
52+
add_test(NAME bits_bench COMMAND bits_bench)
53+
else ()
54+
set_property(TARGET bits_bench PROPERTY EXCLUDE_FROM_ALL TRUE)
55+
endif ()
56+
endif ()

tests/bench.cpp

Lines changed: 100 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,107 @@
1212
#include <limits>
1313

1414
using namespace org::ttldtor::bits;
15+
using namespace std::literals;
1516

1617
// NOLINTNEXTLINE
1718

18-
TEST_CASE("tutorial_fast_v2") {
19-
uint64_t x = 1;
20-
ankerl::nanobench::Bench().run("++x", [&]() {
21-
ankerl::nanobench::doNotOptimizeAway(x += 1);
22-
});
19+
TEST_CASE("bench_sal_sar_vs_builtin") {
20+
constexpr size_t N = 1u << 15;
21+
22+
std::mt19937_64 rng{0xB00B00};
23+
// For comparison with builtin << we use unsigned types and non-negative shifts
24+
std::uniform_int_distribution<uint32_t> u32dist{0u, 0x7FFF'FFFFu};
25+
std::uniform_int_distribution<uint64_t> u64dist{0ull, (1ull << 50)};
26+
std::uniform_int_distribution<unsigned> shldist{0u, 63u};
27+
28+
// For comparison with builtin >> we use signed types and non-negative shifts
29+
std::uniform_int_distribution<int32_t> s32dist{-(1 << 29), (1 << 29)};
30+
std::uniform_int_distribution<int64_t> s64dist{-(1ll << 50), (1ll << 50)};
31+
std::uniform_int_distribution<unsigned> shrdist{0u, 63u};
32+
33+
std::vector<uint32_t> u32(N);
34+
std::vector<unsigned> shl32(N);
35+
std::vector<uint64_t> u64(N);
36+
std::vector<unsigned> shl64(N);
37+
38+
std::vector<int32_t> s32(N);
39+
std::vector<unsigned> shr32(N);
40+
std::vector<int64_t> s64(N);
41+
std::vector<unsigned> shr64(N);
42+
43+
for (size_t i = 0; i < N; ++i) {
44+
u32[i] = u32dist(rng);
45+
shl32[i] = shldist(rng) % 32;
46+
u64[i] = u64dist(rng);
47+
shl64[i] = shldist(rng) % 64;
48+
49+
s32[i] = s32dist(rng);
50+
shr32[i] = shrdist(rng) % 32;
51+
s64[i] = s64dist(rng);
52+
shr64[i] = shrdist(rng) % 64;
53+
}
54+
55+
auto createBench = [&](auto title) {
56+
ankerl::nanobench::Bench bench;
57+
58+
bench.title(title)
59+
.unit("op")
60+
.batch(N)
61+
.warmup(100)
62+
.minEpochTime(150ms)
63+
.minEpochIterations(60000)
64+
.relative(true)
65+
.performanceCounters(true);
66+
67+
return bench;
68+
};
69+
70+
auto runSalBench = [&](auto& bench, const auto& typeName, const auto& values, const auto& shifts) {
71+
bench.run("builtin << ("s + typeName + ")", [&] {
72+
uint32_t acc = 0;
73+
for (size_t i = 0; i < N; ++i) {
74+
acc ^= values[i] << shifts[i];
75+
}
76+
ankerl::nanobench::doNotOptimizeAway(acc);
77+
});
78+
79+
bench.run("sal<"s + typeName + ">", [&] {
80+
uint32_t acc = 0;
81+
for (size_t i = 0; i < N; ++i) {
82+
acc ^= sal(values[i], shifts[i]);
83+
}
84+
ankerl::nanobench::doNotOptimizeAway(acc);
85+
});
86+
};
87+
88+
89+
auto runSarBench = [&](auto& bench, const auto& typeName, const auto& values, const auto& shifts) {
90+
bench.run("builtin >> ("s + typeName + ")", [&] {
91+
uint32_t acc = 0;
92+
for (size_t i = 0; i < N; ++i) {
93+
acc ^= values[i] >> shifts[i];
94+
}
95+
ankerl::nanobench::doNotOptimizeAway(acc);
96+
});
97+
98+
bench.run("sar<"s + typeName + ">", [&] {
99+
uint32_t acc = 0;
100+
for (size_t i = 0; i < N; ++i) {
101+
acc ^= sar(values[i], shifts[i]);
102+
}
103+
ankerl::nanobench::doNotOptimizeAway(acc);
104+
});
105+
};
106+
107+
auto salBench1 = createBench("Compare sal vs builtin << (uint32_t)");
108+
runSalBench(salBench1, "uint32_t", u32, shl32);
109+
110+
auto salBench2 = createBench("Compare sal vs builtin << (uint64_t)");
111+
runSalBench(salBench2, "uint64_t", u64, shl64);
112+
113+
auto sarBench1 = createBench("Compare sar vs builtin >> (uint32_t)");
114+
runSarBench(sarBench1, "uint32_t", u32, shl32);
115+
116+
auto sarBench2 = createBench("Compare sar vs builtin >> (uint64_t)");
117+
runSarBench(sarBench2, "uint64_t", u64, shl64);
23118
}

0 commit comments

Comments
 (0)