From c4bdc85925c6ea267c3de83c5ba3a7a1d0ee83e7 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Wed, 17 Apr 2024 16:14:42 +0000 Subject: [PATCH 01/26] compact into a CSR --- libcusp/test/CMakeLists.txt | 2 +- .../include/galois/graphs/LS_LC_CSR_Graph.h | 52 +++++++++++-------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/libcusp/test/CMakeLists.txt b/libcusp/test/CMakeLists.txt index 710627302..7a26c8aaf 100644 --- a/libcusp/test/CMakeLists.txt +++ b/libcusp/test/CMakeLists.txt @@ -1,2 +1,2 @@ add_executable(shad_dist_graph shad-dist-graph.cpp) -target_link_libraries(shad_dist_graph galois_gnn) +target_link_libraries(shad_dist_graph galois_shmem galois_cusp) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 7a12c439d..35f50fcf1 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -106,6 +106,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { static uint64_t combiner(const uint64_t& f, const uint64_t& s) { return f + s; } + // todo(meyer): there is currently a memory leak in prefix sum :/ PrefixSum m_pfx{&m_vertices[0], &m_pfx_sum_cache[0]}; @@ -366,32 +367,41 @@ class LS_LC_CSR_Graph : private boost::noncopyable { void compact() { using std::swap; - // move from buffer 0 to buffer 1 - galois::do_all( - galois::iterate(vertices().begin(), vertices().end()), - [&](VertexTopologyID vertex_id) { - VertexMetadata& vertex_meta = m_vertices[vertex_id]; + if (m_vertices.empty()) + return; + + auto const& prefix_sum = getEdgePrefixSum(); + std::vector new_vertices(m_vertices.size()); + new_vertices[0].buffer = 0; + new_vertices[0].begin = 0; + new_vertices[0].end = prefix_sum[0]; + galois::do_all(galois::iterate(1ul, m_vertices.size()), + [&](VertexTopologyID vertex_id) { + new_vertices[vertex_id].buffer = 0; + new_vertices[vertex_id].begin = prefix_sum[vertex_id - 1]; + new_vertices[vertex_id].end = prefix_sum[vertex_id]; + }); - if (vertex_meta.buffer == 0) { - this->addEdgesTopologyOnly(vertex_id, {}); - } + LargeVector new_edges(prefix_sum.back()); - // we are about to swap the buffers, so all vertices will - // be in buffer 0 - vertex_meta.buffer = 0; + galois::do_all( + galois::iterate(0ul, m_vertices.size()), + [&](VertexTopologyID vertex_id) { + auto const& m_vertex_meta = m_vertices[vertex_id]; + auto const& new_vertex_meta = new_vertices[vertex_id]; + std::copy(&getEdgeMetadata(m_vertex_meta.buffer, m_vertex_meta.begin), + &getEdgeMetadata(m_vertex_meta.buffer, m_vertex_meta.end), + &new_edges[new_vertex_meta.begin]); }, galois::steal()); - // At this point, there are no more live edges in buffer 0. - m_edges_lock.lock(); - { - m_edges[0].resize(0); - swap(m_edges[0], m_edges[1]); - // relaxed is fine because of locks held: - m_edges_tail.store(0, std::memory_order_relaxed); - m_holes.store(0, std::memory_order_relaxed); - } - m_edges_lock.unlock(); + swap(m_vertices, new_vertices); + swap(m_edges[0], new_edges); + m_edges[1].resize(0); + + m_edges_tail = 0; + m_holes = 0; + m_prefix_valid = false; } /* From 4145bf42ce0e996070ce67666baac0962efc5903 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Wed, 17 Apr 2024 16:25:21 +0000 Subject: [PATCH 02/26] fixup! compact into a CSR --- .../include/galois/graphs/LS_LC_CSR_Graph.h | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 35f50fcf1..a339fd80b 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -408,25 +408,8 @@ class LS_LC_CSR_Graph : private boost::noncopyable { Compaction policy utilities. */ - // Returns an estimated memory usage in bytes for the entire data structure. - inline size_t getMemoryUsageBytes() { - size_t estimate = m_vertices.size() * sizeof(VertexMetadata); - if constexpr (HasVertexData) { - estimate += m_vertices.size() * sizeof(VertexData); - } - m_edges_lock.lock(); - { - estimate += - (m_edges[0].size() + m_edges_tail.load(std::memory_order_relaxed)) * - sizeof(EdgeMetadata); - } - m_edges_lock.unlock(); - if constexpr (HasEdgeData) { - estimate += m_edge_data.size() * - (sizeof(EdgeData) + - sizeof(std::pair)); - } - return estimate; + inline size_t getCSRMemoryUsageBytes() { + return m_edges[0].size() * sizeof(EdgeMetadata); } // Returns the number of bytes used for the log. From 3636968d08bfe0cce73b3347da3f600c3448e0eb Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Wed, 17 Apr 2024 20:48:17 +0000 Subject: [PATCH 03/26] fix bug --- libgalois/include/galois/graphs/LS_LC_CSR_Graph.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index a339fd80b..836e3bced 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -122,6 +122,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { // Compute the prefix sum using the two level method void computePrefixSum() { + resetPrefixSum(); constexpr uint64_t PARALLEL_PREFIX_SUM_VERTEX_THRESHOLD = static_cast(1) << 30; if (m_vertices.size() > PARALLEL_PREFIX_SUM_VERTEX_THRESHOLD) { From 47a48f33d740e3dbda2d66019eb380c3f8ea1417 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Wed, 17 Apr 2024 22:10:37 +0000 Subject: [PATCH 04/26] add functionality to ingest an entire batch at once --- .../include/galois/graphs/LS_LC_CSR_Graph.h | 68 +++++++++++++++++++ libgalois/test/graph-compile-lscsr.cpp | 9 ++- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 836e3bced..4baaa467c 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -308,6 +308,74 @@ class LS_LC_CSR_Graph : private boost::noncopyable { } } + template + void addBatchTopologyOnly( + std::vector>> + edges) { + if (m_vertices.empty() || edges.empty()) + return; + // + std::vector> pfx_sum(edges.size()); + auto const initial_num_vertices = m_vertices.size(); + galois::do_all( + galois::iterate(0ul, edges.size()), + [&](size_t idx) { + auto const vertex_id = edges[idx].first; + auto const degree = + vertex_id < initial_num_vertices ? getDegree(vertex_id) : 0ul; + pfx_sum[idx].second = degree; + pfx_sum[idx].first = degree + edges[idx].second.size(); + }, + galois::loopname("ComputePrefixSumOnBatch")); + + uint64_t max_topology_id = + std::max(initial_num_vertices - 1, edges.front().first); + for (size_t i = 1; i < pfx_sum.size(); ++i) { + pfx_sum[i].first += pfx_sum[i - 1].first; + max_topology_id = std::max(max_topology_id, edges[i].first); + } + // in case this batch adds new vertices (noop otherwise): + m_vertices.resize(max_topology_id + 1); + + auto const num_new_edges = pfx_sum.back().first; + auto const start = m_edges_tail.fetch_add(pfx_sum.back().first); + if (m_edges[1].size() < start + num_new_edges) { + m_edges[1].resize(std::max(m_edges[1].size() * 2, start + num_new_edges)); + } + + galois::do_all( + galois::iterate(0ul, edges.size()), + [&](size_t idx) { + auto const& [src, dsts] = edges[idx]; + auto const& vertex_meta = m_vertices[src]; + auto const new_begin = start + pfx_sum[idx].first; + auto const new_end = new_begin + pfx_sum[idx].second; + EdgeMetadata* log_dst = &getEdgeMetadata(1, new_begin); + if constexpr (sorted) { + std::merge(dsts.begin(), dsts.end(), + &getEdgeMetadata(vertex_meta.buffer, vertex_meta.begin), + &getEdgeMetadata(vertex_meta.buffer, vertex_meta.end), + log_dst); + } else { + // copy old edges + log_dst = std::copy( + &getEdgeMetadata(vertex_meta.buffer, vertex_meta.begin), + &getEdgeMetadata(vertex_meta.buffer, vertex_meta.end), log_dst); + + // insert new edges + std::copy(dsts.begin(), dsts.end(), log_dst); + } + + // update vertex metadata + m_vertices[src].buffer = 1; + m_vertices[src].begin = new_begin; + m_vertices[src].end = new_end; + }, + galois::steal(), galois::loopname("CopyEdgesToLog")); + + m_prefix_valid = false; + } + /* * Adds outgoing edges from the given src to all dsts. If `sorted`, assume * both `dsts` and the existing edge array is sorted ascending, and maintain diff --git a/libgalois/test/graph-compile-lscsr.cpp b/libgalois/test/graph-compile-lscsr.cpp index a239958d3..e8d25fb2f 100644 --- a/libgalois/test/graph-compile-lscsr.cpp +++ b/libgalois/test/graph-compile-lscsr.cpp @@ -70,13 +70,16 @@ int main() { g.setData(3, 3); GALOIS_ASSERT(g.getData(3) == 3); - uint64_t four = g.addVertices({4, 5, 6, 7}); + std::vector>> new_edges = { + {4, {0, 1, 2, 3}}, + {6, {0, 1, 2, 3}}, + {5, {0, 1, 2, 3}}, + {7, {0, 1, 2, 3}}}; + g.addBatchTopologyOnly(std::move(new_edges)); for (size_t ii = 0; ii < 4; ++ii) { // make sure previous data survived the resize GALOIS_ASSERT(g.getData(ii) == ii); - // check the new vertex data - GALOIS_ASSERT(g.getData(four + ii) == 4 + ii); } g.addEdges(0, {1, 2, 3}, {1, 2, 3}); From 45d82c3d194fb484a26cf5baac93ba2efe4f042d Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Wed, 17 Apr 2024 22:31:09 +0000 Subject: [PATCH 05/26] remove hole tracking --- libgalois/include/galois/graphs/LS_LC_CSR_Graph.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 4baaa467c..e831ced4f 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -89,9 +89,6 @@ class LS_LC_CSR_Graph : private boost::noncopyable { EdgeDataStore m_edge_data; alignas(hardware_destructive_interference_size) std::atomic_uint64_t m_edges_tail = ATOMIC_VAR_INIT(0); - // m_holes is the number of holes in the log (m_edges[1]) - alignas(hardware_destructive_interference_size) std::atomic_uint64_t m_holes = - ATOMIC_VAR_INIT(0); /* * Prefix Sum utilities @@ -387,10 +384,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { // Copies the edge list to the end of m_edges[1] together with the new // edges. - auto& vertex_meta = m_vertices[src]; - if (vertex_meta.buffer == 1) - m_holes.fetch_add(vertex_meta.degree(), std::memory_order_relaxed); - + auto& vertex_meta = m_vertices[src]; uint64_t const new_degree = vertex_meta.degree() + dsts.size(); uint64_t const new_begin = m_edges_tail.fetch_add(new_degree, std::memory_order_relaxed); @@ -469,7 +463,6 @@ class LS_LC_CSR_Graph : private boost::noncopyable { m_edges[1].resize(0); m_edges_tail = 0; - m_holes = 0; m_prefix_valid = false; } @@ -486,11 +479,6 @@ class LS_LC_CSR_Graph : private boost::noncopyable { return m_edges_tail.load(std::memory_order_relaxed) * sizeof(EdgeMetadata); } - // Returns the number of bytes used for holes in the log. - inline size_t getLogHolesMemoryUsageBytes() { - return m_holes.load(std::memory_order_relaxed) * sizeof(EdgeMetadata); - } - /** * DO NOT USE WHILE MODIFYING THE GRAPH! * ONLY USE IF GRAPH HAS BEEN LOADED From 97cddb0293af808d451f2aba71754eb7746b5c8f Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Wed, 17 Apr 2024 23:00:48 +0000 Subject: [PATCH 06/26] remove some unnecessary logic --- .../include/galois/graphs/LS_LC_CSR_Graph.h | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index e831ced4f..584e85b5c 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -312,30 +312,21 @@ class LS_LC_CSR_Graph : private boost::noncopyable { if (m_vertices.empty() || edges.empty()) return; // - std::vector> pfx_sum(edges.size()); + std::vector pfx_sum(edges.size()); + std::vector degrees(edges.size()); auto const initial_num_vertices = m_vertices.size(); galois::do_all( galois::iterate(0ul, edges.size()), [&](size_t idx) { auto const vertex_id = edges[idx].first; - auto const degree = - vertex_id < initial_num_vertices ? getDegree(vertex_id) : 0ul; - pfx_sum[idx].second = degree; - pfx_sum[idx].first = degree + edges[idx].second.size(); + auto const degree = getDegree(vertex_id); + degrees[idx] = degree; + pfx_sum[idx] = degree + edges[idx].second.size(); }, galois::loopname("ComputePrefixSumOnBatch")); - uint64_t max_topology_id = - std::max(initial_num_vertices - 1, edges.front().first); - for (size_t i = 1; i < pfx_sum.size(); ++i) { - pfx_sum[i].first += pfx_sum[i - 1].first; - max_topology_id = std::max(max_topology_id, edges[i].first); - } - // in case this batch adds new vertices (noop otherwise): - m_vertices.resize(max_topology_id + 1); - - auto const num_new_edges = pfx_sum.back().first; - auto const start = m_edges_tail.fetch_add(pfx_sum.back().first); + auto const num_new_edges = pfx_sum.back(); + auto const start = m_edges_tail.fetch_add(num_new_edges); if (m_edges[1].size() < start + num_new_edges) { m_edges[1].resize(std::max(m_edges[1].size() * 2, start + num_new_edges)); } From ea5c9375f597876c6c99d574110135906f6ec58c Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Wed, 17 Apr 2024 23:08:52 +0000 Subject: [PATCH 07/26] fix bugs --- .../include/galois/graphs/LS_LC_CSR_Graph.h | 5 ++--- libgalois/test/graph-compile-lscsr.cpp | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 584e85b5c..479de3fc1 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -314,7 +314,6 @@ class LS_LC_CSR_Graph : private boost::noncopyable { // std::vector pfx_sum(edges.size()); std::vector degrees(edges.size()); - auto const initial_num_vertices = m_vertices.size(); galois::do_all( galois::iterate(0ul, edges.size()), [&](size_t idx) { @@ -336,8 +335,8 @@ class LS_LC_CSR_Graph : private boost::noncopyable { [&](size_t idx) { auto const& [src, dsts] = edges[idx]; auto const& vertex_meta = m_vertices[src]; - auto const new_begin = start + pfx_sum[idx].first; - auto const new_end = new_begin + pfx_sum[idx].second; + auto const new_begin = start + pfx_sum[idx]; + auto const new_end = new_begin + degrees[idx]; EdgeMetadata* log_dst = &getEdgeMetadata(1, new_begin); if constexpr (sorted) { std::merge(dsts.begin(), dsts.end(), diff --git a/libgalois/test/graph-compile-lscsr.cpp b/libgalois/test/graph-compile-lscsr.cpp index e8d25fb2f..59c83fd0a 100644 --- a/libgalois/test/graph-compile-lscsr.cpp +++ b/libgalois/test/graph-compile-lscsr.cpp @@ -70,16 +70,25 @@ int main() { g.setData(3, 3); GALOIS_ASSERT(g.getData(3) == 3); + auto const four = g.addVertices({4, 5, 6, 7}); std::vector>> new_edges = { - {4, {0, 1, 2, 3}}, - {6, {0, 1, 2, 3}}, - {5, {0, 1, 2, 3}}, - {7, {0, 1, 2, 3}}}; + {four, {0, 1, 2, 3}}, + {four + 1, {0, 1, 2, 3}}, + {four + 2, {0, 1, 2, 3}}, + {four + 3, {0, 1, 2, 3}}}; g.addBatchTopologyOnly(std::move(new_edges)); for (size_t ii = 0; ii < 4; ++ii) { // make sure previous data survived the resize GALOIS_ASSERT(g.getData(ii) == ii); + // make sure new data is correct + GALOIS_ASSERT(g.getData(four + ii) == 4 + ii); + } + + for (uint64_t ii = 0; ii < 4; ++ii) { + for (uint64_t jj = 0; jj < 4; ++jj) { + GALOIS_ASSERT(g.getEdgeDst(g.edge_begin(four + ii)[jj]) == jj); + } } g.addEdges(0, {1, 2, 3}, {1, 2, 3}); From cf59c7adf018f05abdb0262e164163f9391f9b2d Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Wed, 17 Apr 2024 23:30:21 +0000 Subject: [PATCH 08/26] fix buggy code --- .../include/galois/graphs/LS_LC_CSR_Graph.h | 31 ++++++++++--------- libgalois/test/graph-compile-lscsr.cpp | 2 +- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 479de3fc1..79f972957 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -313,30 +313,31 @@ class LS_LC_CSR_Graph : private boost::noncopyable { return; // std::vector pfx_sum(edges.size()); - std::vector degrees(edges.size()); galois::do_all( galois::iterate(0ul, edges.size()), [&](size_t idx) { - auto const vertex_id = edges[idx].first; - auto const degree = getDegree(vertex_id); - degrees[idx] = degree; - pfx_sum[idx] = degree + edges[idx].second.size(); + auto const vertex_id = edges[idx].first; + auto const old_degree = getDegree(vertex_id); + pfx_sum[idx] = old_degree + edges[idx].second.size(); }, - galois::loopname("ComputePrefixSumOnBatch")); + galois::loopname("ComputeVertexDegrees")); + + for (size_t i = 1; i < pfx_sum.size(); ++i) + pfx_sum[i] += pfx_sum[i - 1]; auto const num_new_edges = pfx_sum.back(); - auto const start = m_edges_tail.fetch_add(num_new_edges); - if (m_edges[1].size() < start + num_new_edges) { + auto const start = + m_edges_tail.fetch_add(num_new_edges, std::memory_order_relaxed); + if (m_edges[1].size() < start + num_new_edges) m_edges[1].resize(std::max(m_edges[1].size() * 2, start + num_new_edges)); - } galois::do_all( galois::iterate(0ul, edges.size()), [&](size_t idx) { auto const& [src, dsts] = edges[idx]; - auto const& vertex_meta = m_vertices[src]; - auto const new_begin = start + pfx_sum[idx]; - auto const new_end = new_begin + degrees[idx]; + auto const new_begin = (idx) ? (start + pfx_sum[idx - 1]) : start; + auto const new_end = start + pfx_sum[idx]; + auto& vertex_meta = m_vertices[src]; EdgeMetadata* log_dst = &getEdgeMetadata(1, new_begin); if constexpr (sorted) { std::merge(dsts.begin(), dsts.end(), @@ -354,9 +355,9 @@ class LS_LC_CSR_Graph : private boost::noncopyable { } // update vertex metadata - m_vertices[src].buffer = 1; - m_vertices[src].begin = new_begin; - m_vertices[src].end = new_end; + vertex_meta.buffer = 1; + vertex_meta.begin = new_begin; + vertex_meta.end = new_end; }, galois::steal(), galois::loopname("CopyEdgesToLog")); diff --git a/libgalois/test/graph-compile-lscsr.cpp b/libgalois/test/graph-compile-lscsr.cpp index 59c83fd0a..8924664c3 100644 --- a/libgalois/test/graph-compile-lscsr.cpp +++ b/libgalois/test/graph-compile-lscsr.cpp @@ -136,7 +136,7 @@ int main() { GALOIS_ASSERT(g[1] == 3); GALOIS_ASSERT(g[2] == 3); // ... - GALOIS_ASSERT(g[8] == 7); + GALOIS_ASSERT(g[four + 4] == 23); uint64_t num_vertices = (1 << 22) + 67; galois::graphs::LS_LC_CSR_Graph big(num_vertices); From 83fd27b6d6f1a6ce12f0e81d4e1ec48c88ad1899 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Wed, 17 Apr 2024 23:41:00 +0000 Subject: [PATCH 09/26] fix bugs --- libgalois/include/galois/LargeVector.h | 25 +++++++------------ .../include/galois/graphs/LS_LC_CSR_Graph.h | 1 + 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/libgalois/include/galois/LargeVector.h b/libgalois/include/galois/LargeVector.h index dfdf80f84..931440924 100644 --- a/libgalois/include/galois/LargeVector.h +++ b/libgalois/include/galois/LargeVector.h @@ -75,14 +75,14 @@ class LargeVector : public boost::noncopyable { } public: - LargeVector(size_t initial_capacity) + LargeVector(size_t initial_size) : m_capacity(0), m_size(0), m_data(nullptr), m_fd(memfd_create("LargeVector", 0)), m_mappings({std::make_pair(nullptr, 0)}) { if (m_fd == -1) throw std::runtime_error(std::string("creating memfd: ") + std::strerror(errno)); - ensure_capacity(initial_capacity); + resize(initial_size); } LargeVector() : LargeVector(1) {} @@ -98,20 +98,13 @@ class LargeVector : public boost::noncopyable { assert(other.m_mappings.empty()); } - LargeVector& operator=(LargeVector&& other) { - m_capacity = std::move(other.m_capacity); - m_size = std::move(other.m_size); - m_data = std::move(other.m_data); - m_fd = std::move(other.m_fd); - m_mappings = std::move(other.m_mappings); - - other.m_capacity = 0; - other.m_size = 0; - other.m_data = nullptr; - other.m_fd = -1; - assert(other.m_mappings.empty()); - - return *this; + friend void swap(LargeVector& first, LargeVector& second) { + using std::swap; + swap(first.m_capacity, second.m_capacity); + swap(first.m_size, second.m_size); + swap(first.m_data, second.m_data); + swap(first.m_fd, second.m_fd); + swap(first.m_mappings, second.m_mappings); } ~LargeVector() { diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 79f972957..0f5783a80 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -437,6 +437,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { }); LargeVector new_edges(prefix_sum.back()); + GALOIS_ASSERT(new_edges.size() == prefix_sum.back()); galois::do_all( galois::iterate(0ul, m_vertices.size()), From e47b61dd0e5a1586cb213acde5868c612e4a06c1 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Wed, 17 Apr 2024 23:47:07 +0000 Subject: [PATCH 10/26] undo bug fix and actually fix --- libgalois/include/galois/LargeVector.h | 2 +- libgalois/include/galois/graphs/LS_LC_CSR_Graph.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libgalois/include/galois/LargeVector.h b/libgalois/include/galois/LargeVector.h index 931440924..3eeccb33b 100644 --- a/libgalois/include/galois/LargeVector.h +++ b/libgalois/include/galois/LargeVector.h @@ -82,7 +82,7 @@ class LargeVector : public boost::noncopyable { if (m_fd == -1) throw std::runtime_error(std::string("creating memfd: ") + std::strerror(errno)); - resize(initial_size); + ensure_capacity(initial_size); } LargeVector() : LargeVector(1) {} diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 0f5783a80..e62fd5e94 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -437,6 +437,8 @@ class LS_LC_CSR_Graph : private boost::noncopyable { }); LargeVector new_edges(prefix_sum.back()); + new_edges.resize(prefix_sum.back()); + GALOIS_ASSERT(new_edges.size() == prefix_sum.back()); galois::do_all( From f463b4dc0090f21bf9f3a3c1331968a3815d8a28 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Thu, 18 Apr 2024 08:39:38 +0000 Subject: [PATCH 11/26] wip --- libgalois/include/galois/LargeVector.h | 10 +- .../include/galois/graphs/LS_LC_CSR_Graph.h | 138 ++++++++++++------ 2 files changed, 100 insertions(+), 48 deletions(-) diff --git a/libgalois/include/galois/LargeVector.h b/libgalois/include/galois/LargeVector.h index 3eeccb33b..3f24cc8b2 100644 --- a/libgalois/include/galois/LargeVector.h +++ b/libgalois/include/galois/LargeVector.h @@ -71,6 +71,8 @@ class LargeVector : public boost::noncopyable { throw std::runtime_error(std::string("mmap failed: ") + std::strerror(errno)); + madvise(m_data, file_size, MADV_WILLNEED | MADV_HUGEPAGE); + m_mappings.push_front(std::make_pair(m_data, mmap_size)); } @@ -138,13 +140,13 @@ class LargeVector : public boost::noncopyable { } void resize(size_t count) { - for (T* ii = begin() + count; ii < end(); ++ii) - ii->~T(); + // galois::do_all(galois::iterate(begin() + count, end()), + // [](T* ii) { ii->~T(); }); ensure_capacity(count); - for (T* ii = end(); ii < begin() + count; ++ii) - new (ii) T(); + // galois::do_all(galois::iterate(end(), begin() + count), + // [](T* ii) { new (ii) T(); }); m_size = count; } diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index e62fd5e94..bf16b29de 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -93,6 +93,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { /* * Prefix Sum utilities */ + static constexpr uint64_t PARALLEL_PREFIX_SUM_VERTEX_THRESHOLD = 1ul << 25; std::vector m_pfx_sum_cache; static uint64_t transmute(const VertexMetadata& vertex_meta) { return vertex_meta.degree(); @@ -103,25 +104,36 @@ class LS_LC_CSR_Graph : private boost::noncopyable { static uint64_t combiner(const uint64_t& f, const uint64_t& s) { return f + s; } - // todo(meyer): there is currently a memory leak in prefix sum :/ PrefixSum m_pfx{&m_vertices[0], &m_pfx_sum_cache[0]}; + static uint64_t transmute_b0(VertexMetadata const& vertex_meta) { + return (vertex_meta.buffer) ? 0 : vertex_meta.degree(); + } + static uint64_t scan_op_b0(VertexMetadata const& p, const uint64_t& l) { + return (p.buffer) ? l : p.degree() + l; + } + PrefixSum + m_pfx_b0{&m_vertices[0], &m_pfx_sum_cache[0]}; + + // todo(meyer): there is currently a memory leak in prefix sum :/ + bool m_prefix_valid; void resetPrefixSum() { m_pfx_sum_cache.resize(m_vertices.size()); m_pfx.src = &m_vertices[0]; m_pfx.dst = &m_pfx_sum_cache[0]; + m_pfx_b0.src = &m_vertices[0]; + m_pfx_b0.dst = &m_pfx_sum_cache[0]; m_prefix_valid = false; } // Compute the prefix sum using the two level method void computePrefixSum() { resetPrefixSum(); - constexpr uint64_t PARALLEL_PREFIX_SUM_VERTEX_THRESHOLD = - static_cast(1) << 30; if (m_vertices.size() > PARALLEL_PREFIX_SUM_VERTEX_THRESHOLD) { m_pfx.computePrefixSumSerially(m_vertices.size()); } else { @@ -136,8 +148,13 @@ class LS_LC_CSR_Graph : private boost::noncopyable { } public: - LS_LC_CSR_Graph(uint64_t num_vertices) - : m_vertices(num_vertices, VertexMetadata()) { + LS_LC_CSR_Graph(uint64_t num_vertices) : m_vertices(num_vertices) { + galois::do_all(galois::iterate(0ul, num_vertices), + [&](VertexTopologyID const& vertex) { + m_vertices[vertex].buffer = 0; + m_vertices[vertex].begin = 0; + m_vertices[vertex].end = 0; + }); if constexpr (HasVertexData) { m_vertex_data.resize(num_vertices); } @@ -192,6 +209,12 @@ class LS_LC_CSR_Graph : private boost::noncopyable { VertexTopologyID addVerticesTopologyOnly(size_t count) { VertexTopologyID const start = m_vertices.size(); m_vertices.resize(start + count); + galois::do_all(galois::iterate(start, start + count), + [&](VertexTopologyID const& vertex) { + m_vertices[vertex].buffer = 0; + m_vertices[vertex].begin = 0; + m_vertices[vertex].end = 0; + }); return start; } @@ -311,7 +334,6 @@ class LS_LC_CSR_Graph : private boost::noncopyable { edges) { if (m_vertices.empty() || edges.empty()) return; - // std::vector pfx_sum(edges.size()); galois::do_all( galois::iterate(0ul, edges.size()), @@ -329,7 +351,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { auto const start = m_edges_tail.fetch_add(num_new_edges, std::memory_order_relaxed); if (m_edges[1].size() < start + num_new_edges) - m_edges[1].resize(std::max(m_edges[1].size() * 2, start + num_new_edges)); + m_edges[1].resize(start + num_new_edges); galois::do_all( galois::iterate(0ul, edges.size()), @@ -385,7 +407,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { m_edges_lock.lock(); { if (m_edges[1].size() < new_end) - m_edges[1].resize(std::max(m_edges[1].size() * 2, new_end)); + m_edges[1].resize(new_end); } m_edges_lock.unlock(); } @@ -414,6 +436,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { m_prefix_valid = false; } +public: // Performs the compaction algorithm by copying any vertices left in buffer 0 // to buffer 1, then swapping the buffers. // @@ -423,41 +446,68 @@ class LS_LC_CSR_Graph : private boost::noncopyable { if (m_vertices.empty()) return; + auto const num_vertices = m_vertices.size(); + + // step 1: copy from CSR to log + { + resetPrefixSum(); + if (m_vertices.size() > PARALLEL_PREFIX_SUM_VERTEX_THRESHOLD) { + m_pfx_b0.computePrefixSum(m_vertices.size()); + } else { + m_pfx_b0.computePrefixSumSerially(m_vertices.size()); + } + auto const log_num_edges = m_pfx_sum_cache.back(); + auto const start = + m_edges_tail.fetch_add(log_num_edges, std::memory_order_relaxed); + if (m_edges[1].size() < start + log_num_edges) { + m_edges[1].resize(start + log_num_edges); + } - auto const& prefix_sum = getEdgePrefixSum(); - std::vector new_vertices(m_vertices.size()); - new_vertices[0].buffer = 0; - new_vertices[0].begin = 0; - new_vertices[0].end = prefix_sum[0]; - galois::do_all(galois::iterate(1ul, m_vertices.size()), - [&](VertexTopologyID vertex_id) { - new_vertices[vertex_id].buffer = 0; - new_vertices[vertex_id].begin = prefix_sum[vertex_id - 1]; - new_vertices[vertex_id].end = prefix_sum[vertex_id]; - }); - - LargeVector new_edges(prefix_sum.back()); - new_edges.resize(prefix_sum.back()); - - GALOIS_ASSERT(new_edges.size() == prefix_sum.back()); - - galois::do_all( - galois::iterate(0ul, m_vertices.size()), - [&](VertexTopologyID vertex_id) { - auto const& m_vertex_meta = m_vertices[vertex_id]; - auto const& new_vertex_meta = new_vertices[vertex_id]; - std::copy(&getEdgeMetadata(m_vertex_meta.buffer, m_vertex_meta.begin), - &getEdgeMetadata(m_vertex_meta.buffer, m_vertex_meta.end), - &new_edges[new_vertex_meta.begin]); - }, - galois::steal()); - - swap(m_vertices, new_vertices); - swap(m_edges[0], new_edges); - m_edges[1].resize(0); - - m_edges_tail = 0; - m_prefix_valid = false; + galois::do_all( + galois::iterate(0ul, num_vertices), + [&](VertexTopologyID ii) { + auto& vertex_meta = m_vertices[ii]; + if (vertex_meta.buffer) + return; // already on the log + auto const new_begin = start + ((ii) ? m_pfx_sum_cache[ii - 1] : 0); + auto const new_end = start + m_pfx_sum_cache[ii]; + std::copy(&getEdgeMetadata(0, vertex_meta.begin), + &getEdgeMetadata(0, vertex_meta.end), + &getEdgeMetadata(1, new_begin)); + // vertex_meta.buffer = 1; + vertex_meta.buffer = 0; // not accurate, but it soon will be... + vertex_meta.begin = new_begin; + vertex_meta.end = new_end; + }, + galois::steal(), galois::loopname("CopyCSRToLog")); + } + // At this point, all edges are on the log (and the prefix sum is invalid). + // We can now compact into the CSR. + { + // compute the actual prefix sum + auto const& prefix_sum = getEdgePrefixSum(); + m_edges[0].resize(prefix_sum.back()); + + galois::do_all( + galois::iterate(0ul, m_vertices.size()), + [&](size_t idx) { + auto& vertex_meta = m_vertices[idx]; + auto const new_begin = (idx) ? prefix_sum[idx - 1] : 0; + auto const new_end = prefix_sum[idx]; + std::copy(&getEdgeMetadata(1, vertex_meta.begin), + &getEdgeMetadata(1, vertex_meta.end), + &getEdgeMetadata(0, new_begin)); + // vertex_meta.buffer = 0; // already done above + vertex_meta.begin = new_begin; + vertex_meta.end = new_end; + }, + galois::steal(), galois::loopname("CompactLogToCSR")); + + swap(m_edges[0], m_edges[1]); + // m_edges[1].resize(0); + m_edges_tail = 0; + m_prefix_valid = false; + } } /* @@ -470,7 +520,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { // Returns the number of bytes used for the log. inline size_t getLogMemoryUsageBytes() { - return m_edges_tail.load(std::memory_order_relaxed) * sizeof(EdgeMetadata); + return m_edges_tail * sizeof(EdgeMetadata); } /** @@ -499,7 +549,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { uint64_t end; // exclusive uint8_t buffer; - VertexMetadata() : begin(0), end(0), buffer(0) {} + VertexMetadata() {} VertexMetadata(VertexMetadata const& other) : begin(other.begin), end(other.end), buffer(other.buffer) {} From 88e012d00386f66a3b2554ddca08d0169c6191ed Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Fri, 19 Apr 2024 13:41:07 +0000 Subject: [PATCH 12/26] wip --- libgalois/include/galois/graphs/LS_LC_CSR_Graph.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index bf16b29de..ae2f348e6 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -335,19 +335,24 @@ class LS_LC_CSR_Graph : private boost::noncopyable { if (m_vertices.empty() || edges.empty()) return; std::vector pfx_sum(edges.size()); + galois::GAccumulator old_degree_total; + old_degree_total.reset(); galois::do_all( galois::iterate(0ul, edges.size()), [&](size_t idx) { auto const vertex_id = edges[idx].first; auto const old_degree = getDegree(vertex_id); - pfx_sum[idx] = old_degree + edges[idx].second.size(); + old_degree_total += old_degree; + pfx_sum[idx] = old_degree + edges[idx].second.size(); }, galois::loopname("ComputeVertexDegrees")); for (size_t i = 1; i < pfx_sum.size(); ++i) pfx_sum[i] += pfx_sum[i - 1]; - auto const num_new_edges = pfx_sum.back(); + std::cout << "old degrees total: " << old_degree_total.reduce() + << ", new degrees total: " << num_new_edges << std::endl; + auto const start = m_edges_tail.fetch_add(num_new_edges, std::memory_order_relaxed); if (m_edges[1].size() < start + num_new_edges) From 0ec74edaf19d9274229de1b629d378df76adf7a9 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Fri, 19 Apr 2024 15:24:12 +0000 Subject: [PATCH 13/26] patch test --- libgalois/test/large-vector.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libgalois/test/large-vector.cpp b/libgalois/test/large-vector.cpp index 313626041..99efe9ff7 100644 --- a/libgalois/test/large-vector.cpp +++ b/libgalois/test/large-vector.cpp @@ -64,10 +64,10 @@ int main() { GALOIS_ASSERT(num_constructed == max_cap); GALOIS_ASSERT(addr == &the_vector[max_cap]); - // resize should call the destructor, but vector should stay mapped + // resize should not call destructor GALOIS_ASSERT(num_destructed == 0); the_vector.resize(0); - GALOIS_ASSERT(num_destructed == max_cap); + GALOIS_ASSERT(num_destructed == 0); GALOIS_ASSERT(addr == &the_vector[max_cap]); // this should not actually allocate memory! From ae610d6adae6627a54e2f5e60d9db077b1a6b1ee Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Fri, 19 Apr 2024 15:28:33 +0000 Subject: [PATCH 14/26] fixup! patch test --- libgalois/test/large-vector.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/libgalois/test/large-vector.cpp b/libgalois/test/large-vector.cpp index 99efe9ff7..65380c2b3 100644 --- a/libgalois/test/large-vector.cpp +++ b/libgalois/test/large-vector.cpp @@ -40,20 +40,17 @@ int main() { } { - static uint64_t num_constructed = 0, num_destructed = 0; class Object { uint8_t dummy; public: - Object() { ++num_constructed; } - ~Object() { ++num_destructed; } + Object() = delete; + ~Object() = delete; }; static_assert(sizeof(Object) > 0); const size_t max_cap = (1 << 22); galois::LargeVector the_vector(max_cap); - // constructor should not actually fill the vector - GALOIS_ASSERT(num_constructed == 0); // entire vector should be mapped, even if it is empty const Object* addr = &the_vector[max_cap]; @@ -61,13 +58,9 @@ int main() { the_vector.resize(max_cap); - GALOIS_ASSERT(num_constructed == max_cap); GALOIS_ASSERT(addr == &the_vector[max_cap]); - // resize should not call destructor - GALOIS_ASSERT(num_destructed == 0); the_vector.resize(0); - GALOIS_ASSERT(num_destructed == 0); GALOIS_ASSERT(addr == &the_vector[max_cap]); // this should not actually allocate memory! From 956bc0d7aec1ea089dd3150e2d923a52af6052e8 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Fri, 19 Apr 2024 15:54:16 +0000 Subject: [PATCH 15/26] fixup! patch test --- libgalois/test/large-vector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgalois/test/large-vector.cpp b/libgalois/test/large-vector.cpp index 65380c2b3..ac3ce6537 100644 --- a/libgalois/test/large-vector.cpp +++ b/libgalois/test/large-vector.cpp @@ -44,7 +44,7 @@ int main() { uint8_t dummy; public: - Object() = delete; + Object() = delete; ~Object() = delete; }; static_assert(sizeof(Object) > 0); From 6f4424421a9699069bad7ed539eba0845e810eb1 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Fri, 19 Apr 2024 22:58:01 +0000 Subject: [PATCH 16/26] wip --- .../include/galois/graphs/LS_LC_CSR_Graph.h | 22 ++++++++++++++++--- libgalois/include/galois/graphs/MorphGraph.h | 4 ++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index ae2f348e6..471afb001 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -320,7 +321,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { template void addEdges(VertexTopologyID src, const std::vector dsts, std::vector data) { - GALOIS_ASSERT(data.size() == dsts.size()); + GALOIS_ASSERT(data.size() == dsts.size(), "Data size mismatch"); this->addEdgesTopologyOnly(src, dsts); for (size_t i = 0; i < dsts.size(); ++i) { auto key = std::make_pair(src, dsts[i]); @@ -334,19 +335,34 @@ class LS_LC_CSR_Graph : private boost::noncopyable { edges) { if (m_vertices.empty() || edges.empty()) return; + std::vector pfx_sum(edges.size()); + galois::GReduceMax max_vertex_id; + max_vertex_id.reset(); galois::GAccumulator old_degree_total; old_degree_total.reset(); galois::do_all( galois::iterate(0ul, edges.size()), [&](size_t idx) { - auto const vertex_id = edges[idx].first; - auto const old_degree = getDegree(vertex_id); + auto const vertex_id = edges[idx].first; + max_vertex_id.update(vertex_id); + auto const old_degree = + vertex_id < m_vertices.size() ? getDegree(vertex_id) : 0; old_degree_total += old_degree; pfx_sum[idx] = old_degree + edges[idx].second.size(); }, galois::loopname("ComputeVertexDegrees")); + uint64_t const prev_num_vertices = m_vertices.size(); + m_vertices.resize(std::max(max_vertex_id.reduce() + 1, m_vertices.size())); + galois::do_all(galois::iterate(m_vertices.begin() + prev_num_vertices, + m_vertices.end()), + [&](VertexMetadata& vertex_meta) { + vertex_meta.buffer = 0; + vertex_meta.begin = 0; + vertex_meta.end = 0; + }); + for (size_t i = 1; i < pfx_sum.size(); ++i) pfx_sum[i] += pfx_sum[i - 1]; auto const num_new_edges = pfx_sum.back(); diff --git a/libgalois/include/galois/graphs/MorphGraph.h b/libgalois/include/galois/graphs/MorphGraph.h index ef29d1c0a..ca8be6025 100644 --- a/libgalois/include/galois/graphs/MorphGraph.h +++ b/libgalois/include/galois/graphs/MorphGraph.h @@ -702,7 +702,7 @@ class MorphGraph : private boost::noncopyable { EdgeTy* constructOutEdgeValue(FileGraph&, typename FileGraph::edge_iterator, GraphNode src, GraphNode dst, - typename std::enable_if<_A1&& !_A2>::type* = 0) { + typename std::enable_if<_A1 && !_A2>::type* = 0) { return createOutEdge(src, dst, galois::MethodFlag::UNPROTECTED); } @@ -977,7 +977,7 @@ public //! Sorts edge of a node by destination. void sortEdgesByDst(GraphNode N, galois::MethodFlag mflag = MethodFlag::WRITE) { - acquire(N, mflag); + N->acquire(mflag); typedef typename gNode::EdgeInfo EdgeInfo; std::sort(N->begin(), N->end(), [=](const EdgeInfo& e1, const EdgeInfo& e2) { From 6a65e1ef9afc19fe0da1f61979d16b552a37285b Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Fri, 19 Apr 2024 23:00:06 +0000 Subject: [PATCH 17/26] remove semicolon --- libgalois/include/galois/graphs/LS_LC_CSR_Graph.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 471afb001..6e2acc3d1 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -613,6 +613,6 @@ class LS_LC_CSR_Graph : private boost::noncopyable { }; }; -}; // namespace galois::graphs +} // namespace galois::graphs #endif From 2ef6f825767f8376569cf1f70d6a078cd4ba1286 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Fri, 19 Apr 2024 23:06:19 +0000 Subject: [PATCH 18/26] format --- libgalois/include/galois/graphs/MorphGraph.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgalois/include/galois/graphs/MorphGraph.h b/libgalois/include/galois/graphs/MorphGraph.h index ca8be6025..7d11ed9e5 100644 --- a/libgalois/include/galois/graphs/MorphGraph.h +++ b/libgalois/include/galois/graphs/MorphGraph.h @@ -702,7 +702,7 @@ class MorphGraph : private boost::noncopyable { EdgeTy* constructOutEdgeValue(FileGraph&, typename FileGraph::edge_iterator, GraphNode src, GraphNode dst, - typename std::enable_if<_A1 && !_A2>::type* = 0) { + typename std::enable_if<_A1&& !_A2>::type* = 0) { return createOutEdge(src, dst, galois::MethodFlag::UNPROTECTED); } From 0539d277972816ca3bbe79d39f7bdb1ca41035a8 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Sat, 20 Apr 2024 00:10:02 +0000 Subject: [PATCH 19/26] wip --- libgalois/include/galois/LargeVector.h | 6 ++++++ libgalois/include/galois/graphs/LS_LC_CSR_Graph.h | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libgalois/include/galois/LargeVector.h b/libgalois/include/galois/LargeVector.h index 3f24cc8b2..53ed33cfd 100644 --- a/libgalois/include/galois/LargeVector.h +++ b/libgalois/include/galois/LargeVector.h @@ -139,6 +139,10 @@ class LargeVector : public boost::noncopyable { m_data[--m_size].~T(); } + /** + * Note: unlike std::vector, resize does not call constructors or + * destructors. + */ void resize(size_t count) { // galois::do_all(galois::iterate(begin() + count, end()), // [](T* ii) { ii->~T(); }); @@ -151,6 +155,8 @@ class LargeVector : public boost::noncopyable { m_size = count; } + bool empty() { return m_size == 0; } + inline T* begin() { return m_data; } inline T* end() { return m_data + m_size; } }; diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 6e2acc3d1..304282df4 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -82,7 +82,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { using EdgeMetadata = VertexTopologyID; VertexDataStore m_vertex_data; - std::vector m_vertices; + LargeVector m_vertices; // m_edges[0] is the CSR with gaps, m_edges[1] is the update log. LargeVector m_edges[2]; @@ -333,7 +333,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { void addBatchTopologyOnly( std::vector>> edges) { - if (m_vertices.empty() || edges.empty()) + if (edges.empty()) return; std::vector pfx_sum(edges.size()); @@ -570,7 +570,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { uint64_t end; // exclusive uint8_t buffer; - VertexMetadata() {} + VertexMetadata() = delete; VertexMetadata(VertexMetadata const& other) : begin(other.begin), end(other.end), buffer(other.buffer) {} From cb74f7b3b4c3b0625cb843eefc176a5ba1e586eb Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Sat, 20 Apr 2024 04:02:03 +0000 Subject: [PATCH 20/26] wip --- libgalois/include/galois/graphs/LS_LC_CSR_Graph.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 304282df4..1620fdf54 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -336,6 +336,16 @@ class LS_LC_CSR_Graph : private boost::noncopyable { if (edges.empty()) return; + static constexpr size_t PARALLEL_VERTEX_SORT_THRESHOLD = (1ul << 16); + if (edges.size() >= PARALLEL_VERTEX_SORT_THRESHOLD) { + galois::ParallelSTL::sort( + edges.begin(), edges.end(), + [](auto const& a, auto const& b) { return a.first < b.first; }); + } else { + std::sort(edges.begin(), edges.end(), + [](auto const& a, auto const& b) { return a.first < b.first; }); + } + std::vector pfx_sum(edges.size()); galois::GReduceMax max_vertex_id; max_vertex_id.reset(); From 31e6b6dc2d6026943a29ead37be2c450f4933745 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Sat, 20 Apr 2024 04:38:57 +0000 Subject: [PATCH 21/26] remove sort --- libgalois/include/galois/graphs/LS_LC_CSR_Graph.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 1620fdf54..304282df4 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -336,16 +336,6 @@ class LS_LC_CSR_Graph : private boost::noncopyable { if (edges.empty()) return; - static constexpr size_t PARALLEL_VERTEX_SORT_THRESHOLD = (1ul << 16); - if (edges.size() >= PARALLEL_VERTEX_SORT_THRESHOLD) { - galois::ParallelSTL::sort( - edges.begin(), edges.end(), - [](auto const& a, auto const& b) { return a.first < b.first; }); - } else { - std::sort(edges.begin(), edges.end(), - [](auto const& a, auto const& b) { return a.first < b.first; }); - } - std::vector pfx_sum(edges.size()); galois::GReduceMax max_vertex_id; max_vertex_id.reset(); From 562ba70352a1a0421d19f5137d598bc4572831fd Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Sun, 21 Apr 2024 22:10:53 +0000 Subject: [PATCH 22/26] remove unused methods of LargeVector --- libgalois/include/galois/LargeVector.h | 43 +++----------------------- 1 file changed, 4 insertions(+), 39 deletions(-) diff --git a/libgalois/include/galois/LargeVector.h b/libgalois/include/galois/LargeVector.h index 53ed33cfd..c5a408121 100644 --- a/libgalois/include/galois/LargeVector.h +++ b/libgalois/include/galois/LargeVector.h @@ -24,6 +24,10 @@ namespace galois { * 2. All iterator methods (e.g. increment) preserve generation. * 3. It is undefined behavior to compare iterators across generations. * 4. Decreasing the container size invalidates some iterators. + * + * Note also that, like LargeArray, this class does not call constructors or + * destructors for elements. If you need to call constructors or destructors, + * you can use placement new and explicit destructor calls. */ template class LargeVector : public boost::noncopyable { @@ -120,25 +124,8 @@ class LargeVector : public boost::noncopyable { uint64_t size() const noexcept { return m_size; } - template - T& emplace_back(Args&&... args) { - if (m_size == m_capacity) { - ensure_capacity(m_size + 1); - } - return *new (m_data + m_size++) T(std::forward(args)...); - } - - T& push_back(const T& t) { return emplace_back(t); } - - T& push_back(T&& t) { return emplace_back(std::move(t)); } - T& operator[](size_t index) const { return m_data[index]; } - void pop_back() { - assert(m_size > 0); - m_data[--m_size].~T(); - } - /** * Note: unlike std::vector, resize does not call constructors or * destructors. @@ -163,26 +150,4 @@ class LargeVector : public boost::noncopyable { }; // namespace galois -namespace std { -template -ostream& operator<<(std::ostream& os, const galois::LargeVector& vec) { - for (uint64_t i = 0; i < vec.getSize(); i++) { - os << vec[i]; - if (i < vec.getSize() - 1) { - os << " "; - } - } - return os; -} - -template -istream& operator>>(istream& is, galois::LargeVector& vec) { - T value; - while (is >> value) { - vec.push_back(value); - } - return is; -} -} // namespace std - #endif From 84153fc73fe1645c15c2a98c62ab25835bd55f70 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Sun, 21 Apr 2024 22:22:08 +0000 Subject: [PATCH 23/26] fixup! remove unused methods of LargeVector --- libgalois/include/galois/LargeVector.h | 2 +- libgalois/test/large-vector.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libgalois/include/galois/LargeVector.h b/libgalois/include/galois/LargeVector.h index c5a408121..bd735c249 100644 --- a/libgalois/include/galois/LargeVector.h +++ b/libgalois/include/galois/LargeVector.h @@ -88,7 +88,7 @@ class LargeVector : public boost::noncopyable { if (m_fd == -1) throw std::runtime_error(std::string("creating memfd: ") + std::strerror(errno)); - ensure_capacity(initial_size); + resize(initial_size); } LargeVector() : LargeVector(1) {} diff --git a/libgalois/test/large-vector.cpp b/libgalois/test/large-vector.cpp index ac3ce6537..f2d0e5a6f 100644 --- a/libgalois/test/large-vector.cpp +++ b/libgalois/test/large-vector.cpp @@ -26,12 +26,13 @@ int main() { galois::SharedMemSys Galois_runtime; { - galois::LargeVector the_vector; + galois::LargeVector the_vector(1 << 21); // should use 4 hugepages std::vector refs; - for (size_t i = 0; i < (1 << 21); ++i) { - refs.emplace_back(&the_vector.emplace_back(i)); + refs.resize(1 << 21); + for (size_t i = 0; i < refs.size(); ++i) { + refs[i] = &the_vector.emplace_back(i); } for (size_t i = 0; i < (1 << 21); ++i) { @@ -63,7 +64,7 @@ int main() { the_vector.resize(0); GALOIS_ASSERT(addr == &the_vector[max_cap]); - // this should not actually allocate memory! + // this should only take 1 hugepage! galois::LargeVector huge(1ul << 40); huge[0] = 0; } From c23c43c9fc1cd61ff3de002bc733d27d75c633f7 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Sun, 21 Apr 2024 22:24:06 +0000 Subject: [PATCH 24/26] fixup! remove unused methods of LargeVector --- libgalois/include/galois/graphs/LS_LC_CSR_Graph.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h index 304282df4..dcc871fed 100644 --- a/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h +++ b/libgalois/include/galois/graphs/LS_LC_CSR_Graph.h @@ -195,7 +195,7 @@ class LS_LC_CSR_Graph : private boost::noncopyable { VertexRange vertices() { return VertexRange(begin(), end()); } VertexTopologyID addVertexTopologyOnly() { - m_vertices.emplace_back(); + m_vertices.resize(m_vertices.size() + 1); if constexpr (HasVertexData) { m_vertex_data.resize(m_vertices.size()); } From 693d17637b723410146634a3ef423a1d77916879 Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Sun, 21 Apr 2024 22:27:00 +0000 Subject: [PATCH 25/26] fixup! remove unused methods of LargeVector --- libgalois/test/large-vector.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libgalois/test/large-vector.cpp b/libgalois/test/large-vector.cpp index f2d0e5a6f..0e701f8f4 100644 --- a/libgalois/test/large-vector.cpp +++ b/libgalois/test/large-vector.cpp @@ -29,13 +29,12 @@ int main() { galois::LargeVector the_vector(1 << 21); // should use 4 hugepages - std::vector refs; - refs.resize(1 << 21); - for (size_t i = 0; i < refs.size(); ++i) { - refs[i] = &the_vector.emplace_back(i); + std::vector refs(the_vector.size()); + for (size_t i = 0; i < the_vector.size(); ++i) { + refs[i] = &the_vector[i]; } - for (size_t i = 0; i < (1 << 21); ++i) { + for (size_t i = 0; i < the_vector.size(); ++i) { GALOIS_ASSERT(*refs[i] == i); } } From 79ab8b4b7a091ec2bff9a9eb19506f4951a9bb4f Mon Sep 17 00:00:00 2001 From: Meyer Zinn Date: Sun, 21 Apr 2024 22:35:01 +0000 Subject: [PATCH 26/26] fixup! remove unused methods of LargeVector --- libgalois/test/large-vector.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libgalois/test/large-vector.cpp b/libgalois/test/large-vector.cpp index 0e701f8f4..0cd706dec 100644 --- a/libgalois/test/large-vector.cpp +++ b/libgalois/test/large-vector.cpp @@ -31,7 +31,8 @@ int main() { // should use 4 hugepages std::vector refs(the_vector.size()); for (size_t i = 0; i < the_vector.size(); ++i) { - refs[i] = &the_vector[i]; + the_vector[i] = i; + refs[i] = &the_vector[i]; } for (size_t i = 0; i < the_vector.size(); ++i) {