diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index eb6d862d..e9732435 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -56,11 +56,11 @@ jobs: echo "IMAGE_VERSION=$(git log --pretty="%h" -1 Dockerfile.dev)" >> $GITHUB_ENV if [ ${{ matrix.build-type }} == 'LSAN' ]; then echo "PANDO_BUILD_DOCS=OFF" >> $GITHUB_ENV - echo "PANDO_CONTAINER_ENV=-e=PANDO_PREP_L1SP_HART=16384 -ePANDO_PREP_MAIN_NODE=8589934592" >> $GITHUB_ENV + echo "PANDO_CONTAINER_ENV=-e=PANDO_PREP_L1SP_HART=16384" >> $GITHUB_ENV fi if [ ${{ matrix.build-type }} == 'UBSAN' ]; then echo "PANDO_BUILD_DOCS=OFF" >> $GITHUB_ENV - echo "PANDO_CONTAINER_ENV=-e=PANDO_PREP_L1SP_HART=16384 -ePANDO_PREP_MAIN_NODE=8589934592" >> $GITHUB_ENV + echo "PANDO_CONTAINER_ENV=-e=PANDO_PREP_L1SP_HART=16384" >> $GITHUB_ENV fi if [ ${{ matrix.build-type }} == 'Release' ]; then echo "PANDO_BUILD_DOCS=OFF" >> $GITHUB_ENV diff --git a/cmake/PANDOTesting.cmake b/cmake/PANDOTesting.cmake index cc90c44f..3a71a1d6 100644 --- a/cmake/PANDOTesting.cmake +++ b/cmake/PANDOTesting.cmake @@ -69,9 +69,9 @@ function(pando_add_driver_test_lib TARGET SOURCEFILE LIBRARY) else () set(HTHREADS "") if (${GASNet_CONDUIT} STREQUAL "smp") - set(DRIVER_SCRIPT ${pando-lib-galois_SOURCE_DIR}/pando-rt/scripts/preprun.sh) + set(DRIVER_SCRIPT ${pando-lib-galois_SOURCE_DIR}/scripts/preprun.sh) elseif (${GASNet_CONDUIT} STREQUAL "mpi") - set(DRIVER_SCRIPT ${pando-lib-galois_SOURCE_DIR}/pando-rt/scripts/preprun_mpi.sh) + set(DRIVER_SCRIPT ${pando-lib-galois_SOURCE_DIR}/scripts/preprun_mpi.sh) else () message(FATAL_ERROR "No runner script for GASNet conduit ${GASNet_CONDUIT}") endif () @@ -124,9 +124,9 @@ endfunction() function(pando_add_bin_test TARGET ARGS INPUTFILE OKFILE) if (NOT PANDO_RT_BACKEND STREQUAL "DRVX") if (${GASNet_CONDUIT} STREQUAL "smp") - set(DRIVER_SCRIPT ${pando-lib-galois_SOURCE_DIR}/pando-rt/scripts/preprun.sh) + set(DRIVER_SCRIPT ${pando-lib-galois_SOURCE_DIR}/scripts/preprun.sh) elseif (${GASNet_CONDUIT} STREQUAL "mpi") - set(DRIVER_SCRIPT ${pando-lib-galois_SOURCE_DIR}/pando-rt/scripts/preprun_mpi.sh) + set(DRIVER_SCRIPT ${pando-lib-galois_SOURCE_DIR}/scripts/preprun_mpi.sh) else () message(FATAL_ERROR "No runner script for GASNet conduit ${GASNet_CONDUIT}") endif () diff --git a/include/pando-lib-galois/graphs/dist_local_csr.hpp b/include/pando-lib-galois/graphs/dist_local_csr.hpp index b4953fb4..8a11308a 100644 --- a/include/pando-lib-galois/graphs/dist_local_csr.hpp +++ b/include/pando-lib-galois/graphs/dist_local_csr.hpp @@ -487,10 +487,14 @@ class DistLocalCSR { } /** Host Information **/ - std::uint64_t getPhysicalHostID(VertexTokenID tid) { + std::uint64_t getVirtualHostID(VertexTokenID tid) { std::uint64_t virtualHostID = tid % this->numVHosts(); - std::uint64_t physicalHost = fmap(virtualToPhysicalMap.getLocalRef(), get, virtualHostID); - return physicalHost; + return virtualHostID; + } + std::uint64_t getPhysicalHostID(VertexTokenID tid) { + std::uint64_t virtualHostID = this->getVirtualHostID(tid); + std::uint64_t physicalHostID = fmap(virtualToPhysicalMap.getLocalRef(), get, virtualHostID); + return physicalHostID; } /** Topology Modifications **/ diff --git a/include/pando-lib-galois/graphs/mirror_dist_local_csr.hpp b/include/pando-lib-galois/graphs/mirror_dist_local_csr.hpp index 812c1546..c498f63d 100644 --- a/include/pando-lib-galois/graphs/mirror_dist_local_csr.hpp +++ b/include/pando-lib-galois/graphs/mirror_dist_local_csr.hpp @@ -8,7 +8,6 @@ #include -#include "pando-rt/sync/mutex.hpp" #include #include #include @@ -17,7 +16,10 @@ #include #include #include +#include +#include #include +#include #include #include #include @@ -132,6 +134,10 @@ class MirrorDistLocalCSR { VertexTopologyID getMaster() { return master; } + + bool operator==(const MirrorToMasterMap& a) noexcept { + return a.mirror == mirror && a.master == master; + } }; /** Vertex Manipulation **/ @@ -239,19 +245,13 @@ class MirrorDistLocalCSR { } /** Host Information **/ + std::uint64_t getVirtualHostID(VertexTokenID tid) { + return dlcsr.getVirtualHostID(tid); + } std::uint64_t getPhysicalHostID(VertexTokenID tid) { return dlcsr.getPhysicalHostID(tid); } - /** Sync **/ - // TODO(Ying-Wei): - // write a sync function that reduces mirror values and then broadcasts master values - // return a bitmap of modified vertices - // - // template - // pando::Array sync(Func func, pando::Array) { - //} - /** * @brief get vertex local dense ID */ @@ -303,8 +303,6 @@ class MirrorDistLocalCSR { return dlcsr.getLocalCSR(); } - // TODO(Jeageun): - // write a initialize function that calls initializeAfterGather function of DistLocalCSR dlcsr template pando::Status initializeAfterGather( galois::HostLocalStorage> vertexData, std::uint64_t numVertices, @@ -390,62 +388,81 @@ class MirrorDistLocalCSR { numVertices += lift(mirrorList[i], size); } PANDO_CHECK(wg.wait()); + + PANDO_CHECK_RETURN(setupCommunication()); + return pando::Status::Success; } - // TODO(Ying-Wei): - // uses doAll to send remoteMasterToLocalMirrorMap to corresponding remote hosts - // no need to use executeON - // just push to the localMasterToRemoteMirrorOrderedTable vector - // make sure to use the spin lock in pando-rt /** - * @brief Get the local mutex + * @brief Exchanges the mirror to master mapping from the mirror side to the maser side */ - pando::GlobalRef getLocalMutex(std::uint64_t host_id) { - return hostMutex[host_id]; - } - pando::Status setupCommunication() { + auto dims = pando::getPlaceDims(); + + // initialize localMirrorToRemoteMasterOrderedTable PANDO_CHECK_RETURN(localMasterToRemoteMirrorTable.initialize()); + for (std::int16_t i = 0; i < dims.node.id; i++) { + pando::GlobalRef>> + localMasterToRemoteMirrorMap = localMasterToRemoteMirrorTable[i]; + PANDO_CHECK_RETURN(fmap(localMasterToRemoteMirrorMap, initialize, dims.node.id)); + for (std::int16_t i = 0; i < dims.node.id; i++) { + pando::GlobalRef> mapVectorFromHost = + fmap(localMasterToRemoteMirrorMap, get, i); + PANDO_CHECK_RETURN(fmap(mapVectorFromHost, initialize, 0)); + } + } - PANDO_CHECK_RETURN(hostMutex.initialize()); - - PANDO_CHECK_RETURN(galois::doAll( - localMirrorToRemoteMasterOrderedTable, localMasterToRemoteMirrorTable, - +[](galois::HostLocalStorage> - localMirrorToRemoteMasterOrderedTable, - pando::GlobalRef> localMasterToRemoteMirrorTable) { - PANDO_CHECK(fmap(localMirrorToRemoteMasterOrderedTable, initialize, 0)); - pando::Array remoteMasterToLocalMirrorMap = - localMirrorToRemoteMasterOrderedTable.getLocal(); - for (MirrorToMasterMap m : remoteMasterToLocalMirrorMap) { - VertexTopologyID masterTopologyID = m.master; - VertexTokenID masterTokenID = getTokenID(masterTopologyID); - std::uint64_t physicalHost = getPhysicalHostID(masterTokenID); - pando::Mutex mutex = getLocalMutex(physicalHost); - - // Lock mutex to ensure atomic append to the vector - mutex.lock(); - PANDO_CHECK(fmap(localMasterToRemoteMirrorTable, pushBack, m)); - mutex.unlock(); + auto thisCSR = *this; + auto state = galois::make_tpl(thisCSR, localMasterToRemoteMirrorTable); + + // push style + // each host traverses its own localMirrorToRemoteMasterOrderedTable and send out the mapping to + // the corresponding remote host append to the vector of vector where each vector is the mapping + // from a specific host + galois::doAll( + state, localMirrorToRemoteMasterOrderedTable, + +[](decltype(state) state, + pando::GlobalRef> localMirrorToRemoteMasterOrderedMap) { + auto [object, localMasterToRemoteMirrorTable] = state; + for (std::uint64_t i = 0ul; i < lift(localMirrorToRemoteMasterOrderedMap, size); i++) { + MirrorToMasterMap m = fmap(localMirrorToRemoteMasterOrderedMap, get, i); + VertexTopologyID masterTopologyID = m.getMaster(); + VertexTokenID masterTokenID = object.getTokenID(masterTopologyID); + std::uint64_t physicalHost = object.getPhysicalHostID(masterTokenID); + + pando::GlobalRef>> + localMasterToRemoteMirrorMap = localMasterToRemoteMirrorTable[physicalHost]; + pando::GlobalRef> mapVectorFromHost = + fmap(localMasterToRemoteMirrorMap, get, pando::getCurrentPlace().node.id); + + PANDO_CHECK(fmap(mapVectorFromHost, pushBack, m)); } - })); + }); return pando::Status::Success; } + /** + * @brief For testing only + */ + pando::GlobalRef> getLocalMirrorToRemoteMasterOrderedMap( + int16_t hostId) { + return localMirrorToRemoteMasterOrderedTable[hostId]; + } + pando::GlobalRef>> getLocalMasterToRemoteMirrorMap( + uint64_t hostId) { + return localMasterToRemoteMirrorTable[hostId]; + } + private: DLCSR dlcsr; uint64_t _mirror_size; galois::HostLocalStorage masterRange; galois::HostLocalStorage mirrorRange; galois::HostLocalStorage> localMirrorToRemoteMasterOrderedTable; - - // TODO(Ying-Wei): - // generate the following - galois::HostLocalStorage hostMutex; - galois::HostLocalStorage> localMasterToRemoteMirrorTable; - // galois::GlobalBarrier barrier; + galois::HostLocalStorage>> + localMasterToRemoteMirrorTable; }; static_assert(graph_checker>::value); diff --git a/pando-rt/cmake/PANDOTesting.cmake b/pando-rt/cmake/PANDOTesting.cmake index eff8498f..7b8753ce 100644 --- a/pando-rt/cmake/PANDOTesting.cmake +++ b/pando-rt/cmake/PANDOTesting.cmake @@ -72,9 +72,9 @@ function(pando_add_driver_test TARGET SOURCEFILE) if (PANDO_RT_BACKEND STREQUAL "PREP") if (${GASNet_CONDUIT} STREQUAL "smp") - set(RUNNER_SCRIPT ${PROJECT_SOURCE_DIR}/scripts/preprun.sh) + set(RUNNER_SCRIPT ${PROJECT_SOURCE_DIR}/../scripts/preprun.sh) elseif (${GASNet_CONDUIT} STREQUAL "mpi") - set(RUNNER_SCRIPT ${PROJECT_SOURCE_DIR}/scripts/preprun_mpi.sh) + set(RUNNER_SCRIPT ${PROJECT_SOURCE_DIR}/../scripts/preprun_mpi.sh) else () message(FATAL_ERROR "No runner script for GASNet conduit ${GASNet_CONDUIT}") endif () diff --git a/pando-rt/scripts/preprun.sh b/scripts/preprun.sh similarity index 59% rename from pando-rt/scripts/preprun.sh rename to scripts/preprun.sh index dc5d29f1..23647c96 100755 --- a/pando-rt/scripts/preprun.sh +++ b/scripts/preprun.sh @@ -1,4 +1,7 @@ #!/bin/bash +# SPDX-License-Identifier: MIT +# Copyright (c) 2023. University of Texas at Austin. All rights reserved. + # # SPDX-License-Identifier: MIT # Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. @@ -29,32 +32,31 @@ usage: preprun -n prog [program args] harts="" -while getopts "n:c:t:h" option -do +while getopts "n:c:t:h" option; do case ${option} in - n) # number of emulated PXNs - nodes=${OPTARG} - ;; - c) # number of emulated cores per PXN - cores=${OPTARG} - ;; - t) # number of emulated cores per PXN - harts=${OPTARG} - ;; - h) # help - show_help - exit - ;; + n) # number of emulated PXNs + nodes=${OPTARG} + ;; + c) # number of emulated cores per PXN + cores=${OPTARG} + ;; + t) # number of emulated cores per PXN + harts=${OPTARG} + ;; + h) # help + show_help + exit + ;; esac done -shift $(expr $OPTIND - 1 ) +shift $(expr $OPTIND - 1) prog=$@ export GASNET_PSHM_NODES=$nodes export PANDO_PREP_NUM_CORES=$cores if [ -n "$harts" ]; then - export PANDO_PREP_NUM_HARTS=$harts + export PANDO_PREP_NUM_HARTS=$harts fi exec $prog diff --git a/pando-rt/scripts/preprun_mpi.sh b/scripts/preprun_mpi.sh similarity index 52% rename from pando-rt/scripts/preprun_mpi.sh rename to scripts/preprun_mpi.sh index b6d3606c..83af3964 100755 --- a/pando-rt/scripts/preprun_mpi.sh +++ b/scripts/preprun_mpi.sh @@ -1,4 +1,7 @@ #!/bin/bash +# SPDX-License-Identifier: MIT +# Copyright (c) 2023. University of Texas at Austin. All rights reserved. + # # SPDX-License-Identifier: MIT # Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. @@ -28,32 +31,35 @@ usage: preprun -n prog [program args] # harts="" +# 16GB Main memory size by default +main_memory_size="${main_memory_size-8589934592}" -while getopts "n:c:t:h" option -do +while getopts "n:c:t:h" option; do case ${option} in - n) # number of emulated PXNs - nodes=${OPTARG} - ;; - c) # number of emulated cores per PXN - cores=${OPTARG} - ;; - t) # number of emulated cores per PXN - harts=${OPTARG} - ;; - h) # help - show_help - exit - ;; + n) # number of emulated PXNs + nodes=${OPTARG} + ;; + c) # number of emulated cores per PXN + cores=${OPTARG} + ;; + t) # number of emulated cores per PXN + harts=${OPTARG} + ;; + h) # help + show_help + exit + ;; esac done -shift $(expr $OPTIND - 1 ) +shift $(expr $OPTIND - 1) prog=$@ export PANDO_PREP_NUM_CORES=$cores if [ -n "$harts" ]; then - export PANDO_PREP_NUM_HARTS=$harts + export PANDO_PREP_NUM_HARTS=$harts fi +export PANDO_PREP_MAIN_NODE=$main_memory_size + gasnetrun_mpi -n $nodes $prog diff --git a/test/graphs/test_mirror_dist_local_csr.cpp b/test/graphs/test_mirror_dist_local_csr.cpp index c50f25cb..ef8acbcd 100644 --- a/test/graphs/test_mirror_dist_local_csr.cpp +++ b/test/graphs/test_mirror_dist_local_csr.cpp @@ -9,6 +9,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -57,3 +61,82 @@ TEST(MirrorDistLocalCSR, NumVertices) { EXPECT_EQ(deleteVectorVector(vec), pando::Status::Success); } + +void getVerticesAndEdgesEL(const std::string& filename, std::uint64_t numVertices, + std::unordered_map>& graph) { + std::ifstream file(filename); + std::uint64_t src, dst; + while (file >> src && file >> dst) { + if (src < numVertices && dst < numVertices) { + graph[src].push_back(dst); + } + } + for (std::uint64_t i = 0; i < numVertices; i++) { + if (graph.find(i) == graph.end()) { + graph[i] = std::vector(); + } + } + file.close(); +} + +template +bool isInVector(T element, pando::GlobalRef> vec) { + for (std::uint64_t i = 0; i < lift(vec, size); i++) { + if (fmap(vec, get, i) == element) { + return true; + } + } + return false; +} + +class MirrorDLCSRInitEdgeList + : public ::testing::TestWithParam> {}; +TEST_P(MirrorDLCSRInitEdgeList, MapExchange) { + using ET = galois::ELEdge; + using VT = galois::ELVertex; + using Graph = galois::MirrorDistLocalCSR; + galois::HostLocalStorageHeap::HeapInit(); + + const std::string elFile = std::get<0>(GetParam()); + const std::uint64_t numVertices = std::get<1>(GetParam()); + + pando::Array filename; + EXPECT_EQ(pando::Status::Success, filename.initialize(elFile.size())); + for (uint64_t i = 0; i < elFile.size(); i++) + filename[i] = elFile[i]; + + Graph graph = + galois::initializeELDLCSR(filename, numVertices); + + auto dims = pando::getPlaceDims(); + for (std::int16_t nodeId = 0; nodeId < dims.node.id; nodeId++) { + pando::GlobalRef> localMirrorToRemoteMasterOrderedMap = + graph.getLocalMirrorToRemoteMasterOrderedMap(nodeId); + for (std::uint64_t i = 0ul; i < lift(localMirrorToRemoteMasterOrderedMap, size); i++) { + Graph::MirrorToMasterMap m = fmap(localMirrorToRemoteMasterOrderedMap, get, i); + Graph::VertexTopologyID masterToopologyID = m.getMaster(); + Graph::VertexTokenID masterTokenID = graph.getTokenID(masterToopologyID); + std::uint64_t physicalHost = graph.getPhysicalHostID(masterTokenID); + pando::GlobalRef>> + localMasterToRemoteMirrorMap = graph.getLocalMasterToRemoteMirrorMap(physicalHost); + pando::GlobalRef> mapVectorFromHost = + fmap(localMasterToRemoteMirrorMap, get, nodeId); + EXPECT_TRUE(isInVector(m, mapVectorFromHost)); + } + } + graph.deinitialize(); +} + +INSTANTIATE_TEST_SUITE_P( + SmallFiles, MirrorDLCSRInitEdgeList, + ::testing::Values(std::make_tuple("/pando/graphs/simple.el", 10), + std::make_tuple("/pando/graphs/rmat_571919_seed1_scale10_nV1024_nE10447.el", + 1024))); + +INSTANTIATE_TEST_SUITE_P( + DISABLED_BigFiles, MirrorDLCSRInitEdgeList, + ::testing::Values( + std::make_tuple("/pando/graphs/rmat_571919_seed1_scale11_nV2048_nE22601.el", 2048), + std::make_tuple("/pando/graphs/rmat_571919_seed1_scale12_nV4096_nE48335.el", 4096), + std::make_tuple("/pando/graphs/rmat_571919_seed1_scale13_nV8192_nE102016.el", 8192), + std::make_tuple("/pando/graphs/rmat_571919_seed1_scale14_nV16384_nE213350.el", 16384)));