Skip to content

Commit

Permalink
Updates for TC. Add initializeELDACSR. Make DistArrayCSR and DistLoca…
Browse files Browse the repository at this point in the history
…lCSR have sorted edge lists when input graph is RMAT. Add iterator bookmark in vertex data. Add EdgeRange to get subset of vertex edges, needed for TC_Chunked_Algo. Add operator in CountedIterator
  • Loading branch information
pingle14 committed Apr 1, 2024
1 parent 48775a7 commit 1bcb81f
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 41 deletions.
11 changes: 5 additions & 6 deletions include/pando-lib-galois/graphs/dist_array_csr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ class DistArrayCSR {
*
* @param[in] edgeList This is an edgeList with the edges of each vertex.
*/
pando::Status initialize(pando::Vector<pando::Vector<std::uint64_t>> edgeList) {
pando::Status initialize(pando::Vector<pando::Vector<EdgeType>> edgeList) {
pando::Status err;
pando::Vector<galois::PlaceType> vec;
err = vec.initialize(pando::getPlaceDims().node.id);
Expand Down Expand Up @@ -490,7 +490,7 @@ class DistArrayCSR {
}

std::uint64_t edgeNums = 0;
for (pando::Vector<std::uint64_t> bucket : edgeList) {
for (pando::Vector<EdgeType> bucket : edgeList) {
edgeNums += bucket.size();
}
numVertices = edgeList.size();
Expand All @@ -517,10 +517,9 @@ class DistArrayCSR {

std::uint64_t edgeCurr = 0;
for (std::uint64_t vertexCurr = 0; vertexCurr < edgeList.size(); vertexCurr++) {
pando::Vector<std::uint64_t> edges = edgeList[vertexCurr];
for (auto edgesIt = edges.cbegin(); edgesIt != edges.cend(); edgesIt++, edgeCurr++) {
edgeDestinations[edgeCurr] = *edgesIt;
}
pando::Vector<EdgeType> edges = edgeList[vertexCurr];
for (EdgeType e : edges)
edgeDestinations[edgeCurr++] = e.dst;
vertexEdgeOffsets[vertexCurr] = edgeCurr;
vertexTokenIDs[vertexCurr] = vertexCurr;
}
Expand Down
14 changes: 14 additions & 0 deletions include/pando-lib-galois/graphs/dist_local_csr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,20 @@ class DistLocalCSR {
Vertex v1 = *(vPtr + 1);
return RefSpan<galois::HalfEdge>(v.edgeBegin, v1.edgeBegin - v.edgeBegin);
}

EdgeRange edges(pando::GlobalPtr<galois::Vertex> vPtr, uint64_t offset_st, uint64_t window_sz) {
Vertex v = *vPtr;
Vertex v1 = *(vPtr + 1);

auto beg = v.edgeBegin + offset_st;
if (beg > v1.edgeBegin)
return RefSpan<galois::HalfEdge>(v.edgeBegin, 0);
if (beg + window_sz <= v1.edgeBegin)
return RefSpan<galois::HalfEdge>(beg, window_sz);

return RefSpan<galois::HalfEdge>(beg, v1.edgeBegin - beg);
}

VertexDataRange vertexDataRange() noexcept {
return VertexDataRange{arrayOfCSRs, lift(arrayOfCSRs.get(0), vertexData.begin),
lift(arrayOfCSRs.get(arrayOfCSRs.size() - 1), vertexData.end),
Expand Down
1 change: 1 addition & 0 deletions include/pando-lib-galois/graphs/local_csr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct HalfEdge {

struct Vertex {
pando::GlobalPtr<HalfEdge> edgeBegin;
uint64_t iterator_offset = 0;
};
} // namespace galois

Expand Down
76 changes: 76 additions & 0 deletions include/pando-lib-galois/import/ingest_rmat_el.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#ifndef PANDO_LIB_GALOIS_IMPORT_INGEST_RMAT_EL_HPP_
#define PANDO_LIB_GALOIS_IMPORT_INGEST_RMAT_EL_HPP_

#include <algorithm>
#include <utility>

#include <pando-lib-galois/containers/dist_array.hpp>
Expand All @@ -26,6 +27,10 @@ struct ELEdge {
constexpr operator std::uint64_t() {
return src;
}

bool operator<(const ELEdge& other) const {
return (src == other.src) ? (dst < other.dst) : (src < other.src);
}
};

void loadELFilePerThread(
Expand All @@ -46,6 +51,65 @@ pando::Status elParse(const char* line, EdgeFunc efunc) {
return efunc(src, dst);
}

pando::Vector<pando::Vector<ELEdge>> reduceLocalEdges(
galois::PerThreadVector<pando::Vector<ELEdge>> localEdges, uint64_t numVertices);

template <typename VertexType, typename EdgeType>
galois::DistArrayCSR<VertexType, EdgeType> initializeELDACSR(pando::Array<char> filename,
std::uint64_t numVertices) {
galois::PerThreadVector<pando::Vector<ELEdge>> localEdges;
PANDO_CHECK(localEdges.initialize());

const std::uint64_t numThreads = localEdges.size() - pando::getPlaceDims().node.id;
galois::DistArray<galois::HashTable<std::uint64_t, std::uint64_t>> perThreadRename;
PANDO_CHECK(perThreadRename.initialize(localEdges.size()));

for (auto hashRef : perThreadRename) {
hashRef = galois::HashTable<std::uint64_t, std::uint64_t>{};
PANDO_CHECK(fmap(hashRef, initialize, 0));
}

std::uint64_t hosts = static_cast<std::uint64_t>(pando::getPlaceDims().node.id);

galois::WaitGroup wg;
PANDO_CHECK(wg.initialize(numThreads));
auto wgh = wg.getHandle();

PANDO_MEM_STAT_NEW_KERNEL("loadELFilePerThread Start");
for (std::uint64_t i = 0; i < numThreads; i++) {
pando::Place place = pando::Place{pando::NodeIndex{static_cast<std::int16_t>(i % hosts)},
pando::anyPod, pando::anyCore};
PANDO_CHECK(pando::executeOn(place, &galois::loadELFilePerThread, wgh, filename, 1, numThreads,
i, localEdges, perThreadRename, numVertices));
}
PANDO_CHECK(wg.wait());
PANDO_MEM_STAT_NEW_KERNEL("loadELFilePerThread End");

pando::Vector<pando::Vector<ELEdge>> edgeList = reduceLocalEdges(localEdges, numVertices);

#ifdef FREE
auto freePerThreadRename =
+[](galois::DistArray<galois::HashTable<std::uint64_t, std::uint64_t>> perThreadRename) {
for (galois::HashTable<std::uint64_t, std::uint64_t> hash : perThreadRename) {
hash.deinitialize();
}
perThreadRename.deinitialize();
};
PANDO_CHECK(pando::executeOn(pando::anyPlace, freePerThreadRename, perThreadRename));
#endif

using Graph = galois::DistArrayCSR<VertexType, EdgeType>;
Graph graph;
PANDO_CHECK(graph.initialize(edgeList));

for (uint64_t i = 0; i < numVertices; i++) {
pando::Vector<ELEdge> ev = edgeList[i];
ev.deinitialize();
edgeList[i] = std::move(ev);
}
return graph;
}

pando::Status generateEdgesPerVirtualHost(pando::GlobalRef<pando::Vector<ELVertex>> vertices,
std::uint64_t totalVertices, std::uint64_t vHostID,
std::uint64_t numVHosts);
Expand Down Expand Up @@ -146,6 +210,18 @@ galois::DistLocalCSR<VertexType, EdgeType> initializeELDLCSR(pando::Array<char>
auto [partEdges, renamePerHost] =
internal::partitionEdgesParallely(pHV, std::move(localEdges), v2PM);

galois::doAll(
partEdges, +[](pando::GlobalRef<pando::Vector<pando::Vector<ELEdge>>> edge_vectors) {
pando::Vector<pando::Vector<ELEdge>> evs_tmp = edge_vectors;
galois::doAll(
evs_tmp, +[](pando::GlobalRef<pando::Vector<ELEdge>> src_ev) {
pando::Vector<ELEdge> tmp = src_ev;
std::sort(tmp.begin(), tmp.end());
src_ev = tmp;
});
edge_vectors = evs_tmp;
});

using Graph = galois::DistLocalCSR<VertexType, EdgeType>;
Graph graph;
graph.template initializeAfterGather<galois::ELVertex, galois::ELEdge>(
Expand Down
4 changes: 4 additions & 0 deletions include/pando-lib-galois/utility/counted_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ struct CountedIterator {
return !(a == b);
}

friend bool operator<(const CountedIterator<It>& a, const CountedIterator<It>& b) {
return a.m_count < b.m_count && a.m_iter < b.m_iter;
}

friend pando::Place localityOf(CountedIterator<It>& a) {
return localityOf(a.m_iter);
}
Expand Down
31 changes: 31 additions & 0 deletions src/ingest_rmat_el.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,34 @@ pando::Status galois::generateEdgesPerVirtualHost(
}
return pando::Status::Success;
}

pando::Vector<pando::Vector<galois::ELEdge>> galois::reduceLocalEdges(
galois::PerThreadVector<pando::Vector<galois::ELEdge>> localEdges, uint64_t numVertices) {
pando::Vector<pando::Vector<galois::ELEdge>> reducedEL;
PANDO_CHECK(reducedEL.initialize(numVertices));

for (uint64_t i = 0; i < numVertices; i++) {
pando::Vector<galois::ELEdge> ev = reducedEL[i];
PANDO_CHECK(ev.initialize(0));
reducedEL[i] = std::move(ev);
}

for (std::uint64_t i = 0; i < localEdges.size(); i++) {
pando::Vector<pando::Vector<galois::ELEdge>> threadLocalEdges = *localEdges.get(i);
for (pando::Vector<galois::ELEdge> ev : threadLocalEdges) {
if (ev.size() > 0) {
ELEdge first_edge = ev[0];
uint64_t src = first_edge.src;
pando::Vector<galois::ELEdge> src_ev = reducedEL[src];
PANDO_CHECK(src_ev.append(&ev));
reducedEL[src] = std::move(src_ev);
}
}
}

galois::doAll(
reducedEL, +[](pando::Vector<galois::ELEdge> src_ev) {
std::sort(src_ev.begin(), src_ev.end());
});
return reducedEL;
}
49 changes: 26 additions & 23 deletions test/graphs/test_dist_array_csr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,30 @@
#include <pando-lib-galois/containers/dist_array.hpp>
#include <pando-lib-galois/graphs/dist_array_csr.hpp>
#include <pando-lib-galois/graphs/graph_traits.hpp>
#include <pando-lib-galois/import/ingest_rmat_el.hpp>
#include <pando-lib-galois/loops/do_all.hpp>
#include <pando-lib-galois/sync/wait_group.hpp>
#include <pando-rt/containers/vector.hpp>
#include <pando-rt/memory/memory_guard.hpp>
#include <pando-rt/pando-rt.hpp>
#include <pando-rt/sync/notification.hpp>

pando::Vector<pando::Vector<std::uint64_t>> generateFullyConnectedGraph(std::uint64_t SIZE) {
pando::Vector<pando::Vector<std::uint64_t>> vec;
using Graph = galois::DistArrayCSR<uint64_t, galois::ELEdge>;

pando::Vector<pando::Vector<galois::ELEdge>> generateFullyConnectedGraph(std::uint64_t SIZE) {
pando::Vector<pando::Vector<galois::ELEdge>> vec;
EXPECT_EQ(vec.initialize(SIZE), pando::Status::Success);
for (pando::GlobalRef<pando::Vector<std::uint64_t>> edges : vec) {
pando::Vector<std::uint64_t> inner;
for (pando::GlobalRef<pando::Vector<galois::ELEdge>> edges : vec) {
pando::Vector<galois::ELEdge> inner;
EXPECT_EQ(inner.initialize(0), pando::Status::Success);
edges = inner;
}

galois::doAll(
SIZE, vec, +[](std::uint64_t size, pando::GlobalRef<pando::Vector<std::uint64_t>> innerRef) {
pando::Vector<std::uint64_t> inner = innerRef;
SIZE, vec, +[](std::uint64_t size, pando::GlobalRef<pando::Vector<galois::ELEdge>> innerRef) {
pando::Vector<galois::ELEdge> inner = innerRef;
for (std::uint64_t i = 0; i < size; i++) {
EXPECT_EQ(inner.pushBack(i), pando::Status::Success);
EXPECT_EQ(inner.pushBack(galois::ELEdge{0, i}), pando::Status::Success);
}
innerRef = inner;
});
Expand All @@ -40,7 +43,7 @@ template <typename T>
pando::Status deleteVectorVector(pando::Vector<pando::Vector<T>> vec) {
auto err = galois::doAll(
vec, +[](pando::GlobalRef<pando::Vector<T>> innerRef) {
pando::Vector<std::uint64_t> inner = innerRef;
pando::Vector<T> inner = innerRef;
inner.deinitialize();
innerRef = inner;
});
Expand All @@ -51,26 +54,27 @@ pando::Status deleteVectorVector(pando::Vector<pando::Vector<T>> vec) {
TEST(DistArrayCSR, FullyConnected) {
constexpr std::uint64_t SIZE = 10;
constexpr std::uint64_t value = 0xDEADBEEF;
galois::DistArrayCSR<std::uint64_t, std::uint64_t> graph;
Graph graph;
auto vec = generateFullyConnectedGraph(SIZE);
graph.initialize(vec);
auto err = deleteVectorVector<std::uint64_t>(vec);
auto err = deleteVectorVector<galois::ELEdge>(vec);
EXPECT_EQ(err, pando::Status::Success);

for (std::uint64_t i = 0; i < SIZE; i++) {
EXPECT_EQ(graph.getNumEdges(i), SIZE);
graph.setData(i, value);
for (std::uint64_t j = 0; j < SIZE; j++) {
EXPECT_EQ(graph.getEdgeDst(i, j), j);
graph.setEdgeData(i, j, value);
graph.setEdgeData(i, j, galois::ELEdge{i, value});
}
}
for (std::uint64_t i = 0; i < SIZE; i++) {
EXPECT_EQ(graph.getNumEdges(i), SIZE);
EXPECT_EQ(graph.getData(i), value);
for (std::uint64_t j = 0; j < SIZE; j++) {
EXPECT_EQ(graph.getEdgeDst(i, j), j);
EXPECT_EQ(graph.getEdgeData(i, j), value);
galois::ELEdge actual = graph.getEdgeData(i, j);
EXPECT_EQ(actual.dst, value);
}
}
graph.deinitialize();
Expand All @@ -79,9 +83,9 @@ TEST(DistArrayCSR, FullyConnected) {
TEST(DistArrayCSR, TopologyIteratorsFor) {
constexpr std::uint64_t SIZE = 10;
auto vec = generateFullyConnectedGraph(SIZE);
galois::DistArrayCSR<std::uint64_t, std::uint64_t> graph;
Graph graph;
graph.initialize(vec);
auto err = deleteVectorVector<std::uint64_t>(std::move(vec));
auto err = deleteVectorVector<galois::ELEdge>(std::move(vec));
EXPECT_EQ(err, pando::Status::Success);

galois::WaitGroup wg;
Expand Down Expand Up @@ -115,8 +119,6 @@ TEST(DistArrayCSR, TopologyIteratorsFor) {
graph.deinitialize();
}

using Graph = galois::DistArrayCSR<std::uint64_t, std::uint64_t>;

struct GraphBools {
Graph graph;
pando::GlobalPtr<bool> ptr;
Expand All @@ -127,7 +129,7 @@ TEST(DistArrayCSR, TopologyVertexIteratorsDoAll) {
auto vec = generateFullyConnectedGraph(SIZE);
GraphBools gBools;
gBools.graph.initialize(vec);
auto err = deleteVectorVector<std::uint64_t>(std::move(vec));
auto err = deleteVectorVector<galois::ELEdge>(std::move(vec));
EXPECT_EQ(err, pando::Status::Success);

pando::GlobalPtr<bool> touchedBools;
Expand Down Expand Up @@ -161,7 +163,7 @@ TEST(DistArrayCSR, TopologyEdgeIteratorsDoAll) {
auto vec = generateFullyConnectedGraph(SIZE);
Graph g;
g.initialize(vec);
auto err = deleteVectorVector<std::uint64_t>(std::move(vec));
auto err = deleteVectorVector<galois::ELEdge>(std::move(vec));
EXPECT_EQ(err, pando::Status::Success);

pando::GlobalPtr<bool> touchedBools;
Expand Down Expand Up @@ -197,7 +199,7 @@ TEST(DistArrayCSR, DataVertexIteratorsDoAll) {
auto vec = generateFullyConnectedGraph(SIZE);
Graph g;
g.initialize(vec);
auto err = deleteVectorVector<std::uint64_t>(std::move(vec));
auto err = deleteVectorVector<galois::ELEdge>(std::move(vec));
EXPECT_EQ(err, pando::Status::Success);

galois::doAll(
Expand All @@ -219,20 +221,21 @@ TEST(DistArrayCSR, DataEdgeIteratorsDoAll) {
auto vec = generateFullyConnectedGraph(SIZE);
Graph g;
g.initialize(vec);
auto err = deleteVectorVector<std::uint64_t>(std::move(vec));
auto err = deleteVectorVector<galois::ELEdge>(std::move(vec));
EXPECT_EQ(err, pando::Status::Success);

for (typename Graph::VertexTopologyID vlid : g.vertices()) {
galois::doAll(
goodValue, g.edgeDataRange(vlid),
+[](std::uint64_t goodValue, pando::GlobalRef<std::uint64_t> eData) {
eData = goodValue;
+[](uint64_t goodValue, pando::GlobalRef<galois::ELEdge> eData) {
eData = galois::ELEdge{goodValue, goodValue};
});
}

for (std::uint64_t i = 0; i < g.size(); i++) {
for (std::uint64_t j = 0; j < g.getNumEdges(i); j++) {
EXPECT_EQ(g.getEdgeData(i, j), goodValue);
galois::ELEdge edge_data = g.getEdgeData(i, j);
EXPECT_EQ(edge_data.dst, goodValue);
}
}

Expand Down
Loading

0 comments on commit 1bcb81f

Please sign in to comment.