Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
69d1c2a
Improved messages for option settings.
c-bebop Oct 31, 2024
07af345
Pedantic warnings are errors option.
c-bebop Oct 31, 2024
1959415
Setting target properties in one place incl. c++ std and target indep…
c-bebop Oct 31, 2024
5fe4e88
Scope explicitly.
c-bebop Oct 31, 2024
d3c9560
TODO: init value when GCC compiles showing warning as error.
c-bebop Oct 31, 2024
3348183
Use signed literals for assignments.
c-bebop Nov 8, 2024
277ff4b
Initialize j: fixing warning of maybe uninitialized variable.
c-bebop Nov 8, 2024
95775c5
Revise comment on when to use a hash table.
c-bebop Nov 8, 2024
39cda54
Passed bsize is const.
c-bebop Mar 24, 2025
87725d3
cache line size ist consexpr
c-bebop Mar 24, 2025
d01f87d
Compare against signed literal: Keeps value type from being interpret…
c-bebop Mar 24, 2025
d53f6a4
Include exception for std::terminate().
c-bebop Mar 24, 2025
0536c50
Merge branch 'main' into super_pedantic
c-bebop Mar 25, 2025
324c9cf
Being extra pedanctic also for dhb test target.
c-bebop Mar 25, 2025
1a7a241
Fix vec tests using uint32_t as indices (rename file to _test.cpp).
c-bebop Mar 25, 2025
d2f72c6
Remove unused variable.
c-bebop Mar 25, 2025
2284e1e
Fix submatrix test not initializing edge data correctly, renaming tes…
c-bebop Mar 25, 2025
cc7da5d
Fix signed / unsigned comparison warning: indices are unsigned integers.
c-bebop Mar 25, 2025
1a8c797
Remove unused variables from matrix tests.
c-bebop Mar 25, 2025
a458aba
Fix unsigned / signed comparisons in batcher.
c-bebop Mar 25, 2025
5514ebf
Remove unused variables.
c-bebop Mar 25, 2025
75027ea
Wrap include of mman.h with pre-processor if clause checking for syst…
c-bebop Mar 25, 2025
dcb2202
Remove redundant comments.
c-bebop Mar 25, 2025
fb9c56a
Remove redundant semicolon?
c-bebop Mar 27, 2025
ef2edc9
Include numeric for std::accumulate().
c-bebop Mar 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,9 @@ include(GNUInstallDirs)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)


# Configure the option whether you want to use the systems own allocater
# DHB_WITH_SYSTEM_ALLOCATOR=ON
# or our own written allocator strategy
# DHB_WITH_SYSTEM_ALLOCATOR=OFF
option(DHB_WITH_SYSTEM_ALLOCATOR "Use DHB System Allocator" OFF)
option(DHB_WITH_64BIT_IDS "Use 64 bit IDs." OFF)
option(DHB_WARNINGS_AS_ERRORS "Sets warning level high, treats warnings as errors ." OFF)

add_library(dhb STATIC)

Expand All @@ -42,18 +38,21 @@ target_sources(${PROJECT_NAME}
# Options check and set definitions
# ===================================
if (DHB_WITH_SYSTEM_ALLOCATOR)
MESSAGE(STATUS "Using DHB System Allocator.")
MESSAGE(STATUS "DHB uses system allocator.")
target_compile_definitions(dhb PUBLIC -DDHB_SYSTEM_ALLOCATOR)
endif()

if (DHB_WITH_64BIT_IDS)
MESSAGE(STATUS "Using 64 bit IDs.")
MESSAGE(STATUS "DHB uses 64 bit vertex IDs.")
target_compile_definitions(dhb PUBLIC -DDHB_64BIT_IDS)
else()
MESSAGE(STATUS "Using 32 bit IDs.")
MESSAGE(STATUS "DHB uses 32 bit vertex IDs.")
endif()

set_property(TARGET dhb PROPERTY POSITION_INDEPENDENT_CODE ON)
if (DHB_WARNINGS_AS_ERRORS)
MESSAGE(STATUS "DHB is extra pedantic, throws errors on warnings.")
target_compile_options(dhb PRIVATE -Werror -Wall -Wextra -Wpedantic -Wmaybe-uninitialized)
endif()

find_package(OpenMP)
# Thanks to NetworKit for the following OpenMP code looking or OpenMP in the
Expand Down Expand Up @@ -95,9 +94,6 @@ if(NOT OpenMP_FOUND)
endif()
target_link_libraries(${PROJECT_NAME} PUBLIC OpenMP::OpenMP_CXX)

# Be extra pedantic about warnings!
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror)

