Skip to content

Commit

Permalink
Add benchmarks and use size_t as value_type
Browse files Browse the repository at this point in the history
  • Loading branch information
rhalbersma committed Feb 5, 2024
1 parent c91bdd5 commit 7b429ab
Show file tree
Hide file tree
Showing 21 changed files with 467 additions and 276 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ target_compile_features(
)

include(CTest)
add_subdirectory(benchmark)
add_subdirectory(test)
105 changes: 105 additions & 0 deletions benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Copyright Rein Halbersma 2014-2024.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

set(Boost_USE_STATIC_LIBS ON)
find_package(Boost REQUIRED)

find_package(benchmark REQUIRED)

set(cxx_compile_definitions
BOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE
BOOST_ALL_NO_LIB
BOOST_TEST_MAIN
$<$<CXX_COMPILER_ID:MSVC>:
_SCL_SECURE_NO_WARNINGS
>
)

set(cxx_compile_options_warnings
$<$<CXX_COMPILER_ID:MSVC>:
/W4
/permissive-
/WX
>
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:GNU>>:
-Werror
-pedantic-errors
>
$<$<CXX_COMPILER_ID:Clang>:
-Weverything
-Wno-unknown-warning-option # forward compatibility for new Clang warnings
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-c++20-compat
-Wno-c++20-compat-pedantic
-Wno-ctad-maybe-unsupported
-Wno-unsafe-buffer-usage
-Wno-disabled-macro-expansion # triggered by Boost.Test
-Wno-global-constructors # triggered by Boost.Test
-Wno-used-but-marked-unused # triggered by Boost.Test
-Wno-zero-as-null-pointer-constant # triggered by Boost.Test
-Wno-padded # only affects performance
>
$<$<CXX_COMPILER_ID:GNU>:
-Wall
-Wextra
-Wpedantic
-Wconversion # NOTE: possibly triggered by range-v3 views::zip overload resolution
-Wshadow
-Wsign-compare
-Wsign-conversion
-Wsign-promo
>
$<$<AND:$<CXX_COMPILER_ID:GNU>,$<CONFIG:Release>>:
-Wno-array-bounds # triggered by Boost.DynamicBitset for gcc >= 12 in Release mode
-Wno-stringop-overflow # triggered by Boost.DynamicBitset for gcc >= 12 in Release mode
>
)

set(cxx_compile_options_optimization
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:GNU>>:
-DNDEBUG -Ofast -march=native
>
)

set(cxx_compile_options_mbig_obj
$<$<AND:$<CXX_COMPILER_ID:GNU>,$<PLATFORM_ID:Windows>>:
-Wa,-mbig-obj
>
)

set(current_include_dir ${CMAKE_CURRENT_SOURCE_DIR}/include)
set(current_src_dir ${CMAKE_CURRENT_SOURCE_DIR}/src)
file(GLOB_RECURSE targets RELATIVE ${current_src_dir} *.cpp)

cmake_path(GET CMAKE_CURRENT_SOURCE_DIR FILENAME target_source_dir)
foreach(t ${targets})
cmake_path(GET t PARENT_PATH target_parent_path)
cmake_path(GET t STEM target_stem )
string(REPLACE "/" "." target_id ${target_source_dir}/${target_parent_path}/${target_stem})
string(REGEX REPLACE "^[.]" "" target_id ${target_id})

add_executable(${target_id} src/${t})

target_link_libraries(
${target_id} PRIVATE
${CMAKE_PROJECT_NAME}
benchmark::benchmark
)

target_compile_definitions(
${target_id} PRIVATE
${cxx_compile_definitions}
)

target_compile_options(
${target_id} PRIVATE
${cxx_compile_options_warnings}
${cxx_compile_options_optimization}
${cxx_compile_options_mbig_obj}
)

