From d684f7ce0c042db4083ea18e8db224eeaafe25c6 Mon Sep 17 00:00:00 2001 From: KavyaVarma Date: Tue, 2 Apr 2024 08:07:12 +0000 Subject: [PATCH 1/3] Ported mem-free changes to mono repo --- Makefile | 2 +- .../include/pando-rt/containers/array.hpp | 16 +++ .../include/pando-rt/containers/vector.hpp | 8 ++ .../memory/deallocate_memory_wait.hpp | 95 +++++++++++++ pando-rt/include/pando-rt/sync/wait_group.hpp | 132 ++++++++++++++++++ pando-rt/src/allocate_memory.cpp | 6 + pando-rt/test/containers/test_array.cpp | 25 ++++ pando-rt/test/containers/test_vector.cpp | 26 ++++ pando-rt/test/sync/CMakeLists.txt | 1 + pando-rt/test/sync/test_wait_group.cpp | 104 ++++++++++++++ 10 files changed, 414 insertions(+), 1 deletion(-) create mode 100644 pando-rt/include/pando-rt/memory/deallocate_memory_wait.hpp create mode 100644 pando-rt/include/pando-rt/sync/wait_group.hpp create mode 100644 pando-rt/test/sync/test_wait_group.cpp diff --git a/Makefile b/Makefile index 45997b12..36452b26 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ CONTAINER_CMD ?= setarch `uname -m` -R bash -l INTERACTIVE ?= i BUILD_TYPE ?= Release -PANDORT_TESTS ?= OFF +PANDORT_TESTS ?= ON # CMake variables PANDO_TEST_DISCOVERY_TIMEOUT ?= 150 diff --git a/pando-rt/include/pando-rt/containers/array.hpp b/pando-rt/include/pando-rt/containers/array.hpp index b6f61f46..1157f9db 100644 --- a/pando-rt/include/pando-rt/containers/array.hpp +++ b/pando-rt/include/pando-rt/containers/array.hpp @@ -9,7 +9,9 @@ #include "../memory/allocate_memory.hpp" #include "../memory/global_ptr.hpp" +#include "../memory/deallocate_memory_wait.hpp" #include "../utility/math.hpp" +#include "../sync/wait_group.hpp" namespace pando { @@ -111,6 +113,20 @@ class Array { m_memoryType = MemoryType::Unknown; } + /** + * @brief Deinitializes the array. + */ + void deinitialize(pando::WaitGroup::HandleType wgh) { + // TODO(ypapadop-amd) Only trivially destructible objects are supported, since deinitialize() + // does not call their destructor. + static_assert(std::is_trivially_destructible_v, + "Array only supports trivially destructible types"); + deallocateMemory(m_data, m_size, wgh); + m_data = nullptr; + m_size = 0; + m_memoryType = MemoryType::Unknown; + } + MemoryType getMemoryType() const noexcept { return m_memoryType; } diff --git a/pando-rt/include/pando-rt/containers/vector.hpp b/pando-rt/include/pando-rt/containers/vector.hpp index c6774409..b862b15e 100644 --- a/pando-rt/include/pando-rt/containers/vector.hpp +++ b/pando-rt/include/pando-rt/containers/vector.hpp @@ -89,6 +89,14 @@ class Vector { m_size = 0; } + /** + * @brief Deinitializes the container. + */ + void deinitialize(pando::WaitGroup::HandleType wgh) { + m_buf.deinitialize(wgh); + m_size = 0; + } + /** * @brief Returns the memory this vector is allocated in. */ diff --git a/pando-rt/include/pando-rt/memory/deallocate_memory_wait.hpp b/pando-rt/include/pando-rt/memory/deallocate_memory_wait.hpp new file mode 100644 index 00000000..5b872ed2 --- /dev/null +++ b/pando-rt/include/pando-rt/memory/deallocate_memory_wait.hpp @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +/* Copyright (c) 2023. University of Texas at Austin. All rights reserved. */ +/* Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. */ + +#ifndef PANDO_RT_MEMORY_DEALLOCATE_MEMORY_WAIT_HPP_ +#define PANDO_RT_MEMORY_DEALLOCATE_MEMORY_WAIT_HPP_ + +#include + +#include "../execution/execute_on.hpp" +#include "../execution/execute_on_wait.hpp" +#include "../locality.hpp" +#include "../memory/global_ptr.hpp" +#include "../status.hpp" +#include "../stdlib.hpp" +#include "../sync/future.hpp" +#include "../sync/wait_group.hpp" +#include "../utility/expected.hpp" +#include "memory_type.hpp" + +namespace pando { + +namespace detail { + +/** + * @brief Deallocates the memory @p p points to. + * + * @param[in] p pointer to memory to deallocate + * @param[in] size number of bytes to deallocate + * @param[in] wgh wait group that waits on deallocate + * + * @ingroup ROOT + */ +void deallocateMemoryWaitImpl(GlobalPtr p, std::uint64_t size, pando::WaitGroup::HandleType wgh); + +} // namespace detail + +/** + * @brief Deallocates memory previously allocated with `allocateMemory`. + * + * @tparam T object type to deallocate memory for + * + * @param[in] p pointer to memory to deallocate + * @param[in] n number of objects to @p p points to + * @param[in] wgh wait group that waits on deallocate + * + * @ingroup ROOT + */ +template +void deallocateMemory(GlobalPtr p, std::uint64_t n, pando::WaitGroup::HandleType wgh) { + if (p == nullptr) { + return; + } + + const auto numBytes = n * sizeof(T); + const auto place = pando::localityOf(p); + const auto memoryType = memoryTypeOf(p); + + switch (memoryType) { + case MemoryType::Main: { + // CP / harts have direct access to main memory on their node + if (place.node == getCurrentNode()) { + detail::deallocateMemoryImpl(p, numBytes); + } else { + wgh.addOne(); + if (executeOn(place, &detail::deallocateMemoryWaitImpl, static_cast>(p), + numBytes, wgh) != Status::Success) { + PANDO_ABORT("Deallocation failed"); + } + } + } break; + + case MemoryType::L2SP: { + // only harts on the same pod as the requested L2SP have direct access + const auto thisPlace = getCurrentPlace(); + if (!isOnCP() && (thisPlace.node == place.node) && (thisPlace.pod == place.pod)) { + detail::deallocateMemoryImpl(p, numBytes); + } else { + if (executeOn(place, &detail::deallocateMemoryImpl, static_cast>(p), + numBytes) != Status::Success) { + PANDO_ABORT("Deallocation failed"); + } + } + } break; + + case MemoryType::L1SP: + default: + PANDO_ABORT("Invalid pointer to deallocate"); + break; + } +} + +} // namespace pando + +#endif // PANDO_RT_MEMORY_DEALLOCATE_MEMORY_WAIT_HPP_ diff --git a/pando-rt/include/pando-rt/sync/wait_group.hpp b/pando-rt/include/pando-rt/sync/wait_group.hpp new file mode 100644 index 00000000..dbf111ee --- /dev/null +++ b/pando-rt/include/pando-rt/sync/wait_group.hpp @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2023. University of Texas at Austin. All rights reserved. + +#ifndef PANDO_RT_SYNC_WAIT_GROUP_HPP_ +#define PANDO_RT_SYNC_WAIT_GROUP_HPP_ + +#include "../memory/allocate_memory.hpp" +#include "../memory/global_ptr.hpp" +#include "../pando-rt.hpp" +#include "../sync/atomic.hpp" +#include "../sync/notification.hpp" +#include +#include "export.h" + +namespace pando { +/** + * @brief This is a termination detection mechanism that is used for detecting nested parallelism + */ +class WaitGroup { + ///@brief This is a pointer to the counter used by everyone + pando::GlobalPtr m_count = nullptr; + +public: + class HandleType { + pando::GlobalPtr m_count = nullptr; + explicit HandleType(pando::GlobalPtr countPtr) : m_count(countPtr) {} + friend WaitGroup; + + public: + HandleType() : m_count(nullptr) {} + HandleType(const HandleType&) = default; + HandleType& operator=(const HandleType&) = default; + + HandleType(HandleType&&) = default; + HandleType& operator=(HandleType&&) = default; + + /** + * @brief adds a number of more items to arrive at the barrier before release + * + * @param[in] delta the amount of things to wait on + */ + void add(std::uint32_t delta) { + pando::atomicFetchAdd(m_count, static_cast(delta), std::memory_order_release); + } + /** + * @brief adds to the barrier to represent one more done to wait on + */ + void addOne() { + add(static_cast(1)); + } + /** + * @brief Signals that one of the things in the WaitGroup has completed. + */ + void done() { + pando::atomicDecrement(m_count, static_cast(1), std::memory_order_release); + } + }; + + WaitGroup() : m_count(nullptr) {} + + WaitGroup(const WaitGroup&) = delete; + WaitGroup& operator=(const WaitGroup&) = delete; + + WaitGroup(WaitGroup&&) = delete; + WaitGroup& operator=(WaitGroup&&) = delete; + + /** + * @brief initializes the WaitGroup + * + * @param[in] initialCount the count that the WaitGroup should start with + * @param[in] place the location the counter should be allocated at + * @param[in] memoryType the type of memory the waitgroup should be allocated in + * + * @warning one of the initialize methods must be called before use + */ + [[nodiscard]] pando::Status initialize(std::uint32_t initialCount, pando::Place place, + pando::MemoryType memoryType) { + const auto expected = pando::allocateMemory(1, place, memoryType); + if (!expected.hasValue()) { + return expected.error(); + } + m_count = expected.value(); + *m_count = static_cast(initialCount); + pando::atomicThreadFence(std::memory_order_release); + return pando::Status::Success; + } + + /** + * @brief initializes the WaitGroup + * + * @param[in] initialCount the count that the WaitGroup should start with + * + * @warning one of the initialize methods must be called before use + */ + [[nodiscard]] pando::Status initialize(std::uint32_t initialCount) { + return initialize(initialCount, pando::getCurrentPlace(), pando::MemoryType::Main); + } + + /** + * @brief deinitializes the waitgroup and frees associated memory + * + * @warning not threadsafe but designed to be idempotent. + */ + void deinitialize() { + if (m_count != nullptr) { + pando::deallocateMemory(m_count, 1); + m_count = nullptr; + } + } + + HandleType getHandle() { + return HandleType{m_count}; + } + + /** + * @brief Waits until the number of items to wait on is zero. + */ + [[nodiscard]] pando::Status wait() { + pando::waitUntil([this] { + const bool ready = *m_count <= static_cast(0); + return ready; + }); + pando::atomicThreadFence(std::memory_order_acquire); + PANDO_MEM_STAT_NEW_PHASE(); + if (*m_count < static_cast(0)) { + return pando::Status::Error; + } + return pando::Status::Success; + } +}; +} // namespace pando +#endif // PANDO_RT_SYNC_WAIT_GROUP_HPP_ diff --git a/pando-rt/src/allocate_memory.cpp b/pando-rt/src/allocate_memory.cpp index 629877f2..240f2b7b 100644 --- a/pando-rt/src/allocate_memory.cpp +++ b/pando-rt/src/allocate_memory.cpp @@ -3,6 +3,7 @@ /* Copyright (c) 2023. University of Texas at Austin. All rights reserved. */ #include "pando-rt/memory/allocate_memory.hpp" +#include "pando-rt/memory/deallocate_memory_wait.hpp" #include "pando-rt/stdlib.hpp" @@ -35,6 +36,11 @@ void deallocateMemoryImpl(GlobalPtr p, std::uint64_t size) { } } +void deallocateMemoryWaitImpl(GlobalPtr p, std::uint64_t size, pando::WaitGroup::HandleType wgh) { + deallocateMemoryImpl(p, size); + wgh.done(); +} + } // namespace detail } // namespace pando diff --git a/pando-rt/test/containers/test_array.cpp b/pando-rt/test/containers/test_array.cpp index e3dfaa3f..b71e71ad 100644 --- a/pando-rt/test/containers/test_array.cpp +++ b/pando-rt/test/containers/test_array.cpp @@ -320,3 +320,28 @@ TEST(Array, Equivalence) { arr0.deinitialize(); arr1.deinitialize(); } + +TEST(Array, DeinitializeWgh) { + const std::uint64_t size = 10000; + + pando::Array array; + EXPECT_EQ(array.initialize(size, + pando::Place{pando::NodeIndex{1}, pando::anyPod, pando::anyCore}, + pando::MemoryType::Main), pando::Status::Success); + EXPECT_EQ(array.size(), size); + EXPECT_NE(array.data(), nullptr); + + for (std::uint64_t i = 0; i < size; i++) { + array[i] = i; + } + + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(array[i], i); + } + + pando::WaitGroup wg; + EXPECT_EQ(wg.initialize(0), pando::Status::Success); + array.deinitialize(wg.getHandle()); + EXPECT_EQ(wg.wait(), pando::Status::Success); + wg.deinitialize(); +} diff --git a/pando-rt/test/containers/test_vector.cpp b/pando-rt/test/containers/test_vector.cpp index fe556228..8899b2e3 100644 --- a/pando-rt/test/containers/test_vector.cpp +++ b/pando-rt/test/containers/test_vector.cpp @@ -523,3 +523,29 @@ TEST(Vector, Inequality) { vec0.deinitialize(); vec1.deinitialize(); } + +TEST(Vector, DeinitializeWgh) { + const std::uint64_t size = 10; + + pando::Vector 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); + } + + pando::WaitGroup wg; + EXPECT_EQ(wg.initialize(0), pando::Status::Success); + vector.deinitialize(wg.getHandle()); + EXPECT_EQ(wg.wait(), pando::Status::Success); + wg.deinitialize(); + EXPECT_EQ(vector.capacity(), 0); + EXPECT_EQ(vector.size(), 0); +} diff --git a/pando-rt/test/sync/CMakeLists.txt b/pando-rt/test/sync/CMakeLists.txt index 802b128b..62884fa4 100644 --- a/pando-rt/test/sync/CMakeLists.txt +++ b/pando-rt/test/sync/CMakeLists.txt @@ -5,3 +5,4 @@ pando_add_driver_test(test_notification test_notification.cpp) pando_add_driver_test(test_future test_future.cpp) pando_add_driver_test(test_mutex test_mutex.cpp) pando_add_driver_test(test_atomics test_atomics.cpp) +pando_add_driver_test(test_waitgroup test_wait_group.cpp) diff --git a/pando-rt/test/sync/test_wait_group.cpp b/pando-rt/test/sync/test_wait_group.cpp new file mode 100644 index 00000000..e1d594e4 --- /dev/null +++ b/pando-rt/test/sync/test_wait_group.cpp @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2023. University of Texas at Austin. All rights reserved. + +#include +#include + +#include + +#include +#include +#include +#include + +constexpr pando::Place anyZero = pando::Place{pando::NodeIndex{0}, pando::anyPod, pando::anyCore}; + +TEST(WaitGroup, Initialize) { + pando::WaitGroup wg; + EXPECT_EQ(wg.initialize(1), pando::Status::Success); + wg.deinitialize(); +} + +TEST(WaitGroup, Wait) { + constexpr std::uint64_t goodVal = 0xDEADBEEF; + pando::WaitGroup wg; + pando::GlobalPtr ptr; + pando::LocalStorageGuard ptrGuard(ptr, 1); + *ptr = 0; + EXPECT_EQ(wg.initialize(1), pando::Status::Success); + auto func = +[](pando::WaitGroup::HandleType wg, pando::GlobalPtr ptr, + std::uint64_t goodVal) { + *ptr = goodVal; + wg.done(); + }; + EXPECT_EQ(pando::executeOn(anyZero, func, wg.getHandle(), ptr, goodVal), pando::Status::Success); + EXPECT_EQ(wg.wait(), pando::Status::Success); + EXPECT_EQ(*ptr, goodVal); + wg.deinitialize(); +} + +TEST(WaitGroup, AddOne) { + constexpr std::uint64_t goodVal = 0xDEADBEEF; + pando::WaitGroup wg; + pando::GlobalPtr ptr; + pando::LocalStorageGuard ptrGuard(ptr, 10); + EXPECT_EQ(wg.initialize(0), pando::Status::Success); + *ptr = 0; + wg.getHandle().addOne(); + auto func = +[](pando::WaitGroup::HandleType wg, pando::GlobalPtr ptr, + std::uint64_t goodVal) { + *ptr = goodVal; + wg.done(); + }; + EXPECT_EQ(pando::executeOn(anyZero, func, wg.getHandle(), ptr, goodVal), pando::Status::Success); + EXPECT_EQ(wg.wait(), pando::Status::Success); + EXPECT_EQ(*ptr, goodVal); + wg.deinitialize(); +} + +TEST(WaitGroup, Add) { + constexpr std::uint64_t goodVal = 0xDEADBEEF; + pando::WaitGroup wg; + pando::GlobalPtr ptr; + pando::LocalStorageGuard ptrGuard(ptr, 10); + EXPECT_EQ(wg.initialize(0), pando::Status::Success); + *ptr = 0; + wg.getHandle().add(10); + auto func = +[](pando::WaitGroup::HandleType wg, pando::GlobalPtr ptr, + std::uint64_t goodVal) { + for (std::uint64_t i = 0; i < 9; i++) { + wg.done(); + } + *ptr = goodVal; + wg.done(); + }; + EXPECT_EQ(pando::executeOn(anyZero, func, wg.getHandle(), ptr, goodVal), pando::Status::Success); + EXPECT_EQ(wg.wait(), pando::Status::Success); + EXPECT_EQ(*ptr, goodVal); + wg.deinitialize(); +} + +TEST(WaitGroup, RemoteUsage) { + auto dims = pando::getPlaceDims(); + constexpr std::uint64_t goodVal = 0xDEADBEEF; + pando::WaitGroup wg; + pando::GlobalPtr ptr; + pando::LocalStorageGuard ptrGuard(ptr, dims.node.id); + EXPECT_EQ(wg.initialize(dims.node.id), pando::Status::Success); + auto func = +[](pando::WaitGroup::HandleType wg, pando::GlobalPtr ptr, + std::uint64_t goodVal) { + ptr[pando::getCurrentPlace().node.id] = goodVal; + wg.done(); + }; + for (std::int16_t nodeId = 0; nodeId < dims.node.id; nodeId++) { + EXPECT_EQ( + pando::executeOn(pando::Place{pando::NodeIndex{nodeId}, pando::anyPod, pando::anyCore}, + func, wg.getHandle(), ptr, goodVal), + pando::Status::Success); + } + EXPECT_EQ(wg.wait(), pando::Status::Success); + for (std::int16_t nodeId = 0; nodeId < dims.node.id; nodeId++) { + EXPECT_EQ(*ptr, goodVal); + } + wg.deinitialize(); +} From 719849e1f688a823ad086d2c4715427d58923ff5 Mon Sep 17 00:00:00 2001 From: KavyaVarma Date: Tue, 2 Apr 2024 18:54:43 +0000 Subject: [PATCH 2/3] Turned off pando rt tests --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 36452b26..45997b12 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ CONTAINER_CMD ?= setarch `uname -m` -R bash -l INTERACTIVE ?= i BUILD_TYPE ?= Release -PANDORT_TESTS ?= ON +PANDORT_TESTS ?= OFF # CMake variables PANDO_TEST_DISCOVERY_TIMEOUT ?= 150 From b75734d613a2fa879bc781838d0b9070cffe9273 Mon Sep 17 00:00:00 2001 From: KavyaVarma Date: Thu, 4 Apr 2024 20:41:14 +0000 Subject: [PATCH 3/3] Modified data structures to include waitgroup deinitialize --- include/pando-lib-galois/containers/array.hpp | 13 +++++ .../containers/dist_array.hpp | 16 ++++++ .../pando-lib-galois/containers/hashtable.hpp | 6 +++ .../containers/host_indexed_map.hpp | 4 ++ .../containers/per_thread.hpp | 16 ++++++ include/pando-lib-galois/containers/stack.hpp | 8 +++ .../memory/deallocate_memory_wait.hpp | 4 +- test/containers/test_array.cpp | 23 ++++++++ test/containers/test_dist_array.cpp | 33 ++++++++++++ test/containers/test_hashtable.cpp | 24 +++++++++ test/containers/test_host_indexed_map.cpp | 54 +++++++++++++++++++ test/containers/test_per_thread.cpp | 40 ++++++++++++++ test/containers/test_stack.cpp | 50 +++++++++++++++++ 13 files changed, 289 insertions(+), 2 deletions(-) diff --git a/include/pando-lib-galois/containers/array.hpp b/include/pando-lib-galois/containers/array.hpp index 0e7be8a9..61a95216 100644 --- a/include/pando-lib-galois/containers/array.hpp +++ b/include/pando-lib-galois/containers/array.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace galois { @@ -105,6 +106,18 @@ class Array { m_size = 0; } + /** + * @brief Deinitializes the array. + */ + void deinitialize(pando::WaitGroup::HandleType wgh) { + static_assert(std::is_trivially_destructible_v, + "Array only supports trivially destructible types"); + + pando::deallocateMemory(m_data, m_size, wgh); + m_data = nullptr; + m_size = 0; + } + constexpr pando::GlobalPtr get(std::uint64_t pos) noexcept { return &m_data[pos]; } diff --git a/include/pando-lib-galois/containers/dist_array.hpp b/include/pando-lib-galois/containers/dist_array.hpp index ed6d9758..5f1b17ab 100644 --- a/include/pando-lib-galois/containers/dist_array.hpp +++ b/include/pando-lib-galois/containers/dist_array.hpp @@ -281,6 +281,22 @@ class DistArray { m_data.deinitialize(); } + /** + * @brief Deinitializes the array. + */ + void deinitialize(pando::WaitGroup::HandleType wgh) { + static_assert(std::is_trivially_destructible_v, + "Array only supports trivially destructible types"); + + if (m_data.data() == nullptr) { + return; + } + for (pando::Array array : m_data) { + array.deinitialize(wgh); + } + m_data.deinitialize(wgh); + } + constexpr pando::GlobalRef operator[](std::uint64_t pos) noexcept { return *get(pos); } diff --git a/include/pando-lib-galois/containers/hashtable.hpp b/include/pando-lib-galois/containers/hashtable.hpp index 81e71905..4a6901cf 100644 --- a/include/pando-lib-galois/containers/hashtable.hpp +++ b/include/pando-lib-galois/containers/hashtable.hpp @@ -136,6 +136,12 @@ class HashTable { m_size = 0; } + // @brief Deinitialize the hashtable + void deinitialize(pando::WaitGroup::HandleType wgh) { + m_buffer.deinitialize(wgh); + m_size = 0; + } + // @brief Resizes the backing array to `capacity`. pando::Status resize(std::size_t capacity) { if (capacity <= m_buffer.size()) { diff --git a/include/pando-lib-galois/containers/host_indexed_map.hpp b/include/pando-lib-galois/containers/host_indexed_map.hpp index 22a626f6..ce1a50c5 100644 --- a/include/pando-lib-galois/containers/host_indexed_map.hpp +++ b/include/pando-lib-galois/containers/host_indexed_map.hpp @@ -57,6 +57,10 @@ class HostIndexedMap { deallocateMemory(m_items, getNumHosts()); } + void deinitialize(pando::WaitGroup::HandleType wgh) { + deallocateMemory(m_items, getNumHosts(), wgh); + } + pando::GlobalRef getLocal() noexcept { return m_items[getCurrentNode()]; } diff --git a/include/pando-lib-galois/containers/per_thread.hpp b/include/pando-lib-galois/containers/per_thread.hpp index 3a8a49f4..18a9a762 100644 --- a/include/pando-lib-galois/containers/per_thread.hpp +++ b/include/pando-lib-galois/containers/per_thread.hpp @@ -118,6 +118,22 @@ class PerThreadVector { m_data.deinitialize(); } + /** + * @brief Deinitializes the PerThreadVector array. + */ + void deinitialize(pando::WaitGroup::HandleType wgh) { + if (m_indices.m_data.data() != nullptr) { + m_indices.deinitialize(wgh); + } + if (m_data.m_data.data() == nullptr) { + return; + } + for (pando::Vector vec : m_data) { + vec.deinitialize(wgh); + } + m_data.deinitialize(wgh); + } + /** * @brief Returns the current hardware thread's vector. */ diff --git a/include/pando-lib-galois/containers/stack.hpp b/include/pando-lib-galois/containers/stack.hpp index 2061e6cf..dc151eae 100644 --- a/include/pando-lib-galois/containers/stack.hpp +++ b/include/pando-lib-galois/containers/stack.hpp @@ -106,6 +106,14 @@ class Stack { m_size = 0; } + /** + * @brief Deinitializes the container. + */ + void deinitialize(pando::WaitGroup::HandleType wgh) { + m_buf.deinitialize(wgh); + m_size = 0; + } + bool empty() const { return size() == 0; } diff --git a/pando-rt/include/pando-rt/memory/deallocate_memory_wait.hpp b/pando-rt/include/pando-rt/memory/deallocate_memory_wait.hpp index 5b872ed2..f265ff82 100644 --- a/pando-rt/include/pando-rt/memory/deallocate_memory_wait.hpp +++ b/pando-rt/include/pando-rt/memory/deallocate_memory_wait.hpp @@ -76,8 +76,8 @@ void deallocateMemory(GlobalPtr p, std::uint64_t n, pando::WaitGroup::HandleT if (!isOnCP() && (thisPlace.node == place.node) && (thisPlace.pod == place.pod)) { detail::deallocateMemoryImpl(p, numBytes); } else { - if (executeOn(place, &detail::deallocateMemoryImpl, static_cast>(p), - numBytes) != Status::Success) { + if (executeOn(place, &detail::deallocateMemoryWaitImpl, static_cast>(p), + numBytes, wgh) != Status::Success) { PANDO_ABORT("Deallocation failed"); } } diff --git a/test/containers/test_array.cpp b/test/containers/test_array.cpp index 1bec73d5..7746f5ed 100644 --- a/test/containers/test_array.cpp +++ b/test/containers/test_array.cpp @@ -323,3 +323,26 @@ TEST(Array, Equivalence) { arr0.deinitialize(); arr1.deinitialize(); } + +TEST(Array, DeinitializeWgh) { + const std::uint64_t size = 10; + + galois::Array array; + EXPECT_EQ(array.initialize(size), pando::Status::Success); + EXPECT_EQ(array.size(), size); + EXPECT_NE(array.data(), nullptr); + + for (std::uint64_t i = 0; i < size; i++) { + array[i] = i; + } + + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(array[i], i); + } + + pando::WaitGroup wg; + EXPECT_EQ(wg.initialize(0), pando::Status::Success); + array.deinitialize(wgh); + EXPECT_EQ(wg.wait(), pando::Status::Success); + wg.deinitialize(); +} diff --git a/test/containers/test_dist_array.cpp b/test/containers/test_dist_array.cpp index ed5a419d..e22c4b7c 100644 --- a/test/containers/test_dist_array.cpp +++ b/test/containers/test_dist_array.cpp @@ -350,3 +350,36 @@ TEST(DistArray, DISABLED_DistributedSort) { } array.deinitialize(); } + +TEST(DistArray, DeinitializeWgh) { + const std::uint64_t size = 10; + pando::Vector vec; + EXPECT_EQ(vec.initialize(size), pando::Status::Success); + for (std::int16_t i = 0; i < static_cast(size); i++) { + std::int16_t nodeIdx = i % pando::getPlaceDims().node.id; + vec[i] = PlaceType{pando::Place{pando::NodeIndex{nodeIdx}, pando::anyPod, pando::anyCore}, + pando::MemoryType::Main}; + } + + galois::DistArray array; + + EXPECT_EQ(array.initialize(vec.begin(), vec.end(), size), pando::Status::Success); + EXPECT_EQ(array.size(), size); + + for (std::uint64_t i = 0; i < size; i++) { + std::int16_t nodeIdx = i % pando::getPlaceDims().node.id; + EXPECT_EQ(pando::localityOf(&array[i]).node.id, nodeIdx); + array[i] = i; + } + + for (std::uint64_t i = 0; i < size; i++) { + EXPECT_EQ(array[i], i); + } + + pando::WaitGroup wg; + EXPECT_EQ(wg.initialize(0), pando::Status::Success); + array.deinitialize(wg.getHandle()); + EXPECT_EQ(wg.wait(), pando::Status::Success); + wg.deinitialize(); + vec.deinitialize(); +} diff --git a/test/containers/test_hashtable.cpp b/test/containers/test_hashtable.cpp index 76613112..530544f8 100644 --- a/test/containers/test_hashtable.cpp +++ b/test/containers/test_hashtable.cpp @@ -306,3 +306,27 @@ TEST(HashTable, PutGet900LoadOne) { checkCorrectness(table); table.deinitialize(); } + +TEST(HashTable, DeinitializeWgh) { + galois::HashTable table{}; + + EXPECT_EQ(table.initialize(8), pando::Status::Success); + table.put(1, 1); + table.put(2, 2); + table.put(3, 3); + table.put(4, 4); + checkCorrectness(table); + table.put(5, 5); + table.put(6, 6); + table.put(7, 7); + table.put(8, 8); + table.put(9, 9); + checkCorrectness(table); + + EXPECT_GT(table.capacity(), 8); + pando::WaitGroup wg; + EXPECT_EQ(wg.initialize(0), pando::Status::Success); + table.deinitialize(wg.getHandle()); + EXPECT_EQ(wg.wait(), pando::Status::Success); + wg.deinitialize(); +} diff --git a/test/containers/test_host_indexed_map.cpp b/test/containers/test_host_indexed_map.cpp index 8e9ebd89..69fc4a17 100644 --- a/test/containers/test_host_indexed_map.cpp +++ b/test/containers/test_host_indexed_map.cpp @@ -97,3 +97,57 @@ TEST(HostIndexedMap, DoAll) { ph.deinitialize(); } + +TEST(HostIndexedMap, DeinitializeWgh) { + galois::HostIndexedMap ph; + pando::Status err; + + EXPECT_EQ(ph.initialize(), pando::Status::Success); + std::uint64_t i = 0; + for (pando::GlobalRef val : ph) { + val = i; + i++; + } + auto f = +[](galois::HostIndexedMap ph, std::uint64_t i, + pando::NotificationHandle done) { + EXPECT_EQ(&ph.getLocal(), &ph.get(i)); + EXPECT_EQ(ph.getLocal(), ph.getCurrentNode()); + done.notify(); + }; + + pando::NotificationArray dones; + err = dones.init(ph.getNumHosts()); + EXPECT_EQ(err, pando::Status::Success); + for (std::uint64_t i = 0; i < ph.getNumHosts(); i++) { + auto place = + pando::Place{pando::NodeIndex{static_cast(i)}, pando::anyPod, pando::anyCore}; + err = pando::executeOn(place, f, ph, i, dones.getHandle(i)); + EXPECT_EQ(err, pando::Status::Success); + } + dones.wait(); + + pando::WaitGroup wg; + EXPECT_EQ(wg.initialize(0), pando::Status::Success); + ph.deinitialize(wg.getHandle()); + + EXPECT_EQ(ph.initialize(), pando::Status::Success); + i = 0; + for (pando::GlobalRef val : ph) { + val = i; + i++; + } + + dones.reset(); + EXPECT_EQ(err, pando::Status::Success); + for (std::uint64_t i = 0; i < ph.getNumHosts(); i++) { + auto place = + pando::Place{pando::NodeIndex{static_cast(i)}, pando::anyPod, pando::anyCore}; + err = pando::executeOn(place, f, ph, i, dones.getHandle(i)); + EXPECT_EQ(err, pando::Status::Success); + } + dones.wait(); + + ph.deinitialize(wg.getHandle()); + EXPECT_EQ(wg.wait(), pando::Status::Success); + wg.deinitialize(); +} diff --git a/test/containers/test_per_thread.cpp b/test/containers/test_per_thread.cpp index 8d02c9ef..0cefbf16 100644 --- a/test/containers/test_per_thread.cpp +++ b/test/containers/test_per_thread.cpp @@ -615,3 +615,43 @@ TEST(Vector, EdgelistVectorOfVectors) { table.deinitialize(); vec.deinitialize(); } + +TEST(PerThreadVector, DeinitializeWgh) { + pando::GlobalPtr> perThreadVecPtr = + getGlobalObject>(); + galois::PerThreadVector perThreadVec = *perThreadVecPtr; + EXPECT_EQ(16, pando::getThreadDims().id); + EXPECT_EQ(perThreadVec.initialize(), pando::Status::Success); + pando::Vector work; + EXPECT_EQ(work.initialize(1), pando::Status::Success); + work[0] = 9801; + galois::doAll( + perThreadVec, work, +[](galois::PerThreadVector perThreadVec, uint64_t x) { + EXPECT_GE(pando::getCurrentThread().id, 0); + EXPECT_EQ(perThreadVec.pushBack(x), pando::Status::Success); + pando::Vector localVec = perThreadVec.getThreadVector(); + EXPECT_EQ(localVec.size(), 1); + }); + EXPECT_EQ(perThreadVec.sizeAll(), 1); + + uint64_t elts = 0; + for (pando::Vector vec : perThreadVec) { + elts += vec.size(); + } + EXPECT_EQ(elts, 1); + + *perThreadVecPtr = perThreadVec; + galois::DistArray copy; + EXPECT_EQ(perThreadVec.assign(copy), pando::Status::Success); + EXPECT_EQ(copy.size(), 1); + uint64_t val = copy[0]; + EXPECT_EQ(val, 9801); + + pando::WaitGroup wg; + EXPECT_EQ(wg.initialize(0), pando::Status::Success); + copy.deinitialize(); + work.deinitialize(); + perThreadVec.deinitialize(); + EXPECT_EQ(wg.wait(), pando::Status::Success); + wg.deinitialize(); +} diff --git a/test/containers/test_stack.cpp b/test/containers/test_stack.cpp index dc6bdfa1..40632155 100644 --- a/test/containers/test_stack.cpp +++ b/test/containers/test_stack.cpp @@ -52,6 +52,9 @@ TEST(Stack, Init) { EXPECT_EQ(val, canary); EXPECT_EQ(s2.size(), 0); EXPECT_EQ(s2.capacity(), 10); + + s1.deinitialize(); + s2.deinitialize(); } TEST(Stack, Grow) { @@ -77,3 +80,50 @@ TEST(Stack, Grow) { EXPECT_EQ(s.size(), 0); EXPECT_EQ(s.pop(check), pando::Status::OutOfBounds); } + +TEST(Stack, DeinitWgh) { + uint64_t val = canary; + galois::Stack s1; + EXPECT_EQ(s1.initialize(0), pando::Status::Success); + EXPECT_EQ(s1.size(), 0); + EXPECT_EQ(s1.capacity(), 1); + EXPECT_EQ(s1.pop(val), pando::Status::OutOfBounds); + EXPECT_EQ(val, canary); + EXPECT_EQ(s1.emplace(val), pando::Status::Success); + EXPECT_EQ(s1.size(), 1); + EXPECT_GT(s1.capacity(), 0); + val = 73; + EXPECT_EQ(s1.pop(val), pando::Status::Success); + EXPECT_EQ(val, canary); + EXPECT_EQ(s1.size(), 0); + EXPECT_GT(s1.capacity(), 0); + EXPECT_EQ(s1.pop(val), pando::Status::OutOfBounds); + EXPECT_EQ(val, canary); + EXPECT_EQ(s1.size(), 0); + EXPECT_GT(s1.capacity(), 0); + + galois::Stack s2; + EXPECT_EQ(s2.initialize(10), pando::Status::Success); + EXPECT_EQ(s2.size(), 0); + EXPECT_EQ(s2.capacity(), 10); + EXPECT_EQ(s2.pop(val), pando::Status::OutOfBounds); + EXPECT_EQ(val, canary); + EXPECT_EQ(s2.emplace(val), pando::Status::Success); + EXPECT_EQ(s2.size(), 1); + EXPECT_EQ(s2.capacity(), 10); + val = 73; + EXPECT_EQ(s2.pop(val), pando::Status::Success); + EXPECT_EQ(val, canary); + EXPECT_EQ(s2.size(), 0); + EXPECT_EQ(s2.capacity(), 10); + EXPECT_EQ(s2.pop(val), pando::Status::OutOfBounds); + EXPECT_EQ(val, canary); + EXPECT_EQ(s2.size(), 0); + EXPECT_EQ(s2.capacity(), 10); + pando::WaitGroup wg; + EXPECT_EQ(wg.initialize(0), pando::Status::Success); + s1.deinitialize(wg.getHandle()); + s2.deinitialize(wg.getHandle()); + EXPECT_EQ(wg.wait(), pando::Status::Success); + wg.deinitialize(); +}