target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
Expand Down Expand Up @@ -128,8 +124,10 @@ set_target_properties(${PROJECT_NAME}::${PROJECT_NAME} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
)

set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "${public_headers}")
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d")
set_target_properties(dhb PROPERTIES CXX_STANDARD 17)
set_target_properties(dhb PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(dhb PROPERTIES DEBUG_POSTFIX "d")
set_target_properties(dhb PROPERTIES PUBLIC_HEADER "${public_headers}")

# ===================================
# Make a Configuration Package
Expand Down Expand Up @@ -192,11 +190,16 @@ if (DHB_BUILD_TESTS)
test/graph_io.h
test/graph_io.cpp
test/matrix_test.cpp
test/vec.cpp
test/vec_test.cpp
test/block.cpp
test/submatrix.cpp
test/submatrix_test.cpp
)

if (DHB_WARNINGS_AS_ERRORS)
MESSAGE(STATUS "DHB test is extra pedantic, throws errors on warnings.")
target_compile_options(dhb_test PRIVATE -Werror -Wall -Wextra -Wpedantic -Wmaybe-uninitialized)
endif()

target_link_libraries(dhb_test PRIVATE dhb Catch2::Catch2WithMain OpenMP::OpenMP_CXX)

install(
Expand Down
20 changes: 9 additions & 11 deletions include/dhb/batcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ template <typename T> class BatchParallelizer {
public:
template <typename Iterator, typename GetSourceF, typename Cmp, typename F>
void operator()(Iterator begin, Iterator end, GetSourceF&& get_source_f, Cmp cmp, F func) {
int const t_count = omp_get_max_threads();
uint32_t const t_count = omp_get_max_threads();
size_t const n = end - begin;
if (t_count == 1 || n < t_count) {
for (auto it = begin; it != end; ++it)
Expand All @@ -90,7 +90,7 @@ template <typename T> class BatchParallelizer {

template <typename Iterator, typename K, typename F>
void apply(Iterator begin, Iterator end, K key, F func) {
size_t const t_count = omp_get_max_threads();
uint32_t const t_count = omp_get_max_threads();
size_t const n = end - begin;
if (t_count == 1 || n < t_count) {
for (auto it = begin; it != end; ++it)
Expand All @@ -104,7 +104,7 @@ template <typename T> class BatchParallelizer {
#pragma omp parallel num_threads(t_count)
{
size_t const t = omp_get_thread_num();
assert(omp_get_num_threads() == t_count);
assert(uint32_t(omp_get_num_threads()) == t_count);

auto counts_of_thread = [&](int ct) -> uint64_t* {
return &m_batch_counts[ct * (t_count + 1)];
Expand Down Expand Up @@ -156,7 +156,6 @@ template <typename T> class BatchParallelizer {
auto j_end = ot_counts[t + 1];
for (size_t j = j_begin; j < j_end; ++j) {
auto i = m_batch_slots[j];
auto edge = *(begin + i);
func(*(begin + i));
}
local_count += j_end - j_begin;
Expand All @@ -165,7 +164,7 @@ template <typename T> class BatchParallelizer {
}

template <typename Iterator, typename K> void distribute(Iterator begin, Iterator end, K key) {
int const t_count = omp_get_num_threads();
uint32_t const t_count = omp_get_num_threads();
size_t const n = end - begin;
if (t_count == 1 || n < t_count) {
return;
Expand All @@ -177,7 +176,7 @@ template <typename T> class BatchParallelizer {
m_batch_slots.resize(n);
}

auto t = omp_get_thread_num();
uint32_t t = omp_get_thread_num();

auto counts_of_thread = [&](int ct) -> uint64_t* {
return &m_batch_counts[ct * (t_count + 1)];
Expand All @@ -192,7 +191,7 @@ template <typename T> class BatchParallelizer {
// First, perform a local counting sort to sort updates according to associated threads.

auto t_counts = counts_of_thread(t);
for (int at = 0; at < t_count; ++at)
for (uint32_t at = 0; at < t_count; ++at)
t_counts[at] = 0;

for (size_t i = i_begin; i < i_end; ++i) {
Expand All @@ -202,7 +201,7 @@ template <typename T> class BatchParallelizer {
}

uint64_t psum = 0;
for (int at = 0; at < t_count; ++at) {
for (uint32_t at = 0; at < t_count; ++at) {
psum += t_counts[at];
t_counts[at] = i_begin + psum;
}
Expand All @@ -223,7 +222,7 @@ template <typename T> class BatchParallelizer {
}

template <typename Iterator, typename F> void map(Iterator begin, Iterator end, F func) {
int const t_count = omp_get_num_threads();
uint32_t const t_count = omp_get_num_threads();
size_t const n = end - begin;
if (t_count == 1 || n < t_count) {
#pragma omp master
Expand All @@ -243,13 +242,12 @@ template <typename T> class BatchParallelizer {
};

uint64_t local_count = 0;
for (int ot = 0; ot < t_count; ++ot) {
for (uint32_t ot = 0; ot < t_count; ++ot) {
auto ot_counts = counts_of_thread(ot);
auto j_begin = ot_counts[t];
auto j_end = ot_counts[t + 1];
for (size_t j = j_begin; j < j_end; ++j) {
auto i = m_batch_slots[j];
auto edge = *(begin + i);
func(*(begin + i));
}
local_count += j_end - j_begin;
Expand Down
33 changes: 19 additions & 14 deletions include/dhb/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,31 @@

#include <algorithm>
#include <cassert>
#include <exception>
#include <mutex>
#include <sys/mman.h>
#include <vector>

#ifndef DHB_SYSTEM_ALLOCATOR
#include <sys/mman.h>
#endif

namespace dhb {

class BlockHandle;
class BlockArray;

using index_type = size_t;
inline index_type illegalIndex() { return static_cast<index_type>(-1); };
inline index_type tombstoneIndex() { return static_cast<index_type>(-2); };
inline index_type illegalIndex() { return static_cast<index_type>(-1); }
inline index_type tombstoneIndex() { return static_cast<index_type>(-2); }

// TODO: This could take the entry size into account.
inline bool uses_htab(size_t bsize) {
const size_t cache_line = 64;
// Each entry is typically 16 bytes or so.
// Preliminary experiments how that using the hash index is only useful if the block becomes
// larger than several cache lines (approx. 16 or so).
// Hence, the following is a reasonably good heuristic:
return 16 * bsize > 16 * cache_line;
inline bool uses_htab(size_t const bsize) {
size_t constexpr cache_line = 64;
// Each entry is typically 16 bytes or so. Preliminary experiments show that
// using the hash index is only useful if the block becomes larger than
// several cache lines (approx. 16 or so). Hence, the following is a
// reasonably good heuristic:
return 16u * bsize > 16u * cache_line;
}

// Taken from https://stackoverflow.com/a/12996028.
Expand Down Expand Up @@ -416,7 +420,7 @@ template <typename E> class BlockState {
if (uses_htab(m_bsize)) {
index_type* htab = m_htab;
auto h = hash_node(v);
index_type j;
index_type j = 0u;
index_type ts = illegalIndex();
for (index_type i = 0; true; ++i) {
if (i == m_bsize) {
Expand All @@ -437,8 +441,9 @@ template <typename E> class BlockState {
}

// If we did hit a tombstone, insert at the tombstone.
if (ts != illegalIndex())
if (ts != illegalIndex()) {
j = ts;
}

// Insert into the adjacency list.
auto i = m_degree++;
Expand Down Expand Up @@ -521,7 +526,7 @@ template <typename E> class BlockState {
} else {
// Find the index.
index_type iv;
for (iv = 0; iv < m_degree; ++iv)
for (iv = 0u; iv < m_degree; ++iv)
if (m_entries[iv].vertex == v)
break;

Expand All @@ -530,7 +535,7 @@ template <typename E> class BlockState {
return false;

// Swap with the last entry.
if (iv + 1 != m_degree)
if (iv + 1u != m_degree)
m_entries[iv] = m_entries[m_degree - 1];

// Remove the last entry.
Expand Down
3 changes: 1 addition & 2 deletions include/dhb/dynamic_hashed_blocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <functional>
#include <memory>
#include <mutex>
#include <numeric>
#include <omp.h>
#include <vector>

Expand Down Expand Up @@ -55,7 +56,6 @@ template <typename E> struct Matrix {
BlockState<E> new_block{new_bhandle, state};
auto result = new_block.insert(v, ed);

auto old_block = std::move(m_graph->m_vertices[m_source]);
auto old_bhandle = m_graph->m_handles[m_source];
m_graph->m_vertices[m_source] = std::move(new_block);
m_graph->m_handles[m_source] = new_bhandle;
Expand Down Expand Up @@ -174,7 +174,6 @@ template <typename E> struct Matrix {
auto new_bhandle = m_manager->allocate_block(degree);
BlockState<E> new_block{new_bhandle, associated_block};

auto old_block = std::move(m_vertices[u]);
auto old_bhandle = m_handles[u];
m_vertices[u] = std::move(new_block);
m_handles[u] = new_bhandle;
Expand Down
1 change: 0 additions & 1 deletion include/dhb/vec.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ template <typename E> struct Vec {
BlockState<E> new_block{new_bhandle, state};
auto result = new_block.insert(u, ed);

auto old_block = std::move(m_state);
auto old_bhandle = m_handle;
m_state = std::move(new_block);
m_handle = new_bhandle;
Expand Down
11 changes: 0 additions & 11 deletions test/matrix_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,6 @@ TEST_CASE("Matrix") {
Edges new_edges{e89_14, e89_8, e89_13_update};

auto cmp = [](Edge const& a, Edge const& b) { return a.source < b.source; };
auto key = [](Edge e) { return e.source; };
auto fun = [&](Edge e) {
std::tuple<dhb::BlockState<dhb::EdgeData>::iterator, bool> insertion_result =
m.neighbors(e.source).insert(e.target.vertex, e.target.data);
Expand Down Expand Up @@ -306,7 +305,6 @@ TEST_CASE("Matrix") {
Matrix<EdgeData> m(graph::vertex_count(edges));

auto cmp = [](Edge const& a, Edge const& b) { return a.source < b.source; };
auto key = [](Edge e) { return e.source; };
auto fun = [&](Edge e) { m.neighbors(e.source).insert(e.target.vertex, e.target.data); };
auto get_edge_f = [](Edge const& e) { return e.source; };
BatchParallelizer<Edge> par;
Expand All @@ -318,7 +316,6 @@ TEST_CASE("Matrix") {
Edges new_edges{e89_14, e89_8};

auto cmp2 = [](Edge const& a, Edge const& b) { return a.source < b.source; };
auto key2 = [](Edge e) { return e.source; };
par(new_edges.begin(), new_edges.end(), std::move(get_edge_f), std::move(cmp2),
[&](Edge e) { m.neighbors(e.source).insert(e.target.vertex, e.target.data); });

Expand Down Expand Up @@ -351,7 +348,6 @@ TEST_CASE("Matrix") {
Edges new_edges{e89_14, e89_8};

auto cmp2 = [](Edge const& a, Edge const& b) { return a.source < b.source; };
auto key2 = [](Edge e) { return e.source; };

par(new_edges.begin(), new_edges.end(), std::move(get_edge_f), std::move(cmp2),
[&](Edge e) { m.neighbors(e.source).insert(e.target.vertex, e.target.data); });
Expand All @@ -372,9 +368,7 @@ TEST_CASE("Matrix") {

Matrix<EdgeData> m(graph::vertex_count(edges));

auto cmp = [](Edge const& a, Edge const& b) { return a.source < b.source; };
auto key = [](Edge e) { return e.source; };
auto fun = [&](Edge e) { m.neighbors(e.source).insert(e.target.vertex, e.target.data); };
auto get_edge_f = [](Edge const& e) { return e.source; };
BatchParallelizer<Edge> par;

Expand All @@ -401,7 +395,6 @@ TEST_CASE("Matrix") {
Edges new_edges{e89_14, e89_8};

auto cmp2 = [](Edge const& a, Edge const& b) { return a.source < b.source; };
auto key2 = [](Edge e) { return e.source; };

par(new_edges.begin(), new_edges.end(), std::move(get_edge_f), std::move(cmp2),
[&](Edge e) { m.neighbors(e.source).insert(e.target.vertex, e.target.data); });
Expand All @@ -423,7 +416,6 @@ TEST_CASE("Matrix") {
Matrix<EdgeData> m(graph::vertex_count(edges));

auto cmp = [](Edge const& a, Edge const& b) { return a.source < b.source; };
auto key = [](Edge e) { return e.source; };
auto get_edge_f = [](Edge const& e) { return e.source; };

BatchParallelizer<Edge> par;
Expand All @@ -437,9 +429,6 @@ TEST_CASE("Matrix") {

Edges new_edges{e89_14, e89_8, e89_13_update};

auto cmp2 = [](Edge const& a, Edge const& b) { return a.source < b.source; };
auto key2 = [](Edge e) { return e.source; };

par(new_edges.begin(), new_edges.end(), std::move(get_edge_f), std::move(cmp), [&](Edge e) {
std::tuple<dhb::BlockState<dhb::EdgeData>::iterator, bool> insertion_result =
m.neighbors(e.source).insert(e.target.vertex, e.target.data);
Expand Down
6 changes: 3 additions & 3 deletions test/submatrix.cpp → test/submatrix_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ class TestMatrix {
// [ 13 | 4 | 0 ]
// clang-format off
dhb::Edges edges_a = {
{0, Tar{0, ED{1.0}}}, {0, Tar{1, ED{3.0}}}, {0, Tar{2, ED{0.0}}},
{1, Tar{0, ED{4.0}}}, {1, Tar{1, ED{5.0}}}, {1, Tar{2, ED{8.0}}},
{2, Tar{0, ED{13.0}}}, {2, Tar{1, ED{4.0}}}, {2, Tar{2, ED{0.0}}},
{0, Tar{0, ED{1.0, 0}}}, {0, Tar{1, ED{3.0, 0}}}, {0, Tar{2, ED{0.0, 0}}},
{1, Tar{0, ED{4.0, 0}}}, {1, Tar{1, ED{5.0, 0}}}, {1, Tar{2, ED{8.0, 0}}},
{2, Tar{0, ED{13.0, 0}}}, {2, Tar{1, ED{4.0, 0}}}, {2, Tar{2, ED{0.0, 0}}},
};
// clang-format on

Expand Down
Loading
Loading