add_test(${target_id} ${target_id})
endforeach()
53 changes: 53 additions & 0 deletions benchmark/src/bitset/sieve.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright Rein Halbersma 2014-2024.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#include <aux/bitset/sieve.hpp> // filter_twins, sift_primes
#include <ext/boost/dynamic_bitset.hpp> // dynamic_bitset
#include <ext/std/bitset.hpp> // bitset
#include <ext/std/ranges.hpp> // as_set
#include <xstd/bitset.hpp> // bitset
#include <xstd/bit_set.hpp> // bit_set
#include <benchmark/benchmark.h> // DoNotOptimize, BENCHMARK_TEMPLATE1, BENCHMARK_MAIN

constexpr auto N = 1'000'000uz;

template<class T>
static void bm_sift_primes(benchmark::State& state) {
for (auto _ : state) {
benchmark::DoNotOptimize(xstd::sift_primes<T>(N));
}
}

template<class T>
static void bm_sift_primes2(benchmark::State& state) {
for (auto _ : state) {
benchmark::DoNotOptimize(xstd::sift_primes2<T>(N));
}
}

template<class T>
static void bm_filter_twins(benchmark::State& state) {
auto const primes = xstd::sift_primes<T>(N);
for (auto _ : state) {
benchmark::DoNotOptimize(xstd::filter_twins(primes));
}
}

BENCHMARK_TEMPLATE1(bm_sift_primes, boost::dynamic_bitset<>);
BENCHMARK_TEMPLATE1(bm_sift_primes, std::bitset<N>);
BENCHMARK_TEMPLATE1(bm_sift_primes, xstd::bitset<N>);
BENCHMARK_TEMPLATE1(bm_sift_primes, xstd::bit_set<N>);

BENCHMARK_TEMPLATE1(bm_sift_primes2, boost::dynamic_bitset<>);
BENCHMARK_TEMPLATE1(bm_sift_primes2, std::bitset<N>);
BENCHMARK_TEMPLATE1(bm_sift_primes2, xstd::bitset<N>);
BENCHMARK_TEMPLATE1(bm_sift_primes2, xstd::bit_set<N>);

BENCHMARK_TEMPLATE1(bm_filter_twins, boost::dynamic_bitset<>);
BENCHMARK_TEMPLATE1(bm_filter_twins, std::bitset<N>);
BENCHMARK_TEMPLATE1(bm_filter_twins, xstd::bitset<N>);
BENCHMARK_TEMPLATE1(bm_filter_twins, xstd::bit_set<N>);

BENCHMARK_MAIN();
48 changes: 48 additions & 0 deletions benchmark/src/set/sieve.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright Rein Halbersma 2014-2024.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#include <aux/set/sieve.hpp> // filter_twins, sift_primes
#include <xstd/bit_set.hpp> // bit_set
#include <boost/container/flat_set.hpp> // flat_set
#include <set> // set
#include <benchmark/benchmark.h> // DoNotOptimize, BENCHMARK_TEMPLATE1, BENCHMARK_MAIN

constexpr auto N = 10'000uz;

template<class T>
static void bm_sift_primes(benchmark::State& state) {
for (auto _ : state) {
benchmark::DoNotOptimize(xstd::sift_primes<T>(N));
}
}

template<class T>
static void bm_sift_primes2(benchmark::State& state) {
for (auto _ : state) {
benchmark::DoNotOptimize(xstd::sift_primes2<T>(N));
}
}

template<class T>
static void bm_filter_twins(benchmark::State& state) {
auto const primes = xstd::sift_primes<T>(N);
for (auto _ : state) {
benchmark::DoNotOptimize(xstd::filter_twins(primes));
}
}

BENCHMARK_TEMPLATE1(bm_sift_primes, std::set<std::size_t>);
BENCHMARK_TEMPLATE1(bm_sift_primes, boost::container::flat_set<std::size_t>);
BENCHMARK_TEMPLATE1(bm_sift_primes, xstd::bit_set<N>);

BENCHMARK_TEMPLATE1(bm_sift_primes2, std::set<std::size_t>);
BENCHMARK_TEMPLATE1(bm_sift_primes2, boost::container::flat_set<std::size_t>);
BENCHMARK_TEMPLATE1(bm_sift_primes2, xstd::bit_set<N>);

