From 8d824be00661c4da92d9d24a0e497fd0615be596 Mon Sep 17 00:00:00 2001 From: AdityaAtulTewari Date: Wed, 17 Jul 2024 18:34:40 -0500 Subject: [PATCH 1/6] Fix small timer error (#128) --- pando-rt/src/init.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pando-rt/src/init.cpp b/pando-rt/src/init.cpp index 75d7f1c8..f151fe28 100644 --- a/pando-rt/src/init.cpp +++ b/pando-rt/src/init.cpp @@ -204,22 +204,22 @@ int main(int argc, char* argv[]) { (start.ru_utime.tv_sec * 1000000000 + start.ru_utime.tv_usec * 1000) + end.ru_stime.tv_sec * 1000000000 + end.ru_stime.tv_usec * 1000 - (start.ru_stime.tv_sec * 1000000000 + start.ru_stime.tv_usec * 1000)); - for(std::uint64_t i = 0; i < std::uint64_t(dims.core.x + 2); i++) { + for(std::uint64_t i = 0; i < std::uint64_t(dims.core.x + 1); i++) { SPDLOG_WARN("Idle time on node: {}, core: {} was {}", thisPlace.node.id, - std::int8_t((i == std::uint64_t(dims.core.x + 1)) ? -1 : i), + std::int8_t((i == std::uint64_t(dims.core.x)) ? -1 : i), idleCount.get(i)); SPDLOG_WARN("Pointer time on node: {}, core: {} was {}", thisPlace.node.id, - std::int8_t((i == std::uint64_t(dims.core.x + 1)) ? -1 : i), + std::int8_t((i == std::uint64_t(dims.core.x)) ? -1 : i), pointerCount.get(i)); SPDLOG_WARN("Scheduler time on node: {}, core: {} was {}", thisPlace.node.id, - std::int8_t((i == std::uint64_t(dims.core.x + 1)) ? -1 : i), + std::int8_t((i == std::uint64_t(dims.core.x)) ? -1 : i), schedulerCount.get(i)); SPDLOG_WARN("DoAll time on node: {}, core: {} was {}", thisPlace.node.id, - std::int8_t((i == std::uint64_t(dims.core.x + 1)) ? -1 : i), + std::int8_t((i == std::uint64_t(dims.core.x)) ? -1 : i), doAllCount.get(i)); } From e7ba8fa785f1b6d17aa4e28791e0750a1452da9c Mon Sep 17 00:00:00 2001 From: AdityaAtulTewari Date: Tue, 23 Jul 2024 16:38:25 -0500 Subject: [PATCH 2/6] Implementation of a naive policy (#130) * Implementation of a naive policy * Fixed wmd policies * Updates for Explicit policy in capturing benchmark information --- .gitignore | 1 + .../graphs/dist_local_csr.hpp | 2 +- .../import/ingest_rmat_el.hpp | 11 +- .../import/ingest_wmd_csv.hpp | 2 +- include/pando-lib-galois/loops/do_all.hpp | 120 +++++++++++++++++- .../bfs/include/pando-bfs-galois/sssp.hpp | 8 +- scripts/run-drv.sh | 4 +- src/ingest_rmat_el.cpp | 2 +- 8 files changed, 133 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 6d96daf0..e27da6ed 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,4 @@ deps/ #Stats Files *stats.csv +*.txt diff --git a/include/pando-lib-galois/graphs/dist_local_csr.hpp b/include/pando-lib-galois/graphs/dist_local_csr.hpp index 2136f4d1..7b4c1d17 100644 --- a/include/pando-lib-galois/graphs/dist_local_csr.hpp +++ b/include/pando-lib-galois/graphs/dist_local_csr.hpp @@ -854,7 +854,7 @@ class DistLocalCSR { galois::HostLocalStorage> pHV{}; PANDO_CHECK_RETURN(pHV.initialize()); - PANDO_CHECK_RETURN(galois::doAll( + PANDO_CHECK_RETURN(galois::doAllExplicitPolicy( partEdges, pHV, +[](HostLocalStorage>> partEdges, pando::GlobalRef> pHV) { diff --git a/include/pando-lib-galois/import/ingest_rmat_el.hpp b/include/pando-lib-galois/import/ingest_rmat_el.hpp index c0303bbb..adf7c5de 100644 --- a/include/pando-lib-galois/import/ingest_rmat_el.hpp +++ b/include/pando-lib-galois/import/ingest_rmat_el.hpp @@ -92,7 +92,7 @@ ReturnType initializeELDACSR(pando::Array filename, std::uint64_t numVerti galois::WaitGroup freeWaiter; PANDO_CHECK(freeWaiter.initialize(0)); auto freeWGH = freeWaiter.getHandle(); - galois::doAll( + galois::doAllExplicitPolicy( freeWGH, perThreadRename, +[](galois::HashTable hash) { hash.deinitialize(); }); @@ -158,7 +158,7 @@ ReturnType initializeELDLCSR(pando::Array filename, std::uint64_t numVerti galois::WaitGroup freeWaiter; PANDO_CHECK(freeWaiter.initialize(0)); auto freeWGH = freeWaiter.getHandle(); - galois::doAll( + galois::doAllExplicitPolicy( freeWGH, perThreadRename, +[](galois::HashTable hash) { hash.deinitialize(); }); @@ -204,15 +204,16 @@ ReturnType initializeELDLCSR(pando::Array filename, std::uint64_t numVerti } }; - PANDO_CHECK(galois::doAll(generateVerticesState, pHV, generateVerticesPerHost)); + PANDO_CHECK(galois::doAllExplicitPolicy(generateVerticesState, pHV, + generateVerticesPerHost)); auto [partEdges, renamePerHost] = internal::partitionEdgesParallely(pHV, std::move(localReadEdges), hostLocalV2PM); - galois::doAll( + galois::doAllExplicitPolicy( partEdges, +[](pando::GlobalRef>> edge_vectors) { pando::Vector> evs_tmp = edge_vectors; - galois::doAll( + galois::doAllExplicitPolicy( evs_tmp, +[](pando::GlobalRef> src_ev) { pando::Vector tmp = src_ev; std::sort(tmp.begin(), tmp.end()); diff --git a/include/pando-lib-galois/import/ingest_wmd_csv.hpp b/include/pando-lib-galois/import/ingest_wmd_csv.hpp index d54cd1bf..04f1b630 100644 --- a/include/pando-lib-galois/import/ingest_wmd_csv.hpp +++ b/include/pando-lib-galois/import/ingest_wmd_csv.hpp @@ -104,7 +104,7 @@ galois::DistLocalCSR initializeWMDDLCSR(pando::Array galois::WaitGroup freeWaiter; PANDO_CHECK(freeWaiter.initialize(0)); auto freeWGH = freeWaiter.getHandle(); - galois::doAll( + galois::doAllExplicitPolicy( freeWGH, perThreadRename, +[](galois::HashTable hash) { hash.deinitialize(); }); diff --git a/include/pando-lib-galois/loops/do_all.hpp b/include/pando-lib-galois/loops/do_all.hpp index 11e90e69..c0e30557 100644 --- a/include/pando-lib-galois/loops/do_all.hpp +++ b/include/pando-lib-galois/loops/do_all.hpp @@ -53,9 +53,15 @@ enum SchedulerPolicy { UNSAFE_STRIPE, CORE_STRIPE, NODE_ONLY, + NAIVE, }; +#ifndef PANDO_SCHED constexpr SchedulerPolicy CURRENT_SCHEDULER_POLICY = SchedulerPolicy::RANDOM; +#else +constexpr SchedulerPolicy CURRENT_SCHEDULER_POLICY = PANDO_SCHED; +#endif + constexpr SchedulerPolicy EVENLY_PARITION_SCHEDULER_POLICY = SchedulerPolicy::CORE_STRIPE; template @@ -92,6 +98,11 @@ pando::Place schedulerImpl(pando::Place preferredLocality, pando::Place(preferredLocality.node, pando::anyPod, pando::CoreIndex(coreIdx, 0)); } else if constexpr (Policy == NODE_ONLY) { preferredLocality = pando::Place(preferredLocality.node, pando::anyPod, pando::anyCore); + } else if constexpr (Policy == NAIVE) { + auto coreIdx = perCoreDist.getLocal()(perCoreRNG.getLocal()); + assert(coreIdx < pando::getCoreDims().x); + preferredLocality = + pando::Place(pando::getCurrentNode(), pando::anyPod, pando::CoreIndex(coreIdx, 0)); } else { PANDO_ABORT("SCHEDULER POLICY NOT IMPLEMENTED"); } @@ -180,7 +191,6 @@ class DoAll { const L& localityFunc) { counter::HighResolutionCount doAllTimer; doAllTimer.start(); - LoopLocalSchedulerStruct loopLocal{}; pando::Status err = pando::Status::Success; const auto end = range.end(); @@ -191,7 +201,7 @@ class DoAll { for (auto curr = range.begin(); curr != end; curr++) { // Required hack without workstealing - auto nodePlace = scheduler(localityFunc(s, *curr), loopLocal); + auto nodePlace = localityFunc(s, *curr); err = pando::executeOn(nodePlace, ¬ifyFunc, func, s, curr, wgh); if (err != pando::Status::Success) { @@ -249,6 +259,37 @@ class DoAll { return err; } + template + static pando::Status doAllExplicitPolicy(WaitGroup::HandleType wgh, State s, R& range, + const F& func) { + counter::HighResolutionCount doAllTimer; + doAllTimer.start(); + LoopLocalSchedulerStruct loopLocal{}; + pando::Status err = pando::Status::Success; + + const auto end = range.end(); + + std::uint64_t iter = 0; + std::uint64_t size = range.size(); + wgh.add(size); + + for (auto curr = range.begin(); curr != end; curr++) { + // Required hack without workstealing + auto nodePlace = schedulerImpl(localityOf(curr), loopLocal); + err = pando::executeOn(nodePlace, ¬ifyFunc, func, s, curr, + wgh); + if (err != pando::Status::Success) { + for (std::uint64_t i = iter; i < size; i++) { + wgh.done(); + } + return err; + } + iter++; + } + counter::recordHighResolutionEvent(doAllCount, doAllTimer); + return err; + } + /** * @brief This is the do_all loop from galois which takes a rang and lifts a function to it, and * adds a barrier afterwards. @@ -291,6 +332,35 @@ class DoAll { return err; } + template + static pando::Status doAllExplicitPolicy(WaitGroup::HandleType wgh, R& range, const F& func) { + counter::HighResolutionCount doAllTimer; + doAllTimer.start(); + LoopLocalSchedulerStruct loopLocal{}; + pando::Status err = pando::Status::Success; + + const auto end = range.end(); + + std::uint64_t iter = 0; + const std::uint64_t size = range.size(); + wgh.add(size); + + for (auto curr = range.begin(); curr != end; curr++) { + // Required hack without workstealing + auto nodePlace = schedulerImpl(localityOf(curr), loopLocal); + err = pando::executeOn(nodePlace, ¬ifyFunc, func, curr, wgh); + if (err != pando::Status::Success) { + for (std::uint64_t i = iter; i < size; i++) { + wgh.done(); + } + return err; + } + iter++; + } + counter::recordHighResolutionEvent(doAllCount, doAllTimer); + return err; + } + /** * @brief This is the do_all loop from galois which takes a range and lifts a function to it, and * adds a barrier afterwards. @@ -342,6 +412,20 @@ class DoAll { return err; } + template + static pando::Status doAllExplicitPolicy(State s, R& range, const F& func) { + pando::Status err; + WaitGroup wg; + err = wg.initialize(0); + if (err != pando::Status::Success) { + return err; + } + doAllExplicitPolicy(wg.getHandle(), s, range, func); + err = wg.wait(); + wg.deinitialize(); + return err; + } + /** * @brief This is the do_all loop from galois which takes a range and lifts a function to it, and * adds a barrier afterwards. @@ -366,6 +450,21 @@ class DoAll { return err; } + template + static pando::Status doAllExplicitPolicy(R& range, const F& func) { + pando::Status err; + WaitGroup wg; + err = wg.initialize(0); + if (err != pando::Status::Success) { + return err; + } + doAllExplicitPolicy(wg.getHandle(), range, func); + + err = wg.wait(); + wg.deinitialize(); + return err; + } + /** * @brief This is the do_all loop from galois which takes an integer number of work items and * lifts a function to it, and adds a barrier afterwards. Work is spread evenly across all pxns @@ -498,10 +597,18 @@ template pando::Status doAll(WaitGroup::HandleType wgh, State s, R range, const F& func) { return DoAll::doAll(wgh, s, range, func); } +template +pando::Status doAllExplicitPolicy(WaitGroup::HandleType wgh, State s, R range, const F& func) { + return DoAll::doAllExplicitPolicy(wgh, s, range, func); +} template pando::Status doAll(WaitGroup::HandleType wgh, R range, const F& func) { return DoAll::doAll(wgh, range, func); } +template +pando::Status doAllExplicitPolicy(WaitGroup::HandleType wgh, R range, const F& func) { + return DoAll::doAllExplicitPolicy(wgh, range, func); +} template pando::Status doAll(State s, R range, const F& func, const L& localityFunc) { return DoAll::doAll(s, range, func, localityFunc); @@ -510,11 +617,18 @@ template pando::Status doAll(State s, R range, const F& func) { return DoAll::doAll(s, range, func); } +template +pando::Status doAllExplicitPolicy(State s, R range, const F& func) { + return DoAll::doAllExplicitPolicy(s, range, func); +} template pando::Status doAll(R range, const F& func) { return DoAll::doAll(range, func); } - +template +pando::Status doAllExplicitPolicy(R range, const F& func) { + return DoAll::doAllExplicitPolicy(range, func); +} template pando::Status doAllEvenlyPartition(WaitGroup::HandleType wgh, State s, uint64_t workItems, const F& func) { diff --git a/microbench/bfs/include/pando-bfs-galois/sssp.hpp b/microbench/bfs/include/pando-bfs-galois/sssp.hpp index a3e8d54a..aa0c9474 100644 --- a/microbench/bfs/include/pando-bfs-galois/sssp.hpp +++ b/microbench/bfs/include/pando-bfs-galois/sssp.hpp @@ -134,7 +134,7 @@ pando::Status SSSP_DLCSR( state.dist = 0; #ifdef PANDO_STAT_TRACE_ENABLE - PANDO_CHECK(galois::doAll( + PANDO_CHECK(galois::doAllExplicitPolicy( wgh, phbfs, +[](pando::Vector) { PANDO_MEM_STAT_NEW_KERNEL("BFS Start"); })); @@ -168,7 +168,7 @@ pando::Status SSSP_DLCSR( } #ifdef PANDO_STAT_TRACE_ENABLE - PANDO_CHECK(galois::doAll( + PANDO_CHECK(galois::doAllExplicitPolicy( wgh, phbfs, +[](pando::Vector) { PANDO_MEM_STAT_NEW_KERNEL("BFS END"); })); @@ -311,7 +311,7 @@ pando::Status SSSPMDLCSR(G& graph, std::uint64_t src, HostLocalStorage( wgh, toRead, +[](MDWorkList) { PANDO_MEM_STAT_NEW_KERNEL("BFS Start"); })); @@ -360,7 +360,7 @@ pando::Status SSSPMDLCSR(G& graph, std::uint64_t src, HostLocalStorage( wgh, toRead, +[](MDWorkList) { PANDO_MEM_STAT_NEW_KERNEL("BFS END"); })); diff --git a/scripts/run-drv.sh b/scripts/run-drv.sh index b6d4dda7..6b2f4777 100755 --- a/scripts/run-drv.sh +++ b/scripts/run-drv.sh @@ -22,7 +22,7 @@ usage: preprun -n prog [program args] " } -HOST_THREADS="${HOST_THREADS:-16}" +HOST_THREADS="${HOST_THREADS:-1}" HOSTS="${HOSTS:-1}" PROCS="${PROCS:-2}" CORES="${CORES:-8}" @@ -72,7 +72,7 @@ shift ${DBG} sst -n ${HOST_THREADS} \ "${LAUNCH_SCRIPT}" -- \ --with-command-processor="${PROG}" \ - --num-pxn=${PROCS} \ + --num-pxn=${HOSTS} \ --pod-cores=${CORES} \ --core-threads=${HARTS} \ --drvx-stack-in-l1sp \ diff --git a/src/ingest_rmat_el.cpp b/src/ingest_rmat_el.cpp index a17a8727..096e3949 100644 --- a/src/ingest_rmat_el.cpp +++ b/src/ingest_rmat_el.cpp @@ -92,7 +92,7 @@ pando::Vector> galois::reduceLocalEdges( } } - galois::doAll( + galois::doAllExplicitPolicy( reducedEL, +[](pando::Vector src_ev) { std::sort(src_ev.begin(), src_ev.end()); }); From 1dcd7eab432ff0dea96a20f268b1ba4097c08af9 Mon Sep 17 00:00:00 2001 From: Brenden Elgarten <32827342+elgarten@users.noreply.github.com> Date: Thu, 25 Jul 2024 17:30:25 -0500 Subject: [PATCH 3/6] update global_ptr.cpp to compile with PANDO_MEM_TRACE_OR_STAT (#131) --- pando-rt/src/global_ptr.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pando-rt/src/global_ptr.cpp b/pando-rt/src/global_ptr.cpp index 51780098..31b21651 100644 --- a/pando-rt/src/global_ptr.cpp +++ b/pando-rt/src/global_ptr.cpp @@ -317,11 +317,11 @@ void bulkMemcpy(GlobalAddress srcGlobalAddr, std::size_t n, GlobalAddress dstGlo counter::recordHighResolutionEvent(pointerCount, pointerTimer); } else if(nodeIdxSrc == Nodes::getCurrentNode()) { // remote store; send remote store request and wait for it to finish + Nodes::AckHandle handle; + void* srcNativePtr = Memory::getNativeAddress(srcGlobalAddr); #if PANDO_MEM_TRACE_OR_STAT MemTraceLogger::log("DMA", nodeIdxSrc, nodeIdxDst, n, srcNativePtr, srcGlobalAddr); #endif - Nodes::AckHandle handle; - void* srcNativePtr = Memory::getNativeAddress(srcGlobalAddr); if (auto status = Nodes::store(nodeIdxDst, dstGlobalAddr, n, srcNativePtr, handle); status != Status::Success) { SPDLOG_ERROR("Store error: {}", status); @@ -340,6 +340,7 @@ void bulkMemcpy(GlobalAddress srcGlobalAddr, std::size_t n, GlobalAddress dstGlo PANDO_ABORT("Load error"); } #if PANDO_MEM_TRACE_OR_STAT + void *srcNativePtr = Memory::getNativeAddress(srcGlobalAddr); MemTraceLogger::log("STORE", nodeIdxSrc, nodeIdxSrc, n, srcNativePtr, srcGlobalAddr); #endif From 57cdb90a30c6a48e5992d859e38f60d6119ae2e9 Mon Sep 17 00:00:00 2001 From: AdityaAtulTewari Date: Thu, 25 Jul 2024 18:13:28 -0500 Subject: [PATCH 4/6] Symlink for pando-drv configs. (#132) * Update Dockerfile for easy python changes to drv configs * Updates for properly exporting files that manage drv implementations --- .dockerignore | 1 + Dockerfile.dev | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..012e612f --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +pando-drv/tests diff --git a/Dockerfile.dev b/Dockerfile.dev index 5d12c6cf..c34bcf0e 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -82,6 +82,8 @@ RUN cd /dependencies && \ RUN ln -s /dependencies/install /dependencies/pando-drv/install +RUN ln -s /pando/pando-drv/tests /dependencies/pando-drv/tests + FROM ${DRIVEX_IMAGE} AS drivex_wrapper # Base ci image @@ -132,7 +134,6 @@ RUN if [ "${IS_CI}" != "true" ] ; then \ powerline \ zsh \ valgrind \ - sudo \ doxygen \ texlive-latex-extra \ texlive-font-utils \ @@ -146,7 +147,7 @@ ARG UID ARG GID RUN if [ "${UNAME}" != "root" ] ; then groupadd -g ${GID} ${UNAME} \ - && useradd -ms /bin/bash -u "${UID}" -g "${GID}" ${UNAME} ; fi + && useradd -ms /bin/bash -u "${UID}" -g "${GID}" ${UNAME}; fi RUN mkdir -p /home/${UNAME} \ && chown ${UNAME}:${UNAME} /home/${UNAME} From 07cd7f31b6e28356d9fe6de6b3dcb0de760d26f5 Mon Sep 17 00:00:00 2001 From: AdityaAtulTewari Date: Fri, 26 Jul 2024 01:58:41 -0500 Subject: [PATCH 5/6] Added inner-vector in order to help with interior locality inference (#133) --- .../containers/inner_vector.hpp | 366 +++++++++++ test/containers/CMakeLists.txt | 1 + test/containers/test_inner_vector.cpp | 568 ++++++++++++++++++ 3 files changed, 935 insertions(+) create mode 100644 include/pando-lib-galois/containers/inner_vector.hpp create mode 100644 test/containers/test_inner_vector.cpp diff --git a/include/pando-lib-galois/containers/inner_vector.hpp b/include/pando-lib-galois/containers/inner_vector.hpp new file mode 100644 index 00000000..266b8edc --- /dev/null +++ b/include/pando-lib-galois/containers/inner_vector.hpp @@ -0,0 +1,366 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2023. University of Texas at Austin. All rights reserved. + +// SPDX-License-Identifier: MIT +/* Copyright (c) 2024. University of Texas at Austin. All rights reserved. */ + +#ifndef PANDO_LIB_GALOIS_CONTAINERS_INNER_VECTOR_HPP_ +#define PANDO_LIB_GALOIS_CONTAINERS_INNER_VECTOR_HPP_ + +#include + +#include "pando-rt/export.h" + +#include +#include + +namespace galois { + +template +class GlobalPtrInnerLocality { + pando::GlobalPtr m_ptr; + +public: + using iterator_category = std::random_access_iterator_tag; + using difference_type = std::int64_t; + using value_type = T; + using pointer = pando::GlobalPtr; + using reference = pando::GlobalRef; + + explicit GlobalPtrInnerLocality(pando::GlobalPtr ptr) : m_ptr(ptr) {} + + constexpr GlobalPtrInnerLocality() noexcept = default; + constexpr GlobalPtrInnerLocality(GlobalPtrInnerLocality&&) noexcept = default; + constexpr GlobalPtrInnerLocality(const GlobalPtrInnerLocality&) noexcept = default; + ~GlobalPtrInnerLocality() = default; + + constexpr GlobalPtrInnerLocality& operator=(const GlobalPtrInnerLocality&) noexcept = default; + constexpr GlobalPtrInnerLocality& operator=(GlobalPtrInnerLocality&&) noexcept = default; + + reference operator*() const noexcept { + return *m_ptr; + } + + reference operator*() noexcept { + return *m_ptr; + } + + pointer operator->() { + return m_ptr; + } + + GlobalPtrInnerLocality& operator++() { + m_ptr++; + return *this; + } + + GlobalPtrInnerLocality operator++(int) { + GlobalPtrInnerLocality tmp = *this; + ++(*this); + return tmp; + } + + GlobalPtrInnerLocality& operator--() { + m_ptr--; + return *this; + } + + GlobalPtrInnerLocality operator--(int) { + GlobalPtrInnerLocality tmp = *this; + --(*this); + return tmp; + } + + constexpr GlobalPtrInnerLocality operator+(std::uint64_t n) const noexcept { + return GlobalPtrInnerLocality(m_ptr + n); + } + + constexpr GlobalPtrInnerLocality& operator+=(std::uint64_t n) noexcept { + m_ptr += n; + return *this; + } + + constexpr GlobalPtrInnerLocality operator-(std::uint64_t n) const noexcept { + return GlobalPtrInnerLocality(m_ptr - n); + } + + constexpr difference_type operator-(GlobalPtrInnerLocality b) const noexcept { + return m_ptr - b.m_ptr; + } + + reference operator[](std::uint64_t n) noexcept { + return m_ptr[n]; + } + + reference operator[](std::uint64_t n) const noexcept { + return m_ptr[n]; + } + + friend bool operator==(const GlobalPtrInnerLocality& a, const GlobalPtrInnerLocality& b) { + return a.m_ptr == b.m_ptr; + } + + friend bool operator!=(const GlobalPtrInnerLocality& a, const GlobalPtrInnerLocality& b) { + return !(a == b); + } + + friend bool operator<(const GlobalPtrInnerLocality& a, const GlobalPtrInnerLocality& b) { + return a.m_ptr < b.m_ptr; + } + + friend bool operator<=(const GlobalPtrInnerLocality& a, const GlobalPtrInnerLocality& b) { + return a.m_ptr <= b.m_ptr; + } + + friend bool operator>(const GlobalPtrInnerLocality& a, const GlobalPtrInnerLocality& b) { + return a.m_ptr > b.m_ptr; + } + + friend bool operator>=(const GlobalPtrInnerLocality& a, const GlobalPtrInnerLocality& b) { + return a.m_ptr >= b.m_ptr; + } + + friend pando::Place localityOf(GlobalPtrInnerLocality& a) { + T val = *a.m_ptr; + return galois::localityOf(val); + } +}; + +template +class InnerVector { + pando::Vector m_vec; + +public: + using iterator = galois::GlobalPtrInnerLocality; + using const_iterator = galois::GlobalPtrInnerLocality; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + explicit constexpr InnerVector(pando::Vector&& v) : m_vec(std::move(v)) {} + + constexpr InnerVector() noexcept = default; + + constexpr InnerVector(InnerVector&&) noexcept = default; + constexpr InnerVector(const InnerVector&) noexcept = default; + + ~InnerVector() = default; + + constexpr InnerVector& operator=(const InnerVector&) noexcept = default; + constexpr InnerVector& operator=(InnerVector&&) noexcept = default; + + [[nodiscard]] pando::Status initialize(std::uint64_t size, pando::Place place, + pando::MemoryType memoryType) { + return m_vec.initialize(size, place, memoryType); + } + + [[nodiscard]] pando::Status initialize(std::uint64_t size) { + return m_vec.initialize(size); + } + + /** + * @brief Deinitializes the container. + */ + void deinitialize() { + m_vec.deinitialize(); + } + + /** + * @brief Returns the memory this vector is allocated in. + */ + pando::MemoryType getMemoryType() const noexcept { + return m_vec.getMemoryType(); + } + + /** + * @brief Reserves space in the container for at least @p nextCapacity number of elements. + * + * @note If the new capacity is less that the current capacity, the function has not effect. + * @note The function does not change the size of the container and does not initialize the new + * elements. + * @note If the container has not been initialized, then the memory will be @ref MemoryType::Main. + * + * @param[in] nextCapacity new capacity of the container in elements + */ + [[nodiscard]] pando::Status reserve(std::uint64_t nextCapacity) { + return m_vec.reserve(nextCapacity); + } + + /** + * @brief this function resizes the array + * + * @note the implementation is simple because T must be trivially copyable. + * + * @param[in] newSize the new desired size + **/ + [[nodiscard]] pando::Status resize(std::uint64_t newSize) { + return m_vec.resize(newSize); + } + + /** + * @brief clear the vector + */ + void clear() { + m_vec.clear(); + } + + constexpr std::uint64_t capacity() const noexcept { + return m_vec.capacity(); + } + + constexpr bool empty() const noexcept { + return m_vec.empty(); + } + + constexpr auto get(std::uint64_t pos) { + return m_vec.get(pos); + } + + constexpr auto operator[](std::uint64_t pos) { + return m_vec[pos]; + } + + constexpr auto operator[](std::uint64_t pos) const { + return m_vec[pos]; + } + + constexpr pando::GlobalPtr data() noexcept { + return m_vec.data(); + } + + constexpr pando::GlobalPtr data() const noexcept { + return m_vec.data(); + } + + constexpr std::uint64_t size() const noexcept { + return m_vec.size(); + } + + /** + * @brief Appends the element to the end of the vector. + * + * @warning If the operation will increase the size of the container past its capacity, a + * realocation takes places. + * + * @param[in] value element to append + */ + [[nodiscard]] pando::Status pushBack(const T& value) { + return m_vec.pushBack(value); + } + + /** + * @copydoc pushBack(const T&) + */ + [[nodiscard]] pando::Status pushBack(T&& value) { + return m_vec.pushBack(value); + } + + // TODO(AdityaAtulTewari) Whenever it is time for performance counters they need to be encoded + // properly + /** + * @brief Copies data from one vector to another + * + * @note Super useful for doing bulk data transfers from remote sources + * @warning Assumes that this vector is not initialized. + * @warning Will allocate memory in local main memory + * + * @param from this is the vector we are copying from + */ + [[nodiscard]] pando::Status assign(pando::GlobalPtr> from) { + return m_vec.assign(from); + } + + // TODO(AdityaAtulTewari) Whenever it is time for performance counters they need to be encoded + // properly + /** + * @brief Copies data from one vector and appends it to another + * + * @note Super useful for doing bulk data transfers from remote sources + * + * @param from this is the vector we are copying from + */ + [[nodiscard]] pando::Status append(pando::GlobalPtr> from) { + return m_vec.append(from); + } + + iterator begin() noexcept { + return iterator(data()); + } + + const_iterator begin() const noexcept { + return const_iterator(data()); + } + + const_iterator cbegin() const noexcept { + return const_iterator(data()); + } + + iterator end() noexcept { + return iterator(data() + size()); + } + + const_iterator end() const noexcept { + return const_iterator(data() + size()); + } + + const_iterator cend() const noexcept { + return const_iterator(data() + size()); + } + + /** + * @brief reverse iterator to the first element + */ + reverse_iterator rbegin() noexcept { + return reverse_iterator(end()--); + } + + /** + * @copydoc rbegin() + */ + reverse_iterator rbegin() const noexcept { + return reverse_iterator(end()--); + } + + /** + * @copydoc rbegin() + */ + const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(cend()--); + } + + /** + * reverse iterator to the last element + */ + reverse_iterator rend() noexcept { + return reverse_iterator(begin()--); + } + + /** + * @copydoc rend() + */ + reverse_iterator rend() const noexcept { + return reverse_iterator(begin()--); + } + + /** + * @copydoc rend() + */ + const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(cbegin()--); + } +}; + +/// @ingroup ROOT +template +bool operator==(const InnerVector& lhs, const InnerVector& rhs) noexcept { + return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +/// @ingroup ROOT +template +bool operator!=(const InnerVector& lhs, const InnerVector& rhs) noexcept { + return !(lhs == rhs); +} + +} // namespace galois + +#endif // PANDO_LIB_GALOIS_CONTAINERS_INNER_VECTOR_HPP_ diff --git a/test/containers/CMakeLists.txt b/test/containers/CMakeLists.txt index a2f6182d..7cab8a8a 100644 --- a/test/containers/CMakeLists.txt +++ b/test/containers/CMakeLists.txt @@ -10,3 +10,4 @@ pando_add_driver_test(test_host_local_storage test_host_local_storage.cpp) pando_add_driver_test(test_thread_local_storage test_thread_local_storage.cpp) pando_add_driver_test(test_thread_local_vector test_thread_local_vector.cpp) pando_add_driver_test(test_host_cached_array test_host_cached_array.cpp) +pando_add_driver_test(test_inner_vector test_inner_vector.cpp) diff --git a/test/containers/test_inner_vector.cpp b/test/containers/test_inner_vector.cpp new file mode 100644 index 00000000..59dee911 --- /dev/null +++ b/test/containers/test_inner_vector.cpp @@ -0,0 +1,568 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2023. University of Texas at Austin. All rights reserved. + +// SPDX-License-Identifier: MIT +/* Copyright (c) 2024. University of Texas at Austin. All rights reserved. */ + +#include + +#include "pando-rt/export.h" + +#include +#include + +TEST(InnerVector, Empty) { + galois::InnerVector vector; + EXPECT_EQ(vector.initialize(0), pando::Status::Success); + EXPECT_TRUE(vector.empty()); + EXPECT_EQ(vector.size(), 0); + EXPECT_EQ(vector.capacity(), 0); + + vector.deinitialize(); + EXPECT_EQ(vector.capacity(), 0); + EXPECT_EQ(vector.size(), 0); +} + +TEST(InnerVector, Initialize) { + const std::uint64_t size = 10; + + galois::InnerVector vector; + EXPECT_EQ(vector.initialize(size), pando::Status::Success); + EXPECT_FALSE(vector.empty()); + EXPECT_EQ(vector.size(), size); + EXPECT_EQ(vector.capacity(), size); + + for (std::uint64_t i = 0; i < size; i++) { + vector[i] = i; + } + + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(vector[i], i); + } + + vector.deinitialize(); + EXPECT_EQ(vector.capacity(), 0); + EXPECT_EQ(vector.size(), 0); +} + +TEST(InnerVector, PushBack) { + const std::uint64_t size = 10; + const std::uint64_t newCap = 16; + + galois::InnerVector vector; + EXPECT_EQ(vector.initialize(size), pando::Status::Success); + + for (std::uint64_t i = 0; i < size; i++) { + vector[i] = i; + } + + EXPECT_EQ(vector.pushBack(size), pando::Status::Success); + + // This is only for power of 2 allocators + EXPECT_EQ(vector.capacity(), newCap); + EXPECT_FALSE(vector.empty()); + EXPECT_EQ(vector.size(), size + 1); + + for (std::uint64_t i = 0; i < size + 1; i++) { + EXPECT_EQ(vector[i], i); + } + + for (std::uint64_t i = size + 1; i < newCap; i++) { + EXPECT_EQ(vector.pushBack(i), pando::Status::Success); + + EXPECT_EQ(vector.capacity(), newCap); + EXPECT_FALSE(vector.empty()); + EXPECT_EQ(vector.size(), i + 1); + } + + for (std::uint64_t i = 0; i < newCap; i++) { + EXPECT_EQ(vector[i], i); + } + + vector.deinitialize(); +} + +TEST(InnerVector, Clear) { + const std::uint64_t size = 10; + + galois::InnerVector vector; + EXPECT_EQ(vector.initialize(size), pando::Status::Success); + + for (std::uint64_t i = 0; i < size; i++) { + vector[i] = i; + } + + vector.clear(); + EXPECT_EQ(vector.size(), 0); + EXPECT_TRUE(vector.empty()); + EXPECT_EQ(vector.capacity(), size); + + vector.deinitialize(); +} + +TEST(InnerVector, RemotePushBack) { + auto f = +[](pando::Notification::HandleType done) { + auto pushBackF = +[](pando::Notification::HandleType done, + pando::GlobalPtr> vectorPtr) { + auto vector = static_cast>(*vectorPtr); + EXPECT_EQ(vector.initialize(0), pando::Status::Success); + EXPECT_EQ(vector.reserve(1), pando::Status::Success); + EXPECT_EQ(vector.pushBack(1u), pando::Status::Success); + EXPECT_EQ(vector.pushBack(2u), pando::Status::Success); + EXPECT_EQ(vector.size(), 2); + *vectorPtr = vector; + done.notify(); + }; + + galois::InnerVector vector; + pando::Notification innerNotification; + EXPECT_EQ(innerNotification.init(), pando::Status::Success); + EXPECT_EQ(pando::executeOn(pando::Place{pando::NodeIndex{0}, pando::anyPod, pando::anyCore}, + pushBackF, innerNotification.getHandle(), + pando::GlobalPtr>(&vector)), + pando::Status::Success); + innerNotification.wait(); + + EXPECT_EQ(vector.size(), 2u); + EXPECT_EQ(vector[0], 1u); + EXPECT_EQ(vector[1], 2u); + + vector.deinitialize(); + + done.notify(); + }; + + pando::Notification notification; + EXPECT_EQ(notification.init(), pando::Status::Success); + EXPECT_EQ(pando::executeOn(pando::Place{pando::NodeIndex{0}, pando::anyPod, pando::anyCore}, f, + notification.getHandle()), + pando::Status::Success); + notification.wait(); +} + +TEST(InnerVector, StressCreateDestroy) { + const std::uint64_t requests = 10; + pando::NotificationArray notifications; + EXPECT_EQ(notifications.init(requests), pando::Status::Success); + for (std::uint64_t i = 0; i < requests; i++) { + EXPECT_EQ(pando::executeOn( + pando::Place{pando::NodeIndex{1}, pando::anyPod, pando::anyCore}, + +[](pando::Notification::HandleType done) { + constexpr auto size = 1; + galois::InnerVector vec; + EXPECT_EQ(vec.initialize(size), pando::Status::Success); + vec.deinitialize(); + done.notify(); + }, + notifications.getHandle(i)), + pando::Status::Success); + } + notifications.wait(); +} + +TEST(InnerVector, StressPushBack) { + const std::uint64_t size = 8; + const std::uint64_t finalSz = 1 << 6; + + galois::InnerVector vector; + EXPECT_EQ(vector.initialize(size), pando::Status::Success); + for (std::uint64_t i = 0; i < size; i++) { + vector[i] = i; + } + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(vector[i], i); + } + + for (std::uint64_t currSz = size; currSz < finalSz; currSz++) { + EXPECT_EQ(vector.pushBack(currSz), pando::Status::Success); + EXPECT_EQ(vector.size(), currSz + 1); + EXPECT_FALSE(vector.empty()); + EXPECT_GE(vector.capacity(), vector.size()); + + for (std::uint64_t i = 0; i < currSz + 1; i++) { + EXPECT_EQ(vector[i], i); + } + } + + vector.deinitialize(); +} + +TEST(InnerVector, MultiNodePushBack) { + auto f = +[](pando::Notification::HandleType done) { + const std::uint64_t size = 8; + const std::uint64_t finalSz = 1 << 8; + + galois::InnerVector vector; + EXPECT_EQ(vector.initialize(size), pando::Status::Success); + for (std::uint64_t i = 0; i < size; i++) { + vector[i] = i; + } + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(vector[i], i); + } + + for (std::uint64_t currSz = size; currSz < finalSz; currSz++) { + EXPECT_EQ(vector.pushBack(currSz), pando::Status::Success); + EXPECT_EQ(vector.size(), currSz + 1); + EXPECT_FALSE(vector.empty()); + EXPECT_GE(vector.capacity(), vector.size()); + + for (std::uint64_t i = 0; i < currSz + 1; i++) { + EXPECT_EQ(vector[i], i); + } + } + + vector.deinitialize(); + + done.notify(); + }; + + const auto& dims = pando::getPlaceDims(); + pando::NotificationArray notification; + EXPECT_EQ(notification.init(dims.node.id), pando::Status::Success); + for (std::int16_t node = 0; node < dims.node.id; ++node) { + EXPECT_EQ(pando::executeOn(pando::Place{pando::NodeIndex{node}, pando::anyPod, pando::anyCore}, + f, notification.getHandle(node)), + pando::Status::Success); + } + notification.wait(); +} + +TEST(InnerVector, Assign) { + auto f = +[](pando::Notification::HandleType done) { + constexpr uint64_t size = 1000; + + // create data vector + pando::Vector dataVector; + EXPECT_EQ(dataVector.initialize(0), pando::Status::Success); + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(dataVector.pushBack(i), pando::Status::Success); + } + EXPECT_EQ(dataVector.size(), size); + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(dataVector[i], i); + } + + // create local vector + galois::InnerVector vector; + EXPECT_EQ(vector.initialize(0), pando::Status::Success); + EXPECT_EQ(vector.assign(pando::GlobalPtr>(&dataVector)), + pando::Status::Success); + EXPECT_EQ(vector.size(), size); + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(dataVector[i], i); + } + + // destroy vectors + vector.deinitialize(); + dataVector.deinitialize(); + + done.notify(); + }; + + pando::Notification notification; + EXPECT_EQ(notification.init(), pando::Status::Success); + EXPECT_EQ(pando::executeOn(pando::Place{pando::NodeIndex{0}, pando::anyPod, pando::anyCore}, f, + notification.getHandle()), + pando::Status::Success); + notification.wait(); +} + +TEST(InnerVector, Append) { + auto f = +[](pando::Notification::HandleType done) { + constexpr std::uint64_t size = 1000; + constexpr std::uint64_t numAppends = 4; + + pando::Vector dataVector; + EXPECT_EQ(dataVector.initialize(0), pando::Status::Success); + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(dataVector.pushBack(i), pando::Status::Success); + } + EXPECT_EQ(dataVector.size(), size); + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(dataVector[i], i); + } + + // create local vector + galois::InnerVector lvec; + EXPECT_EQ(lvec.initialize(0), pando::Status::Success); + + // append vectors to local vector + for (std::uint64_t i = 0; i < numAppends; i++) { + EXPECT_EQ(lvec.append(&dataVector), pando::Status::Success); + } + + // check if local vector has all the data from the other vectors + EXPECT_EQ(lvec.size(), size * numAppends); + for (std::uint64_t j = 0; j < numAppends; ++j) { + for (std::uint64_t k = 0; k < size; ++k) { + EXPECT_EQ(lvec[j * size + k], k); + } + } + + // destroy vectors + lvec.deinitialize(); + dataVector.deinitialize(); + + done.notify(); + }; + + pando::Notification notification; + EXPECT_EQ(notification.init(), pando::Status::Success); + EXPECT_EQ(pando::executeOn(pando::Place{pando::NodeIndex{0}, pando::anyPod, pando::anyCore}, f, + notification.getHandle()), + pando::Status::Success); + notification.wait(); +} + +TEST(InnerVector, AssignRemote) { + constexpr std::uint64_t SIZE = 1000; + auto createVector = +[](uint64_t size) -> pando::Vector { + pando::Vector vec; + PANDO_CHECK(vec.initialize(size)); + for (std::uint64_t i = 0; i < size; i++) { + vec[i] = i; + } + return vec; + }; + pando::GlobalPtr> gvec; + pando::LocalStorageGuard gvecGuard(gvec, 1); + const auto place = pando::Place(pando::NodeIndex(1), pando::anyPod, pando::anyCore); + *gvec = PANDO_EXPECT_CHECK(pando::executeOnWait(place, createVector, SIZE)); + galois::InnerVector localVec{}; + EXPECT_EQ(localVec.assign(gvec), pando::Status::Success); + for (std::uint64_t i = 0; i < localVec.size(); i++) { + EXPECT_EQ(localVec[i], i); + } + localVec.deinitialize(); + pando::Vector tvec = *gvec; + tvec.deinitialize(); +} + +TEST(InnerVector, RangeLoop) { + constexpr std::uint64_t size = 1000; + + galois::InnerVector vec; + EXPECT_EQ(vec.initialize(0), pando::Status::Success); + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(vec.pushBack(i), pando::Status::Success); + } + std::uint64_t i = 0; + for (auto val : vec) { + EXPECT_EQ(val, i); + i++; + } + EXPECT_EQ(size, i); + + vec.deinitialize(); +} + +TEST(InnerVector, ConstRangeLoop) { + constexpr std::uint64_t size = 1000; + + galois::InnerVector vec; + EXPECT_EQ(vec.initialize(0), pando::Status::Success); + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(vec.pushBack(i), pando::Status::Success); + } + std::uint64_t i = 0; + for (const auto val : vec) { + EXPECT_EQ(val, i); + i++; + } + EXPECT_EQ(size, i); + + vec.deinitialize(); +} + +TEST(InnerVector, Iterator) { + constexpr std::uint64_t size = 1000; + + galois::InnerVector vec; + EXPECT_EQ(vec.initialize(0), pando::Status::Success); + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(vec.pushBack(i), pando::Status::Success); + } + std::uint64_t i = 0; + for (auto it = vec.begin(); it != vec.end(); it++) { + EXPECT_EQ(*it, i); + i++; + } + + vec.deinitialize(); +} + +TEST(InnerVector, ConstIterator) { + constexpr std::uint64_t size = 1000; + + galois::InnerVector vec; + EXPECT_EQ(vec.initialize(0), pando::Status::Success); + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(vec.pushBack(i), pando::Status::Success); + } + std::uint64_t i = 0; + for (auto it = vec.cbegin(); it != vec.cend(); it++) { + EXPECT_EQ(*it, i); + i++; + } + + vec.deinitialize(); +} + +TEST(InnerVector, ReverseIterator) { + constexpr std::uint64_t size = 1000; + + galois::InnerVector vec; + EXPECT_EQ(vec.initialize(0), pando::Status::Success); + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(vec.pushBack(i), pando::Status::Success); + } + std::uint64_t i = size - 1; + for (auto it = vec.rbegin(); it != vec.rend(); it++) { + EXPECT_EQ(*it, i); + i--; + } + + vec.deinitialize(); +} + +TEST(InnerVector, ReverseConstIterator) { + constexpr std::uint64_t size = 1000; + + galois::InnerVector vec; + EXPECT_EQ(vec.initialize(0), pando::Status::Success); + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(vec.pushBack(i), pando::Status::Success); + } + std::uint64_t i = size - 1; + for (auto it = vec.crbegin(); it != vec.crend(); it++) { + EXPECT_EQ(*it, i); + i--; + } + + vec.deinitialize(); +} + +TEST(InnerVector, Equality) { + constexpr std::uint64_t size = 1000; + + galois::InnerVector vec0; + galois::InnerVector vec1; + EXPECT_EQ(vec0.initialize(size), pando::Status::Success); + EXPECT_EQ(vec1.initialize(size), pando::Status::Success); + + std::uint64_t i = 0; + auto it0 = vec0.begin(); + auto it1 = vec1.begin(); + for (; it0 != vec0.end() && it1 != vec1.end(); it0++, it1++, i++) { + *it0 = i; + *it1 = i; + } + EXPECT_TRUE(vec0 == vec0); + EXPECT_TRUE(vec1 == vec1); + EXPECT_TRUE(vec0 == vec1); + + constexpr std::uint64_t newSize = 1025; + + for (std::uint64_t i = size; i < newSize; i++) { + EXPECT_EQ(vec0.pushBack(i), pando::Status::Success); + EXPECT_EQ(vec1.pushBack(i), pando::Status::Success); + + EXPECT_TRUE(vec0 == vec1); + } + + // TODO(muhaawad-amd) this does a shallow copy + auto func = +[](pando::Notification::HandleType done, galois::InnerVector vec0, + galois::InnerVector vec1) { + galois::InnerVector vec2; + EXPECT_EQ(vec2.initialize(newSize), pando::Status::Success); + for (auto it = vec2.begin(); it != vec2.end(); it++) { + *it = 0; + } + EXPECT_TRUE(vec0 == vec1); + EXPECT_FALSE(vec0 == vec2); + vec2.deinitialize(); + + done.notify(); + }; + + pando::Notification notification; + EXPECT_EQ(notification.init(), pando::Status::Success); + EXPECT_EQ(pando::executeOn(pando::Place{pando::NodeIndex{0}, pando::anyPod, pando::anyCore}, func, + notification.getHandle(), vec0, vec1), + pando::Status::Success); + notification.wait(); + vec0.deinitialize(); + vec1.deinitialize(); +} + +TEST(InnerVector, Inequality) { + constexpr std::uint64_t size = 10; + + galois::InnerVector vec0; + galois::InnerVector vec1; + EXPECT_EQ(vec0.initialize(size), pando::Status::Success); + EXPECT_EQ(vec1.initialize(size), pando::Status::Success); + + std::uint64_t i = 0; + auto it0 = vec0.begin(); + auto it1 = vec1.begin(); + for (; it0 != vec0.end() && it1 != vec1.end(); it0++, it1++, i++) { + *it0 = i; + *it1 = i; + } + EXPECT_FALSE(vec0 != vec0); + EXPECT_FALSE(vec1 != vec1); + EXPECT_FALSE(vec0 != vec1); + + constexpr std::uint64_t newSize = 17; + for (std::uint64_t i = size; i < newSize; i++) { + EXPECT_EQ(vec0.pushBack(i), pando::Status::Success); + EXPECT_EQ(vec1.pushBack(i + 1), pando::Status::Success); + + EXPECT_TRUE(vec0 != vec1); + } + + auto func = +[](pando::Notification::HandleType done, galois::InnerVector vec0, + galois::InnerVector vec1) { + galois::InnerVector vec2; + EXPECT_EQ(vec2.initialize(newSize), pando::Status::Success); + for (auto it = vec2.begin(); it != vec2.end(); it++) { + *it = 0; + } + EXPECT_TRUE(vec0 != vec1); + EXPECT_TRUE(vec0 != vec2); + + vec2.deinitialize(); + done.notify(); + }; + + pando::Notification notification; + EXPECT_EQ(notification.init(), pando::Status::Success); + EXPECT_EQ(pando::executeOn(pando::Place{pando::NodeIndex{0}, pando::anyPod, pando::anyCore}, func, + notification.getHandle(), vec0, vec1), + pando::Status::Success); + notification.wait(); + + vec0.deinitialize(); + vec1.deinitialize(); +} + +TEST(InnerVector, LocalityIterator) { + galois::InnerVector> innVec; + EXPECT_EQ(innVec.initialize(pando::getNodeDims().id), pando::Status::Success); + for (std::int64_t nodeIdx = 0; nodeIdx < pando::getNodeDims().id; nodeIdx++) { + pando::Array arr; + EXPECT_EQ( + arr.initialize(1, pando::Place(pando::NodeIndex(nodeIdx), pando::anyPod, pando::anyCore), + pando::MemoryType::Main), + pando::Status::Success); + innVec[nodeIdx] = arr; + } + std::int64_t nodeIdx = 0; + for (auto it = innVec.begin(); it != innVec.end(); it++) { + EXPECT_EQ(localityOf(it).node.id, nodeIdx); + nodeIdx++; + } + EXPECT_EQ(nodeIdx, pando::getNodeDims().id); +} From c869479bc3f7a0da1a165b27705e997a4f24cff7 Mon Sep 17 00:00:00 2001 From: AdityaAtulTewari Date: Fri, 26 Jul 2024 02:54:32 -0500 Subject: [PATCH 6/6] Inner vec for bfs (#134) --- microbench/bfs/include/pando-bfs-galois/sssp.hpp | 6 ++++++ microbench/bfs/src/sssp.cpp | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/microbench/bfs/include/pando-bfs-galois/sssp.hpp b/microbench/bfs/include/pando-bfs-galois/sssp.hpp index aa0c9474..cdd74626 100644 --- a/microbench/bfs/include/pando-bfs-galois/sssp.hpp +++ b/microbench/bfs/include/pando-bfs-galois/sssp.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -105,6 +106,11 @@ void BFSPerHostLoop_DLCSR(BFSState state, PANDO_CHECK(err); } +using DLCSR = galois::DistLocalCSR; +template <> +void BFSPerHostLoop_DLCSR( + BFSState state, + pando::GlobalRef> vecRef); template pando::Status SSSP_DLCSR( G& graph, std::uint64_t src, ThreadLocalVector& active, diff --git a/microbench/bfs/src/sssp.cpp b/microbench/bfs/src/sssp.cpp index d2b6cdaa..9e32d86d 100644 --- a/microbench/bfs/src/sssp.cpp +++ b/microbench/bfs/src/sssp.cpp @@ -5,6 +5,7 @@ /* Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. */ #include +#include void bfs::updateData(std::uint64_t val, pando::GlobalRef ref) { std::uint64_t temp = pando::atomicLoad(&ref, std::memory_order_relaxed); @@ -16,4 +17,14 @@ void bfs::updateData(std::uint64_t val, pando::GlobalRef ref) { std::memory_order_relaxed)); } +template <> +void bfs::BFSPerHostLoop_DLCSR( + BFSState state, + pando::GlobalRef> vecRef) { + using G = DLCSR; + pando::Vector vec = vecRef; + galois::InnerVector innVec(std::move(vec)); + PANDO_CHECK(galois::doAll(state, innVec, &BFSOuterLoop_DLCSR)); +} + bfs::CountEdges bfs::countEdges;