BENCHMARK_TEMPLATE1(bm_filter_twins, std::set<std::size_t>);
BENCHMARK_TEMPLATE1(bm_filter_twins, boost::container::flat_set<std::size_t>);
BENCHMARK_TEMPLATE1(bm_filter_twins, xstd::bit_set<N>);

BENCHMARK_MAIN();
32 changes: 24 additions & 8 deletions test/include/bitset/sieve.hpp → include/aux/bitset/sieve.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
// http://www.boost.org/LICENSE_1_0.txt)

#include <boost/dynamic_bitset_fwd.hpp> // dynamic_bitset
#include <cstddef> // size_t
#include <ranges> // iota, stride, take_while
#include <type_traits> // conditional_t

namespace xstd {

template<int N, std::unsigned_integral Block>
requires (N >= 0)
template<std::size_t N, std::unsigned_integral Block>
class bit_set;

template<class C>
Expand All @@ -31,7 +31,7 @@ auto size(C const& c)
template<class C>
struct generate_empty
{
auto operator()(auto) const
auto operator()(std::size_t) const
{
return C();
}
Expand All @@ -40,7 +40,7 @@ struct generate_empty
template<std::unsigned_integral Block, class Allocator>
struct generate_empty<boost::dynamic_bitset<Block, Allocator>>
{
auto operator()(boost::dynamic_bitset<Block, Allocator>::size_type n) const
auto operator()(std::size_t n) const
{
return boost::dynamic_bitset<Block, Allocator>(n);
}
Expand All @@ -52,7 +52,7 @@ auto fill(C& empty)
empty.set();
}

template<int N, std::unsigned_integral Block>
template<std::size_t N, std::unsigned_integral Block>
auto fill(xstd::bit_set<N, Block>& empty)
{
empty.fill();
Expand All @@ -64,8 +64,8 @@ auto sift(C& primes, std::size_t m)
primes.reset(m);
}

template<int N, std::unsigned_integral Block>
auto sift(xstd::bit_set<N, Block>& primes, int m)
template<std::size_t N, std::unsigned_integral Block>
auto sift(xstd::bit_set<N, Block>& primes, std::size_t m)
{
primes.pop(m);
}
Expand All @@ -84,7 +84,7 @@ struct generate_candidates
};

template<class C>
auto sift_primes(std::conditional_t<legacy_bitset<C>, std::size_t, int> n)
auto sift_primes(std::size_t n)
{
auto primes = generate_candidates<C>()(n);
for (auto p
Expand All @@ -101,6 +101,22 @@ auto sift_primes(std::conditional_t<legacy_bitset<C>, std::size_t, int> n)
return primes;
}

template<class C>
auto sift_primes2(std::size_t n)
{
auto primes = generate_candidates<C>()(n);
for (auto p : primes) {
auto const p_squared = p * p;
if (p_squared > n) {
break;
}
for (auto m = p_squared; m < n; m += p) {
sift(primes, m);
}
}
return primes;
}

template<class C>
auto filter_twins(C const& primes)
{
Expand Down
24 changes: 20 additions & 4 deletions test/include/set/sieve.hpp → include/aux/set/sieve.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@
namespace xstd {

template<class C>
auto sift(C& primes, int m)
auto sift(C& primes, std::size_t m)
{
primes.erase(m);
}

template<class C>
struct generate_candidates
{
auto operator()(int n) const
auto operator()(std::size_t n) const
{
return std::views::iota(2, n) | std::ranges::to<C>();
return std::views::iota(2uz, n) | std::ranges::to<C>();
}
};

template<class C>
auto sift_primes(int n)
auto sift_primes(std::size_t n)
{
auto primes = generate_candidates<C>()(n);
for (auto p
Expand All @@ -42,6 +42,22 @@ auto sift_primes(int n)
return primes;
}

template<class C>
auto sift_primes2(std::size_t n)
{
auto primes = generate_candidates<C>()(n);
for (auto p : primes) {
auto const p_squared = p * p;
if (p_squared > n) {
break;
}
for (auto m = p_squared; m < n; m += p) {
sift(primes, m);
}
}
return primes;
}

template<class C>
auto filter_twins(C const& primes)
{
Expand Down
Loading

0 comments on commit 7b429ab

Please sign in to comment.