Transfer files from RAD repository
Αυτή η υποβολή περιλαμβάνεται σε:
@@ -0,0 +1,32 @@
|
||||
###############################################################################
|
||||
# Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
# IN THE SOFTWARE.
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# ADD ROCSHMEM TARGET FOR FILES IN CURRENT DIRECTORY
|
||||
###############################################################################
|
||||
target_sources(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
single_heap.cpp
|
||||
slab_heap.cpp
|
||||
memory_allocator.cpp
|
||||
)
|
||||
@@ -0,0 +1,133 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_ADDRESS_RECORD_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_ADDRESS_RECORD_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* @file address_record.hpp
|
||||
*
|
||||
* @brief Contains an address record class
|
||||
*
|
||||
* The address record is intended to be used by allocators which need to
|
||||
* keep track of raw pointers and the corresponding allocation size.
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class AddressRecord {
|
||||
/**
|
||||
* @brief Helper type for address records
|
||||
*/
|
||||
using AR_T = AddressRecord;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*
|
||||
* @note This constructor generates an empty record. In some contexts,
|
||||
* an empty record signifies an INVALID record and is treated
|
||||
* accordingly.
|
||||
*/
|
||||
AddressRecord() = default;
|
||||
|
||||
/**
|
||||
* @brief Primary constructor type
|
||||
*
|
||||
* @param[in] raw pointer holding an address
|
||||
* @param[in] size
|
||||
*/
|
||||
AddressRecord(char* address, size_t size) : address_(address), size_(size) {}
|
||||
|
||||
/**
|
||||
* @brief Accessor for address_
|
||||
*
|
||||
* @return raw pointer
|
||||
*/
|
||||
char* get_address() { return address_; }
|
||||
|
||||
/**
|
||||
* @brief Accessor for size_
|
||||
*
|
||||
* @return size
|
||||
*/
|
||||
size_t get_size() { return size_; }
|
||||
|
||||
/**
|
||||
* @brief Splits record in half
|
||||
*
|
||||
* @return pair containing initialized address records
|
||||
*/
|
||||
std::pair<AR_T, AR_T> split() {
|
||||
assert(address_);
|
||||
assert(size_);
|
||||
auto half_size{size_ >> 1};
|
||||
assert(half_size);
|
||||
|
||||
AR_T e1{address_, half_size};
|
||||
AR_T e2{address_ + half_size, half_size};
|
||||
|
||||
return {e1, e2};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Combines record with another record
|
||||
*
|
||||
* @return an address record containing both input records
|
||||
*/
|
||||
AR_T combine(AR_T other) {
|
||||
assert(address_);
|
||||
assert(other.get_address());
|
||||
bool this_smaller{address_ < other.get_address()};
|
||||
|
||||
auto smaller_addr{this_smaller ? address_ : other.get_address()};
|
||||
[[maybe_unused]] auto larger_addr{this_smaller ? other.get_address()
|
||||
: address_};
|
||||
|
||||
assert(size_ == other.get_size());
|
||||
auto combined_size{size_ + size_};
|
||||
|
||||
assert(smaller_addr + size_ == larger_addr);
|
||||
|
||||
AR_T record{smaller_addr, combined_size};
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief raw memory pointer
|
||||
*/
|
||||
char* address_{nullptr};
|
||||
|
||||
/**
|
||||
* @brief size of address record
|
||||
*/
|
||||
size_t size_{0};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_ADDRESS_RECORD_HPP_
|
||||
@@ -0,0 +1,85 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_BIN_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_BIN_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <stack>
|
||||
|
||||
/**
|
||||
* @file bin.hpp
|
||||
*
|
||||
* @brief Simple container class
|
||||
*
|
||||
* The class wraps a stack and provides simple mutators. A different internal
|
||||
* container class might be preferable to a stack.
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
template <typename T>
|
||||
class Bin {
|
||||
public:
|
||||
/**
|
||||
* @brief Is stack empty?
|
||||
*
|
||||
* @return A boolean denoting stack emptiness
|
||||
*/
|
||||
bool empty() { return stack_.empty(); }
|
||||
|
||||
/**
|
||||
* @brief How many elements in stack?
|
||||
*
|
||||
* @return The number of elements in the stack
|
||||
*/
|
||||
size_t size() { return stack_.size(); }
|
||||
|
||||
/**
|
||||
* @brief Emplace an element in stack
|
||||
*
|
||||
* @param[in] An element
|
||||
*/
|
||||
void put(T element) { stack_.emplace(element); }
|
||||
|
||||
/**
|
||||
* @brief Retrieve an element from stack
|
||||
*
|
||||
* @return An element
|
||||
*/
|
||||
T get() {
|
||||
assert(stack_.size());
|
||||
auto top = stack_.top();
|
||||
stack_.pop();
|
||||
return top;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Implementation container
|
||||
*/
|
||||
std::stack<T> stack_{};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_BIN_HPP_
|
||||
@@ -0,0 +1,246 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_BINNER_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_BINNER_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "../constants.hpp"
|
||||
#include "bin.hpp"
|
||||
|
||||
/**
|
||||
* @file binner.hpp
|
||||
*
|
||||
* @brief Contains a builder for bins_ object in Pow2Bins.
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
/**
|
||||
* @brief Helper to choose between clz variants
|
||||
*
|
||||
* @param[in] An input value
|
||||
*
|
||||
* @return __builtin_clz value
|
||||
*/
|
||||
template <typename T>
|
||||
inline int clz_fn([[maybe_unused]] T v) {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int clz_fn(unsigned v) {
|
||||
return __builtin_clz(v);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int clz_fn(unsigned long v) {
|
||||
return __builtin_clzl(v);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int clz_fn(unsigned long long v) {
|
||||
return __builtin_clzll(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finds the bit position of the first one
|
||||
*
|
||||
* @param[in] An input value
|
||||
*
|
||||
* @return A bit position or UINT_MAX
|
||||
*/
|
||||
template <typename T>
|
||||
inline unsigned find_first_set_one(T v) {
|
||||
if (v == 0) {
|
||||
return UINT_MAX;
|
||||
}
|
||||
auto num_bytes{sizeof(T)};
|
||||
auto num_bits{num_bytes * CHAR_BIT};
|
||||
auto num_leading_zeroes{clz_fn(v)};
|
||||
auto last_zero_bit_position{num_bits - num_leading_zeroes};
|
||||
auto first_one_bit_position{last_zero_bit_position - 1};
|
||||
return first_one_bit_position;
|
||||
}
|
||||
|
||||
template <typename AR_T, typename BINS_T>
|
||||
class Binner {
|
||||
public:
|
||||
/**
|
||||
* @brief Required for default construction of other objects
|
||||
*
|
||||
* @note Not intended for direct usage.
|
||||
*/
|
||||
Binner() = default;
|
||||
|
||||
/**
|
||||
* @brief Primary constructor type
|
||||
*
|
||||
* Constructs bins by inserting a set of bin into it.
|
||||
*
|
||||
* @param[in] Raw memory pointer to bins object
|
||||
* @param[in] Raw memory pointer to symmetric heap memory.
|
||||
* @param[in] Size of symmetric heap allocation.
|
||||
*/
|
||||
Binner(BINS_T* bins, char* heap_ptr, size_t heap_size)
|
||||
: bins_{bins}, heap_{heap_ptr, heap_size} {
|
||||
auto bit_position_heap{find_first_set_one(heap_size)};
|
||||
assert(bit_position_heap != UINT_MAX);
|
||||
|
||||
auto bit_position_align{find_first_set_one(ALIGNMENT)};
|
||||
assert(bit_position_align != UINT_MAX);
|
||||
|
||||
assert(bit_position_heap >= bit_position_align);
|
||||
|
||||
auto difference_in_position{bit_position_heap - bit_position_align};
|
||||
auto vector_size{difference_in_position + 1};
|
||||
|
||||
std::vector<size_t> v;
|
||||
v.resize(vector_size);
|
||||
|
||||
auto pow2 = [&bit_position_align]() {
|
||||
return std::pow(2, bit_position_align++);
|
||||
};
|
||||
|
||||
std::generate(v.begin(), v.end(), pow2);
|
||||
|
||||
for (auto x : v) {
|
||||
bins_->insert({x, Bin<AR_T>{}});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assign symmetric heap memory to bins object
|
||||
*/
|
||||
void assign_heap_to_bins() {
|
||||
assert(bins_);
|
||||
assert(heap_.get_address());
|
||||
assert(heap_.get_size());
|
||||
|
||||
ignore_unaligned_heap_memory();
|
||||
assign_heap_memory_to_bins();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Accessor for bins_ pointer.
|
||||
*
|
||||
* @return Raw pointer to bins_
|
||||
*
|
||||
* @note Used by unit-test test fixture
|
||||
*/
|
||||
BINS_T* get_bins() { return bins_; }
|
||||
|
||||
/**
|
||||
* @brief Dump the bins_ object to the standard out
|
||||
*/
|
||||
void dump_bins() {
|
||||
auto dump_bin = [](const auto& pair) {
|
||||
auto [address, bin] = pair;
|
||||
std::cout << "address " << address << " bin.size " << bin.size()
|
||||
<< std::endl;
|
||||
};
|
||||
std::for_each(bins_->begin(), bins_->end(), dump_bin);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Shift assignment point past unaligned memory.
|
||||
*/
|
||||
void ignore_unaligned_heap_memory() {
|
||||
static_assert(sizeof(char) == 1);
|
||||
|
||||
auto heap_ptr{heap_.get_address()};
|
||||
size_t off_by_bytes{reinterpret_cast<size_t>(heap_ptr) % ALIGNMENT};
|
||||
|
||||
if (off_by_bytes) {
|
||||
size_t required_offset{ALIGNMENT - off_by_bytes};
|
||||
heap_ptr += required_offset;
|
||||
auto heap_size{heap_.get_size() - required_offset};
|
||||
heap_ = AR_T(heap_ptr, heap_size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delegate method for top-level heap assignment.
|
||||
*/
|
||||
void assign_heap_memory_to_bins() {
|
||||
AR_T chunk = heap_;
|
||||
while (chunk.get_address()) {
|
||||
chunk = assign_heap_chunk(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Chunk heap memory up into bin sized allocations
|
||||
*
|
||||
* The method starts with the largest chunks possible and proceeds
|
||||
* to smaller chunks. It continues chunking until there are no more
|
||||
* chunks which will fit into bins.
|
||||
*
|
||||
* @param[in] An address record
|
||||
*
|
||||
* @return An address record minus a chunk
|
||||
*/
|
||||
AR_T assign_heap_chunk(AR_T address_record) {
|
||||
char* memory_chunk{address_record.get_address()};
|
||||
size_t memory_chunk_size{address_record.get_size()};
|
||||
|
||||
auto rit{bins_->rbegin()};
|
||||
auto rend{bins_->rend()};
|
||||
while (rit != rend) {
|
||||
auto& [bin_memory_chunk_size, bin] = *rit;
|
||||
if (memory_chunk_size >= bin_memory_chunk_size) {
|
||||
break;
|
||||
}
|
||||
rit++;
|
||||
}
|
||||
|
||||
if (rit == rend) {
|
||||
return {nullptr, 0};
|
||||
}
|
||||
|
||||
auto& [bin_memory_chunk_size, bin] = *rit;
|
||||
bin.put({memory_chunk, bin_memory_chunk_size});
|
||||
|
||||
return {memory_chunk + bin_memory_chunk_size,
|
||||
memory_chunk_size - bin_memory_chunk_size};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Raw pointer to external bins_ object
|
||||
*/
|
||||
BINS_T* bins_{nullptr};
|
||||
|
||||
/**
|
||||
* @brief An address record holding heap object's information
|
||||
*/
|
||||
AR_T heap_{};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_BINNER_HPP_
|
||||
@@ -0,0 +1,144 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_DEV_MONO_LINEAR_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_DEV_MONO_LINEAR_HPP_
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "shmem_allocator_strategy.hpp"
|
||||
#include "../util.hpp"
|
||||
|
||||
/**
|
||||
* @file dev_mono_linear.hpp
|
||||
*
|
||||
* @brief Contains an allocator strategy for the heap.
|
||||
*
|
||||
* This strategy returns memory chunks by monotonically increasing a pointer.
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
template <typename HM_T>
|
||||
class DevMonoLinear : public ShmemAllocatorStrategy {
|
||||
public:
|
||||
/**
|
||||
* @brief Required for default construction of other objects
|
||||
*
|
||||
* @note Not intended for direct usage.
|
||||
*/
|
||||
DevMonoLinear() = default;
|
||||
|
||||
/**
|
||||
* @brief Primary constructor type
|
||||
*
|
||||
* @param[in] Raw pointer to heap memory type
|
||||
*/
|
||||
explicit DevMonoLinear(HM_T* heap_mem)
|
||||
: heap_mem_{heap_mem}, current_ptr_{heap_mem_->get_ptr()} {}
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from the heap
|
||||
*
|
||||
* @param[in, out] Address of raw pointer (&pointer_to_char)
|
||||
* @param[in] Size in bytes of memory allocation
|
||||
*/
|
||||
void alloc(char** ptr, size_t request_size) override {
|
||||
assert(ptr);
|
||||
*ptr = nullptr;
|
||||
|
||||
if (!request_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
char* heap_end{heap_mem_->get_ptr() + heap_mem_->get_size()};
|
||||
|
||||
if (current_ptr_ + request_size < heap_end) {
|
||||
*ptr = current_ptr_;
|
||||
current_ptr_ += request_size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from the heap
|
||||
*
|
||||
* @param[in, out] Address of raw pointer (&pointer_to_char)
|
||||
* @param[in] Size in bytes of memory allocation
|
||||
*/
|
||||
__device__ void alloc(char** ptr, size_t request_size) override {
|
||||
if (is_thread_zero_in_block()) {
|
||||
assert(ptr);
|
||||
*ptr = nullptr;
|
||||
|
||||
if (!request_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
char* heap_end{heap_mem_->get_ptr() + heap_mem_->get_size()};
|
||||
|
||||
if (current_ptr_ + request_size < heap_end) {
|
||||
*ptr = current_ptr_;
|
||||
current_ptr_ += request_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Frees memory from the heap
|
||||
*
|
||||
* Released memory ignored.
|
||||
*
|
||||
* @param[in] Raw pointer to heap memory
|
||||
*/
|
||||
__host__ void free([[maybe_unused]] char* ptr) override {}
|
||||
|
||||
/**
|
||||
* @brief Frees memory from the heap
|
||||
*
|
||||
* Released memory ignored.
|
||||
*
|
||||
* @param[in] Raw pointer to heap memory
|
||||
*/
|
||||
__device__ void free([[maybe_unused]] char* ptr) override {}
|
||||
|
||||
/**
|
||||
* @brief Return pointer to monotonic linear ptr
|
||||
*
|
||||
* @return Raw pointer to heap memory.
|
||||
*/
|
||||
__host__ __device__ char* current() { return current_ptr_; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* The pointer is used to keep reference to heap memory.
|
||||
*/
|
||||
HM_T* heap_mem_{nullptr};
|
||||
|
||||
/**
|
||||
* The pointer is used to track the next allocation point.
|
||||
*/
|
||||
char* current_ptr_{nullptr};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_DEV_MONO_LINEAR_HPP_
|
||||
@@ -0,0 +1,133 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_HEAP_MEMORY_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_HEAP_MEMORY_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* @file heap_memory.hpp
|
||||
*
|
||||
* @brief Contains heap memory class
|
||||
*
|
||||
* @note The heap memory class owns the symmetric heap memory allocation
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
template <typename ALLOCATOR>
|
||||
class HeapMemory {
|
||||
public:
|
||||
/**
|
||||
* @brief Primary constructor type
|
||||
*
|
||||
* Uses default heap size specified in class body.
|
||||
*/
|
||||
HeapMemory() : HeapMemory(gibibyte_) {}
|
||||
|
||||
/**
|
||||
* @brief Secondary constructor type
|
||||
*
|
||||
* @param[in] User-specified size used as heap size
|
||||
*/
|
||||
explicit HeapMemory(size_t size) : size_{size} {
|
||||
char* temp;
|
||||
allocator_.allocate(reinterpret_cast<void**>(&temp), size_);
|
||||
assert(temp);
|
||||
std::unique_ptr<char, Deleter> up{temp};
|
||||
up_ = std::move(up);
|
||||
|
||||
/*
|
||||
* Set a c-style ptr for access by the device.
|
||||
*/
|
||||
ptr_ = up_.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap ptr
|
||||
*
|
||||
* @return Raw memory pointer
|
||||
*/
|
||||
__host__ __device__ char* get_ptr() { return ptr_; }
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap size
|
||||
*
|
||||
* @return Heap size
|
||||
*/
|
||||
__host__ __device__ size_t get_size() { return size_; }
|
||||
|
||||
/**
|
||||
* @brief Returns is the heap is allocated with managed memory
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
bool is_managed() { return allocator_.is_managed(); }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Template type member with allocate and deallocate methods.
|
||||
*/
|
||||
ALLOCATOR allocator_{};
|
||||
|
||||
/**
|
||||
* @brief Wrap deallocator into a functor for up_ template.
|
||||
*/
|
||||
class Deleter {
|
||||
public:
|
||||
void operator()(void* x) { a_.deallocate(x); }
|
||||
|
||||
private:
|
||||
ALLOCATOR a_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Owning pointer to heap memory.
|
||||
*/
|
||||
std::unique_ptr<char, Deleter> up_{nullptr};
|
||||
|
||||
/**
|
||||
* @brief Named constant for a gibibyte.
|
||||
*/
|
||||
static constexpr size_t gibibyte_{1 << 30};
|
||||
|
||||
/**
|
||||
* @brief Size of heap memory.
|
||||
*/
|
||||
size_t size_{gibibyte_};
|
||||
|
||||
/**
|
||||
* @brief A handle to access the internal memory.
|
||||
*
|
||||
* In general, device code cannot access standard library routines
|
||||
* like std::unique_ptr::get(). Circumvent this problem by caching
|
||||
* the pointer manually in this class.
|
||||
*/
|
||||
char* ptr_{nullptr};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_HEAP_MEMORY_HPP_
|
||||
@@ -0,0 +1,55 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_HEAP_TYPE_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_HEAP_TYPE_HPP_
|
||||
|
||||
#include "config.h" // NOLINT(build/include_subdir)
|
||||
#include "hip_allocator.hpp"
|
||||
|
||||
/**
|
||||
* @file heap_type.hpp
|
||||
*
|
||||
* @brief Contains the type of heap memory used to allocate the symmetric heap
|
||||
*
|
||||
* The heap type in this file is used by other classes to select the allocation
|
||||
* policy for the symmetric heap. The heap type choices depend on whether
|
||||
* the heap is cacheable in hardware and if the heap is a managed memory type.
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
#if defined USE_MANAGED_HEAP
|
||||
using HEAP_T = HeapMemory<HIPAllocatorManaged>;
|
||||
#elif defined USE_COHERENT_HEAP || defined USE_CACHED_HEAP
|
||||
using HEAP_T = HeapMemory<HIPAllocator>;
|
||||
#elif defined USE_HOST_HEAP
|
||||
using HEAP_T = HeapMemory<HostAllocator>;
|
||||
#elif defined USE_HIP_HOST_HEAP
|
||||
using HEAP_T = HeapMemory<HIPHostAllocator>;
|
||||
#else
|
||||
using HEAP_T = HeapMemory<HIPDefaultFinegrainedAllocator>;
|
||||
#endif
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_HEAP_TYPE_HPP_
|
||||
@@ -0,0 +1,139 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_HIP_ALLOCATOR_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_HIP_ALLOCATOR_HPP_
|
||||
|
||||
/**
|
||||
* @file hip_allocator.hpp
|
||||
*
|
||||
* @brief Contains HIP wrapper class for memory allocator
|
||||
*/
|
||||
|
||||
#include <hip/hip_runtime_api.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
|
||||
#include "memory_allocator.hpp"
|
||||
|
||||
// `hipDeviceMallocUncached` was introduced at ROCm 5.5
|
||||
#if HIP_VERSION_MAJOR >= 5 && HIP_VERSION_MINOR >= 5
|
||||
#define HIP_SUPPORTS_MALLOC_UNCACHED
|
||||
#endif
|
||||
namespace rocshmem {
|
||||
|
||||
class HIPAllocator : public MemoryAllocator {
|
||||
public:
|
||||
HIPAllocator() : MemoryAllocator(hipMalloc, hipFree) {}
|
||||
};
|
||||
|
||||
class HIPAllocatorFinegrained : public MemoryAllocator {
|
||||
public:
|
||||
HIPAllocatorFinegrained()
|
||||
: MemoryAllocator(hipExtMallocWithFlags, hipFree,
|
||||
hipDeviceMallocFinegrained) {}
|
||||
};
|
||||
|
||||
#ifdef HIP_SUPPORTS_MALLOC_UNCACHED
|
||||
class HIPAllocatorUncached : public MemoryAllocator {
|
||||
public:
|
||||
HIPAllocatorUncached()
|
||||
: MemoryAllocator(hipExtMallocWithFlags, hipFree,
|
||||
hipDeviceMallocUncached) {}
|
||||
};
|
||||
// The default fine-grained coherence allocator is the uncached allocator
|
||||
using HIPDefaultFinegrainedAllocator = HIPAllocatorUncached;
|
||||
#else
|
||||
// The default fine-grained coherence allocator is the fine-grained allocator
|
||||
using HIPDefaultFinegrainedAllocator = HIPAllocatorFinegrained;
|
||||
#endif
|
||||
|
||||
class HIPAllocatorManaged : public MemoryAllocator {
|
||||
public:
|
||||
HIPAllocatorManaged()
|
||||
: MemoryAllocator(hipMallocManaged, hipFree, hipMemAttachHost) {
|
||||
_managed = true;
|
||||
}
|
||||
};
|
||||
|
||||
class HIPHostAllocator : public MemoryAllocator {
|
||||
public:
|
||||
HIPHostAllocator()
|
||||
: MemoryAllocator(hipHostMalloc, hipFree, hipHostMallocCoherent) {}
|
||||
};
|
||||
|
||||
class HostAllocator : public MemoryAllocator {
|
||||
public:
|
||||
HostAllocator() : MemoryAllocator(std::malloc, std::free) {}
|
||||
};
|
||||
|
||||
class PosixAligned64Allocator : public MemoryAllocator {
|
||||
public:
|
||||
PosixAligned64Allocator() : MemoryAllocator(posix_memalign, std::free, 64) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class StdAllocatorHIP {
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
StdAllocatorHIP() = default;
|
||||
|
||||
template <class U>
|
||||
constexpr StdAllocatorHIP(const StdAllocatorHIP<U>&) noexcept {}
|
||||
|
||||
[[nodiscard]] T* allocate(size_t n) {
|
||||
if (n > std::numeric_limits<size_t>::max() / sizeof(T)) {
|
||||
throw std::bad_array_new_length();
|
||||
}
|
||||
|
||||
T* p{nullptr};
|
||||
allocator_.allocate(reinterpret_cast<void**>(&p), n * sizeof(T));
|
||||
if (p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
void deallocate(T* p, [[maybe_unused]] size_t n) noexcept {
|
||||
allocator_.deallocate(p);
|
||||
}
|
||||
|
||||
private:
|
||||
HIPDefaultFinegrainedAllocator allocator_{};
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
bool operator==(const StdAllocatorHIP<T>&, const StdAllocatorHIP<U>&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool operator!=(const StdAllocatorHIP<T>&, const StdAllocatorHIP<U>&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_HIP_ALLOCATOR_HPP_
|
||||
@@ -0,0 +1,99 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "memory_allocator.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "../util.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
MemoryAllocator::MemoryAllocator(hipError_t (*hip_alloc_fn)(void**, size_t,
|
||||
unsigned),
|
||||
hipError_t (*hip_free_fn)(void*),
|
||||
unsigned flags)
|
||||
: _hip_alloc_with_flags(hip_alloc_fn),
|
||||
_hip_free(hip_free_fn),
|
||||
_flags(flags) {}
|
||||
|
||||
MemoryAllocator::MemoryAllocator(hipError_t (*hip_alloc_fn)(void**, size_t),
|
||||
hipError_t (*hip_free_fn)(void*))
|
||||
: _hip_alloc(hip_alloc_fn), _hip_free(hip_free_fn) {}
|
||||
|
||||
MemoryAllocator::MemoryAllocator(std::function<void*(size_t)> alloc_fn,
|
||||
std::function<void(void*)> free_fn)
|
||||
: _alloc(alloc_fn), _free(free_fn) {}
|
||||
|
||||
MemoryAllocator::MemoryAllocator(
|
||||
std::function<int(void**, size_t, size_t)> posix_align_fn,
|
||||
std::function<void(void*)> free_fn, size_t alignment)
|
||||
: _alloc_posix_memalign(posix_align_fn),
|
||||
_free(free_fn),
|
||||
_alignment(alignment) {}
|
||||
|
||||
void MemoryAllocator::allocate(void** void_ptr, size_t size) {
|
||||
assert(void_ptr);
|
||||
|
||||
if (_alloc) {
|
||||
*(reinterpret_cast<char**>(void_ptr)) =
|
||||
reinterpret_cast<char*>(_alloc(size));
|
||||
assert(*reinterpret_cast<char**>(void_ptr));
|
||||
return;
|
||||
}
|
||||
if (_alloc_posix_memalign) {
|
||||
assert(_alignment);
|
||||
_alloc_posix_memalign(void_ptr, _alignment, size);
|
||||
assert(*reinterpret_cast<char**>(void_ptr));
|
||||
return;
|
||||
}
|
||||
if (_hip_alloc) {
|
||||
CHECK_HIP(_hip_alloc(void_ptr, size));
|
||||
return;
|
||||
}
|
||||
if (_hip_alloc_with_flags) {
|
||||
CHECK_HIP(_hip_alloc_with_flags(void_ptr, size, _flags));
|
||||
return;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void MemoryAllocator::deallocate(void* ptr) {
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
if (_free) {
|
||||
_free(ptr);
|
||||
return;
|
||||
}
|
||||
if (_hip_free) {
|
||||
CHECK_HIP(_hip_free(ptr));
|
||||
return;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
bool MemoryAllocator::is_managed() { return _managed; }
|
||||
|
||||
} // namespace rocshmem
|
||||
@@ -0,0 +1,168 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_MEMORY_ALLOCATOR_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_MEMORY_ALLOCATOR_HPP_
|
||||
|
||||
/**
|
||||
* @file memory_allocator.hpp
|
||||
*
|
||||
* @brief Wraps allocators in a uniform interface
|
||||
*/
|
||||
|
||||
#include <hip/hip_runtime_api.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class MemoryAllocator {
|
||||
public:
|
||||
/**
|
||||
* @brief Required for default construction of other objects
|
||||
*
|
||||
* @note Not intended for direct usage.
|
||||
*/
|
||||
MemoryAllocator() = default;
|
||||
|
||||
/**
|
||||
* @brief Primary constructor
|
||||
*
|
||||
* @param[in] hip library allocation function
|
||||
* @param[in] hip library free function
|
||||
* @param[in] hip flags
|
||||
*
|
||||
* @note Finegrained flag is assumed by default
|
||||
*/
|
||||
MemoryAllocator(hipError_t (*hip_alloc_fn)(void**, size_t, unsigned),
|
||||
hipError_t (*hip_free_fn)(void*), unsigned flags);
|
||||
|
||||
/**
|
||||
* @brief Primary constructor
|
||||
*
|
||||
* @param[in] hip library allocation function
|
||||
* @param[in] hip library free function
|
||||
*/
|
||||
MemoryAllocator(hipError_t (*hip_alloc_fn)(void**, size_t),
|
||||
hipError_t (*hip_free_fn)(void*));
|
||||
|
||||
/**
|
||||
* @brief Primary constructor
|
||||
*
|
||||
* @param[in] an allocation function
|
||||
* @param[in] a free function
|
||||
*/
|
||||
MemoryAllocator(std::function<void*(size_t)> alloc_fn,
|
||||
std::function<void(void*)> free_fn);
|
||||
|
||||
/**
|
||||
* @brief Primary constructor
|
||||
*
|
||||
* @param[in] an allocation function
|
||||
* @param[in] a free function
|
||||
* @param[in] alignment for allocations
|
||||
*/
|
||||
MemoryAllocator(std::function<int(void**, size_t, size_t)> posix_align_fn,
|
||||
std::function<void(void*)> free_fn, size_t alignment);
|
||||
|
||||
/**
|
||||
* @brief Allocates memory
|
||||
*
|
||||
* @param[in, out] Address of raw pointer (&pointer_to_char)
|
||||
* @param[in] Size in bytes of memory allocation
|
||||
*/
|
||||
void allocate(void** ptr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Deallocates memory
|
||||
*
|
||||
* @param[in] Address of raw pointer (&pointer_to_char)
|
||||
*/
|
||||
void deallocate(void* ptr);
|
||||
|
||||
/**
|
||||
* @brief Returns is memory is managed
|
||||
*
|
||||
* @return returns whether this memory is managed
|
||||
*/
|
||||
bool is_managed();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief is this memory allocated using managed memory
|
||||
*/
|
||||
bool _managed{false};
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief a posix allocator function for memory aligned accesses
|
||||
*/
|
||||
std::function<int(void**, size_t, size_t)> _alloc_posix_memalign;
|
||||
|
||||
/**
|
||||
* @brief alignment for posix_memalign allocations
|
||||
*/
|
||||
size_t _alignment{0};
|
||||
|
||||
/**
|
||||
* @brief a standard allocator function
|
||||
*/
|
||||
std::function<void*(size_t)> _alloc{nullptr};
|
||||
|
||||
/**
|
||||
* @brief a standard free function
|
||||
*/
|
||||
std::function<void(void*)> _free{nullptr};
|
||||
|
||||
/**
|
||||
* @brief a hip-specific allocator function
|
||||
*/
|
||||
std::function<hipError_t(void**, size_t)> _hip_alloc{nullptr};
|
||||
|
||||
/**
|
||||
* @brief a hip-specific allocator function
|
||||
*/
|
||||
std::function<hipError_t(void**, size_t, unsigned)> _hip_alloc_with_flags{
|
||||
nullptr};
|
||||
|
||||
/**
|
||||
* @brief flags specified in hip_runtime_api.h
|
||||
*
|
||||
* Used as a runtime input parameter to the _hip_alloc_with_flags function.
|
||||
*/
|
||||
unsigned _flags{0x0};
|
||||
|
||||
/**
|
||||
* @brief a hip-specific free function
|
||||
*/
|
||||
std::function<hipError_t(void*)> _hip_free{nullptr};
|
||||
|
||||
/**
|
||||
* @brief a hip-specific return code
|
||||
*/
|
||||
hipError_t _hip_return_value{hipSuccess};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_MEMORY_ALLOCATOR_HPP_
|
||||
@@ -0,0 +1,83 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file notifier.hpp
|
||||
*
|
||||
* @brief Contains the notification memory space for threads to communicate
|
||||
* results with one another.
|
||||
*
|
||||
* Assume one thread does work on behalf of other threads (as a leader) and
|
||||
* that work needs to be communicated to the other threads as a result.
|
||||
* To expose the result, the threads need to share a memory space where the
|
||||
* result can be written. The leader thread writes the result out to this
|
||||
* memory space and all threads synchronize on it.
|
||||
*
|
||||
* This class allows the leader thread to notify other threads of the update.
|
||||
*/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_NOTIFIER_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_NOTIFIER_HPP_
|
||||
|
||||
#include "../device_proxy.hpp"
|
||||
#include "../util.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class Notifier {
|
||||
public:
|
||||
__device__ uint64_t read() { return value_; }
|
||||
|
||||
__device__ void write(uint64_t val) {
|
||||
if (is_thread_zero_in_block()) {
|
||||
value_ = val;
|
||||
}
|
||||
publish();
|
||||
}
|
||||
|
||||
__device__ void done() { __syncthreads(); }
|
||||
|
||||
private:
|
||||
__device__ void publish() {
|
||||
if (is_thread_zero_in_block()) {
|
||||
__threadfence();
|
||||
}
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
uint64_t value_{};
|
||||
};
|
||||
|
||||
template <typename ALLOCATOR>
|
||||
class NotifierProxy {
|
||||
using ProxyT = DeviceProxy<ALLOCATOR, Notifier, 1>;
|
||||
|
||||
public:
|
||||
__host__ __device__ Notifier* get() { return proxy_.get(); }
|
||||
|
||||
private:
|
||||
ProxyT proxy_{};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_NOTIFIER_HPP_
|
||||
@@ -0,0 +1,353 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_POW2_BINS_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_POW2_BINS_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
|
||||
#include "../constants.hpp"
|
||||
#include "bin.hpp"
|
||||
#include "binner.hpp"
|
||||
#include "shmem_allocator_strategy.hpp"
|
||||
|
||||
/**
|
||||
* @file pow2_bins.hpp
|
||||
*
|
||||
* @brief Contains an allocator strategy for the heap.
|
||||
*
|
||||
* This strategy returns memory chunks with power-of-two sizes.
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
template <typename AR_T, typename HM_T>
|
||||
class Pow2Bins : public ShmemAllocatorStrategy {
|
||||
/**
|
||||
* @brief Helper type for bins of address records
|
||||
*/
|
||||
using BIN_T = Bin<AR_T>;
|
||||
|
||||
/**
|
||||
* @brief Helper type for size to bin maps
|
||||
*/
|
||||
using BINS_T = std::map<size_t, BIN_T>;
|
||||
|
||||
/**
|
||||
* @brief Helper type for BINS_T iterator
|
||||
*/
|
||||
using BINS_IT_T = typename BINS_T::iterator;
|
||||
|
||||
/**
|
||||
* @brief Helper type for raw pointers to address record maps
|
||||
*/
|
||||
using PROFFERED_T = std::map<char*, AR_T>;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Required for default construction of other objects
|
||||
*
|
||||
* @note Not intended for direct usage.
|
||||
*/
|
||||
Pow2Bins() = default;
|
||||
|
||||
/**
|
||||
* @brief Primary constructor type
|
||||
*
|
||||
* @param[in] Raw pointer to heap memory type
|
||||
*/
|
||||
explicit Pow2Bins(HM_T* heap_mem)
|
||||
: binner_{&bins_, heap_mem->get_ptr(), heap_mem->get_size()} {
|
||||
binner_.assign_heap_to_bins();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from the heap
|
||||
*
|
||||
* @param[in, out] Address of raw pointer (&pointer_to_char)
|
||||
* @param[in] Size in bytes of memory allocation
|
||||
*/
|
||||
void alloc(char** ptr, size_t request_size) override {
|
||||
assert(ptr);
|
||||
*ptr = nullptr;
|
||||
|
||||
if (!request_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto do_request_using = [&](auto it) {
|
||||
if (it != bins_.end()) {
|
||||
AR_T record{retrieve_record_from_bin(it)};
|
||||
/*
|
||||
* Record retrieval may have generated INVALID record.
|
||||
* If INVALID, do not mark record as proffered.
|
||||
* Also notice, input pointer "ptr" may have nullptr value.
|
||||
*/
|
||||
if (record.get_address()) {
|
||||
emplace_in_proffered(record);
|
||||
}
|
||||
*ptr = record.get_address();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Try to find exact power-of-two matches.
|
||||
*/
|
||||
do_request_using(bins_.find(request_size));
|
||||
if (*ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Round up to the nearest power-of-two size.
|
||||
*/
|
||||
do_request_using(bins_.lower_bound(request_size));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from the heap
|
||||
*
|
||||
* @param[in, out] Address of raw pointer (&pointer_to_char)
|
||||
* @param[in] Size in bytes of memory allocation
|
||||
*
|
||||
* @note Not implemented
|
||||
*/
|
||||
__device__ void alloc([[maybe_unused]] char** ptr,
|
||||
[[maybe_unused]] size_t request_size) override {}
|
||||
|
||||
/**
|
||||
* @brief Frees memory from the heap
|
||||
*
|
||||
* Released memory is tracked by bookkeeping structures within this class.
|
||||
*
|
||||
* @param[in] Raw pointer to heap memory
|
||||
*
|
||||
* @note We do not attempt to combine records together into larger
|
||||
* even if it is possible to do so. This may eventually exhaust the
|
||||
* number of records in the larger bins.
|
||||
*/
|
||||
void free(char* ptr) override {
|
||||
auto record{retrieve_from_proffered(ptr)};
|
||||
emplace_record_in_bin(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Frees memory from the heap
|
||||
*
|
||||
* Released memory is tracked by bookkeeping structures within this class.
|
||||
*
|
||||
* @param[in] Raw pointer to heap memory
|
||||
*
|
||||
* @note Not implemented
|
||||
*/
|
||||
__device__ void free([[maybe_unused]] char* ptr) override {}
|
||||
|
||||
/**
|
||||
* @brief Sum of all proffered_ memory sizes
|
||||
*
|
||||
* @return memory size
|
||||
*/
|
||||
size_t amount_proffered() {
|
||||
size_t size{0};
|
||||
auto sum_sizes = [&size](const auto& pair) {
|
||||
auto [address, record] = pair;
|
||||
size += record.get_size();
|
||||
};
|
||||
std::for_each(proffered_.begin(), proffered_.end(), sum_sizes);
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Accessor for bins_ internal data structure
|
||||
*
|
||||
* @return BINS_T raw pointer
|
||||
*
|
||||
* @note Used by unit-test test fixture
|
||||
*/
|
||||
BINS_T* get_bins() { return &bins_; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Store address record in appropriate bin
|
||||
*
|
||||
* @param[in] An address record
|
||||
*/
|
||||
void emplace_record_in_bin(AR_T record) {
|
||||
auto record_size{record.get_size()};
|
||||
|
||||
auto bins_it = bins_.find(record_size);
|
||||
assert(bins_it != bins_.end());
|
||||
|
||||
auto& [IGNORE_BIN_SIZE, bin]{*bins_it};
|
||||
bin.put(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve address record from bin within a BINS_IT_T
|
||||
*
|
||||
* @param[in] a VALID FORWARD iterator containing a bin
|
||||
*
|
||||
* @return An address record
|
||||
*
|
||||
* @note May return an empty record indicating a retrieval failure.
|
||||
* The failure must be resolved somewhere else within the allocation
|
||||
* framework.
|
||||
*/
|
||||
AR_T retrieve_record_from_bin(BINS_IT_T it) {
|
||||
try_to_ensure_bin_has_records(it);
|
||||
|
||||
auto& [IGNORE, bin]{*it};
|
||||
|
||||
if (bin.empty()) {
|
||||
return AR_T{};
|
||||
}
|
||||
|
||||
return bin.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempt to accommodate a subsequent record request
|
||||
*
|
||||
* The bin under iterator may not (or may) contain records when
|
||||
* this method is invoked. This method tries to make at least one
|
||||
* record available.
|
||||
*
|
||||
* @param[in] a VALID FORWARD iterator containing a bin
|
||||
*
|
||||
* @note BINS_T container must be sorted in ascending bin size for
|
||||
* delegate method "split_larger_bin"
|
||||
*/
|
||||
void try_to_ensure_bin_has_records(BINS_IT_T it) {
|
||||
auto& [IGNORE, bin]{*it};
|
||||
|
||||
if (!bin.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
split_larger_bin(it);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Split records in next largest bin
|
||||
*
|
||||
* This method tries to create records within this bin by decomposing
|
||||
* records in other bins (with larger bin sizes).
|
||||
*
|
||||
* This method may be called recursively if records are unavailable
|
||||
* at each step until records are made available to the initial
|
||||
* bin.
|
||||
*
|
||||
* @param[in] a VALID FORWARD iterator containing a bin
|
||||
*
|
||||
* @note BINS_T container must be sorted in ascending bin size
|
||||
*/
|
||||
void split_larger_bin(BINS_IT_T it) {
|
||||
assert(it != bins_.end());
|
||||
|
||||
auto next{std::next(it)};
|
||||
if (next == bins_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& [IGNORE_NEXT, next_bin]{*next};
|
||||
if (next_bin.empty()) {
|
||||
split_larger_bin(next);
|
||||
}
|
||||
|
||||
if (next_bin.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto record{next_bin.get()};
|
||||
auto [smaller, larger]{record.split()};
|
||||
|
||||
auto& [IGNORE, bin]{*it};
|
||||
bin.put(larger);
|
||||
bin.put(smaller);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Store record in proffered_ data structure
|
||||
*
|
||||
* @param[in] An address record
|
||||
*/
|
||||
void emplace_in_proffered(AR_T record) {
|
||||
assert(record.get_address());
|
||||
proffered_[record.get_address()] = record;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve record from proffered_ data structure
|
||||
*
|
||||
* @param[in] raw memory pointer
|
||||
*
|
||||
* The memory pointer must match a pointer previously
|
||||
* handed to the user.
|
||||
*
|
||||
* @return An address record
|
||||
*/
|
||||
AR_T retrieve_from_proffered(char* ptr) {
|
||||
assert(ptr);
|
||||
|
||||
auto prof_it{proffered_.find(ptr)};
|
||||
assert(prof_it != proffered_.end());
|
||||
|
||||
auto [IGNORE_RECORD_ADDR, record]{*prof_it};
|
||||
proffered_.erase(prof_it);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Holds a SORTED set of bin objects
|
||||
*
|
||||
* The bin objects are sorted by ascending bin sizes. Each bin holds
|
||||
* address records with matching sizes. The bin sizes increase by
|
||||
* powers-of-two. There is a minimum bin size set by memory alignment
|
||||
* constraints.
|
||||
*/
|
||||
BINS_T bins_{};
|
||||
|
||||
/**
|
||||
* @brief Initializes the bins_ object
|
||||
*
|
||||
* The binner functions as a bins_ builder. The binner access data in
|
||||
* the heap memory to establish the number of bins and each bin's size.
|
||||
*
|
||||
* Additionally, binner_ will assign the heap memory to bins_.
|
||||
*/
|
||||
Binner<AR_T, BINS_T> binner_{};
|
||||
|
||||
/**
|
||||
* @brief Tracks all address records handed over to user.
|
||||
*
|
||||
* This member is required to track the sizes of memory allocations
|
||||
* since the user is not required to provide a size_t field back
|
||||
* through the "free" interface.
|
||||
*/
|
||||
PROFFERED_T proffered_{};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_POW2_BINS_HPP_
|
||||
@@ -0,0 +1,223 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_REMOTE_HEAP_INFO_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_REMOTE_HEAP_INFO_HPP_
|
||||
|
||||
#include <hip/hip_runtime_api.h>
|
||||
#include <mpi.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "hip_allocator.hpp"
|
||||
#include "window_info.hpp"
|
||||
|
||||
/**
|
||||
* @file remote_heap_info.hpp
|
||||
*
|
||||
* @brief Contains information about remote processing elements' heaps
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class CommunicatorMPI {
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
CommunicatorMPI() = default;
|
||||
|
||||
/**
|
||||
* @brief Primary constructor
|
||||
*/
|
||||
CommunicatorMPI(char* heap_base, size_t heap_size) {
|
||||
int initialized;
|
||||
MPI_Initialized(&initialized);
|
||||
if (!initialized) {
|
||||
int provided;
|
||||
MPI_Init_thread(nullptr, nullptr, MPI_THREAD_SINGLE, &provided);
|
||||
}
|
||||
MPI_Comm_rank(comm_, &my_pe_);
|
||||
MPI_Comm_size(comm_, &num_pes_);
|
||||
|
||||
heap_window_info_ = WindowInfo(comm_, heap_base, heap_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~CommunicatorMPI() {}
|
||||
|
||||
/**
|
||||
* @brief Returns my processing element ID
|
||||
*/
|
||||
int my_pe() { return my_pe_; }
|
||||
|
||||
/**
|
||||
* @brief Returns number of processing elements
|
||||
*/
|
||||
int num_pes() { return num_pes_; }
|
||||
|
||||
/**
|
||||
* @brief Performs MPI_Barrier
|
||||
*/
|
||||
void barrier() { MPI_Barrier(comm_); }
|
||||
|
||||
/**
|
||||
* @brief Performs MPI_Allgather on recvbuf
|
||||
*/
|
||||
void allgather(void* recvbuf) {
|
||||
MPI_Allgather(MPI_IN_PLACE, sizeof(void*), MPI_CHAR, recvbuf, sizeof(void*),
|
||||
MPI_CHAR, comm_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Accessor method for heap_window_info_
|
||||
*/
|
||||
WindowInfo* get_window_info() { return &heap_window_info_; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Identifier for this processing element
|
||||
*/
|
||||
MPI_Comm comm_{MPI_COMM_WORLD};
|
||||
|
||||
/**
|
||||
* @brief Identifier for this processing element
|
||||
*/
|
||||
int my_pe_{-1};
|
||||
|
||||
/**
|
||||
* @brief The total number of processing elements
|
||||
*/
|
||||
int num_pes_{-1};
|
||||
|
||||
/**
|
||||
* @brief MPI window on the symmetric GPU heap
|
||||
*/
|
||||
WindowInfo heap_window_info_{};
|
||||
};
|
||||
|
||||
template <typename COMMUNICATOR_T>
|
||||
class RemoteHeapInfo {
|
||||
/**
|
||||
* @brief Helper type for heap_bases_ member
|
||||
*/
|
||||
using HEAP_BASES_T = std::vector<char*, StdAllocatorHIP<char*>>;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Required for default construction of other objects
|
||||
*
|
||||
* @note Not intended for direct usage
|
||||
*/
|
||||
RemoteHeapInfo() = default;
|
||||
|
||||
/**
|
||||
* @brief Primary constructor
|
||||
*
|
||||
* @param[in] The identifier for this processing element
|
||||
* @param[in] The total number of processing elements
|
||||
*/
|
||||
RemoteHeapInfo(char* heap_ptr, size_t heap_size)
|
||||
: communicator_{heap_ptr, heap_size} {
|
||||
heap_bases_.resize(communicator_.num_pes());
|
||||
for (auto& base : heap_bases_) {
|
||||
base = nullptr;
|
||||
}
|
||||
heap_bases_[communicator_.my_pe()] = heap_ptr;
|
||||
communicator_.allgather(heap_bases_.data());
|
||||
|
||||
device_heap_bases_ = heap_bases_.data();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Invoke barrier on communicator
|
||||
*/
|
||||
void barrier() { communicator_.barrier(); }
|
||||
|
||||
/**
|
||||
* @brief Accessor for my processing element identifier
|
||||
*
|
||||
* @return My processing element identifier
|
||||
*/
|
||||
int my_pe() { return communicator_.my_pe(); }
|
||||
|
||||
/**
|
||||
* @brief Accessor for number of processing elements
|
||||
*
|
||||
* @return Number of processing elements
|
||||
*/
|
||||
int num_pes() { return communicator_.num_pes(); }
|
||||
|
||||
/**
|
||||
* @brief Accessor method for heap_window_info_
|
||||
*
|
||||
* @return Window info for Reverse Offload interface
|
||||
*/
|
||||
auto get_window_info() { return communicator_.get_window_info(); }
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap bases
|
||||
*
|
||||
* @return Vector containing the addresses of the symmetric heap bases
|
||||
*/
|
||||
__host__ const HEAP_BASES_T& get_heap_bases() { return heap_bases_; }
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap bases
|
||||
*
|
||||
* @return Vector containing the addresses of the symmetric heap bases
|
||||
*/
|
||||
__device__ auto get_heap_bases() { return device_heap_bases_; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Communicator implementation
|
||||
*/
|
||||
COMMUNICATOR_T communicator_{};
|
||||
|
||||
/**
|
||||
* @brief C-array of symmetric heap base pointers
|
||||
*
|
||||
* A vector of char* pointers corresponding to the heap_bases virtual
|
||||
* address for all processing element that we can communicate with.
|
||||
*
|
||||
* @note Used by __host__ code
|
||||
*/
|
||||
HEAP_BASES_T heap_bases_{};
|
||||
|
||||
/**
|
||||
* @brief C-array of symmetric heap base pointers
|
||||
*
|
||||
* A vector of char* pointers corresponding to the heap_bases virtual
|
||||
* address for all processing element that we can communicate with.
|
||||
*
|
||||
* @note Used by __device__ code
|
||||
*/
|
||||
char** device_heap_bases_{nullptr};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_REMOTE_HEAP_INFO_HPP_
|
||||
@@ -0,0 +1,90 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_SHMEM_ALLOCATOR_STRATEGY_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_SHMEM_ALLOCATOR_STRATEGY_HPP_
|
||||
|
||||
/**
|
||||
* @file shmem_allocator_strategy.hpp
|
||||
*
|
||||
* @brief Strategy design pattern for SHMEM symmetric heap allocator.
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class ShmemAllocatorStrategy {
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
ShmemAllocatorStrategy() = default;
|
||||
|
||||
/**
|
||||
* @brief Default destructor
|
||||
*/
|
||||
virtual ~ShmemAllocatorStrategy() = default;
|
||||
|
||||
/**
|
||||
* @brief Default copy construction
|
||||
*/
|
||||
ShmemAllocatorStrategy(const ShmemAllocatorStrategy& other) = default;
|
||||
|
||||
/**
|
||||
* @brief Disable copy assignment
|
||||
*/
|
||||
ShmemAllocatorStrategy& operator=(const ShmemAllocatorStrategy& other) =
|
||||
default;
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from the symmetric heap
|
||||
*
|
||||
* @param[in, out] Address of raw pointer (&pointer_to_char)
|
||||
* @param[in] Size in bytes of memory allocation
|
||||
*/
|
||||
virtual void alloc(char** ptr, size_t request_size) = 0;
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from the symmetric heap
|
||||
*
|
||||
* @param[in, out] Address of raw pointer (&pointer_to_char)
|
||||
* @param[in] Size in bytes of memory allocation
|
||||
*/
|
||||
__device__ virtual void alloc(char** ptr, size_t request_size) = 0;
|
||||
|
||||
/**
|
||||
* @brief Frees memory from the symmetric heap
|
||||
*
|
||||
* @param[in] Raw pointer to symmetric heap memory
|
||||
*/
|
||||
virtual void free(char* ptr) = 0;
|
||||
|
||||
/**
|
||||
* @brief Frees memory from the symmetric heap
|
||||
*
|
||||
* @param[in] Raw pointer to symmetric heap memory
|
||||
*/
|
||||
__device__ virtual void free(char* ptr) = 0;
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_SHMEM_ALLOCATOR_STRATEGY_HPP_
|
||||
@@ -0,0 +1,66 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "single_heap.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
SingleHeap::SingleHeap() {
|
||||
if (auto heap_size_cstr = getenv("ROC_SHMEM_HEAP_SIZE")) {
|
||||
std::stringstream sstream(heap_size_cstr);
|
||||
size_t heap_size;
|
||||
sstream >> heap_size;
|
||||
heap_mem_ = HEAP_T{heap_size};
|
||||
strat_ = STRAT_T{&heap_mem_};
|
||||
}
|
||||
}
|
||||
|
||||
void SingleHeap::malloc(void** ptr, size_t size) {
|
||||
strat_.alloc(reinterpret_cast<char**>(ptr), size);
|
||||
}
|
||||
|
||||
__device__ void SingleHeap::malloc(void** ptr, size_t size) {}
|
||||
|
||||
void SingleHeap::free(void* ptr) {
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
strat_.free(reinterpret_cast<char*>(ptr));
|
||||
}
|
||||
|
||||
__device__ void SingleHeap::free(void* ptr) {}
|
||||
|
||||
void* SingleHeap::realloc(void* ptr, size_t size) { return nullptr; }
|
||||
|
||||
void* SingleHeap::malign(size_t alignment, size_t size) { return nullptr; }
|
||||
|
||||
char* SingleHeap::get_base_ptr() { return heap_mem_.get_ptr(); }
|
||||
|
||||
size_t SingleHeap::get_size() { return heap_mem_.get_size(); }
|
||||
|
||||
size_t SingleHeap::get_used() { return strat_.amount_proffered(); }
|
||||
|
||||
size_t SingleHeap::get_avail() { return get_size() - get_used(); }
|
||||
|
||||
} // namespace rocshmem
|
||||
@@ -0,0 +1,162 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_SINGLE_HEAP_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_SINGLE_HEAP_HPP_
|
||||
|
||||
#include "address_record.hpp"
|
||||
#include "heap_memory.hpp"
|
||||
#include "heap_type.hpp"
|
||||
#include "pow2_bins.hpp"
|
||||
|
||||
/**
|
||||
* @file single_heap.hpp
|
||||
*
|
||||
* @brief Contains a single heap
|
||||
*
|
||||
* The single heap implements local processing element allocations. The
|
||||
* symmetric heap delegates allocations to this class.
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class SingleHeap {
|
||||
/**
|
||||
* @brief Helper type for address records
|
||||
*/
|
||||
using AR_T = AddressRecord;
|
||||
|
||||
/**
|
||||
* @brief Helper type for allocation strategy
|
||||
*/
|
||||
using STRAT_T = Pow2Bins<AR_T, HEAP_T>;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Primary constructor
|
||||
*/
|
||||
SingleHeap();
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from the heap
|
||||
*
|
||||
* @param[in,out] A pointer to memory handle
|
||||
* @param[in] Size in bytes of memory allocation
|
||||
*/
|
||||
void malloc(void** ptr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from the heap
|
||||
*
|
||||
* @param[in,out] A pointer to memory handle
|
||||
* @param[in] Size in bytes of memory allocation
|
||||
*
|
||||
* @note Not implemented
|
||||
*/
|
||||
__device__ void malloc(void** ptr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Frees memory from the heap
|
||||
*
|
||||
* @param[in] Raw pointer to heap memory
|
||||
*/
|
||||
void free(void* ptr);
|
||||
|
||||
/**
|
||||
* @brief Frees memory from the heap
|
||||
*
|
||||
* @param[in] Raw pointer to heap memory
|
||||
*
|
||||
* @note Not implemented
|
||||
*/
|
||||
__device__ void free(void* ptr);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param[in]
|
||||
* @param[in]
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
void* realloc(void* ptr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param[in]
|
||||
* @param[in]
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
void* malign(size_t alignment, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap base ptr
|
||||
*
|
||||
* @return Pointer to base of my heap
|
||||
*/
|
||||
char* get_base_ptr();
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap size
|
||||
*
|
||||
* @return Amount of bytes in heap
|
||||
*/
|
||||
size_t get_size();
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap usage
|
||||
*
|
||||
* @return Amount of used bytes in heap
|
||||
*/
|
||||
size_t get_used();
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap available
|
||||
*
|
||||
* @return Amount of available bytes in heap
|
||||
*/
|
||||
size_t get_avail();
|
||||
|
||||
/**
|
||||
* @brief Returns is the heap is allocated with managed memory
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
bool is_managed() { return heap_mem_.is_managed(); }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Heap memory object
|
||||
*/
|
||||
HEAP_T heap_mem_{};
|
||||
|
||||
/**
|
||||
* @brief Allocation strategy object
|
||||
*/
|
||||
STRAT_T strat_{&heap_mem_};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_SINGLE_HEAP_HPP_
|
||||
@@ -0,0 +1,113 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "slab_heap.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "../util.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
SlabHeap::SlabHeap() {
|
||||
if (auto slab_size_cstr = getenv("ROC_SHMEM_SLAB_SIZE")) {
|
||||
std::stringstream sstream(slab_size_cstr);
|
||||
size_t slab_size;
|
||||
sstream >> slab_size;
|
||||
heap_mem_ = HEAP_T{slab_size};
|
||||
strat_ = STRAT_T{&heap_mem_};
|
||||
}
|
||||
}
|
||||
|
||||
void SlabHeap::malloc(void** ptr, size_t size) {
|
||||
strat_.alloc(reinterpret_cast<char**>(ptr), size);
|
||||
}
|
||||
|
||||
__device__ void SlabHeap::malloc(void** ptr, size_t size) {
|
||||
/*
|
||||
* Grab the mutex from the proxy object which owns it.
|
||||
*/
|
||||
auto mutex{mutex_.get()};
|
||||
|
||||
/*
|
||||
* Take the ticketed lock.
|
||||
*
|
||||
* The lock is held jointly by all threads in the block.
|
||||
*/
|
||||
auto ticket{mutex->lock()};
|
||||
|
||||
/*
|
||||
* Perform allocation and verify it worked.
|
||||
*
|
||||
* Allocation should only be run by only one thread in the
|
||||
* strategy code.
|
||||
*/
|
||||
char** ptr_c{reinterpret_cast<char**>(ptr)};
|
||||
strat_.alloc(ptr_c, size);
|
||||
__threadfence();
|
||||
|
||||
/*
|
||||
* The notifier works with uint64_t for the address broadcasts
|
||||
* between threads (as type erasure for the pointer arithmetic).
|
||||
*/
|
||||
uint64_t ptr_deref_u64{reinterpret_cast<uint64_t>(*ptr)};
|
||||
|
||||
/*
|
||||
* Notify other threads in block about the allocation result.
|
||||
*/
|
||||
auto notifier{notifier_.get()};
|
||||
notifier->write(ptr_deref_u64);
|
||||
uint64_t notification_u64{notifier->read()};
|
||||
notifier->done();
|
||||
|
||||
/*
|
||||
* Write to the ptr parameter (to return it back up the call stack).
|
||||
*/
|
||||
char* read_value_c{reinterpret_cast<char*>(notification_u64)};
|
||||
*ptr_c = read_value_c;
|
||||
|
||||
/*
|
||||
* Release the lock with our ticket number.
|
||||
*/
|
||||
mutex->unlock(ticket);
|
||||
}
|
||||
|
||||
__host__ __device__ void SlabHeap::free(void* ptr) {
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
strat_.free(reinterpret_cast<char*>(ptr));
|
||||
}
|
||||
|
||||
void* SlabHeap::realloc(void* ptr, size_t size) { return nullptr; }
|
||||
|
||||
void* SlabHeap::malign(size_t alignment, size_t size) { return nullptr; }
|
||||
|
||||
char* SlabHeap::get_base_ptr() { return heap_mem_.get_ptr(); }
|
||||
|
||||
size_t SlabHeap::get_size() { return heap_mem_.get_size(); }
|
||||
|
||||
size_t SlabHeap::get_used() { return strat_.current() - get_base_ptr(); }
|
||||
|
||||
size_t SlabHeap::get_avail() { return get_size() - get_used(); }
|
||||
|
||||
} // namespace rocshmem
|
||||
@@ -0,0 +1,185 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_SLAB_HEAP_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_SLAB_HEAP_HPP_
|
||||
|
||||
#include "dev_mono_linear.hpp"
|
||||
#include "heap_memory.hpp"
|
||||
#include "heap_type.hpp"
|
||||
#include "notifier.hpp"
|
||||
#include "../sync/abql_block_mutex.hpp"
|
||||
|
||||
/**
|
||||
* @file slab_heap.hpp
|
||||
*
|
||||
* @brief Contains a heap used to allocate library objects
|
||||
*
|
||||
* The slab heap is used internally by the library
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class SlabHeap {
|
||||
/**
|
||||
* @brief Helper type for allocation strategy
|
||||
*/
|
||||
using STRAT_T = DevMonoLinear<HEAP_T>;
|
||||
|
||||
/**
|
||||
* @brief Helper type for notifier
|
||||
*/
|
||||
using NOTIFIER_PROXY_T = NotifierProxy<HIPAllocator>;
|
||||
|
||||
/**
|
||||
* @brief Helper type for notifier
|
||||
*/
|
||||
using MUTEX_PROXY_T = ABQLBlockMutexProxy<HIPAllocator>;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Primary constructor
|
||||
*/
|
||||
SlabHeap();
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from the heap
|
||||
*
|
||||
* @param[in,out] A pointer to memory handle
|
||||
* @param[in] Size in bytes of memory allocation
|
||||
*/
|
||||
void malloc(void** ptr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from the heap
|
||||
*
|
||||
* @param[in,out] A pointer to memory handle
|
||||
* @param[in] Size in bytes of memory allocation
|
||||
*/
|
||||
__device__ void malloc(void** ptr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Frees memory from the heap
|
||||
*
|
||||
* @param[in] Raw pointer to heap memory
|
||||
*/
|
||||
__host__ __device__ void free(void* ptr);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param[in]
|
||||
* @param[in]
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
void* realloc(void* ptr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param[in]
|
||||
* @param[in]
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
void* malign(size_t alignment, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap base ptr
|
||||
*
|
||||
* @return Pointer to base of my heap
|
||||
*/
|
||||
char* get_base_ptr();
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap size
|
||||
*
|
||||
* @return Amount of bytes in heap
|
||||
*/
|
||||
size_t get_size();
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap usage
|
||||
*
|
||||
* @return Amount of used bytes in heap
|
||||
*/
|
||||
size_t get_used();
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap available
|
||||
*
|
||||
* @return Amount of available bytes in heap
|
||||
*/
|
||||
size_t get_avail();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Heap memory object
|
||||
*/
|
||||
HEAP_T heap_mem_{};
|
||||
|
||||
/**
|
||||
* @brief Allocation strategy object
|
||||
*/
|
||||
STRAT_T strat_{&heap_mem_};
|
||||
|
||||
/**
|
||||
* @brief Notifier proxy to share information between threads.
|
||||
*
|
||||
* Need this object to share allocation information between the
|
||||
* leader thread (that does allocation) and the follower threads
|
||||
* (who need the allocation address).
|
||||
*/
|
||||
NOTIFIER_PROXY_T notifier_{};
|
||||
|
||||
/**
|
||||
* @brief Mutex to access the heap mutator methods.
|
||||
*/
|
||||
MUTEX_PROXY_T mutex_;
|
||||
};
|
||||
|
||||
template <typename ALLOCATOR>
|
||||
class SlabHeapProxy {
|
||||
using ProxyT = DeviceProxy<ALLOCATOR, SlabHeap, 1>;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Placement new the memory which is allocated by proxy_
|
||||
*/
|
||||
SlabHeapProxy() { new (proxy_.get()) SlabHeap(); }
|
||||
|
||||
/*
|
||||
* Since placement new is called in the constructor, then
|
||||
* delete must be called manually.
|
||||
*/
|
||||
~SlabHeapProxy() { proxy_.get()->~SlabHeap(); }
|
||||
|
||||
__host__ __device__ SlabHeap* get() { return proxy_.get(); }
|
||||
|
||||
private:
|
||||
ProxyT proxy_{};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_SLAB_HEAP_HPP_
|
||||
@@ -0,0 +1,129 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_SYMMETRIC_HEAP_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_SYMMETRIC_HEAP_HPP_
|
||||
|
||||
/**
|
||||
* @file symmetric_heap.hpp
|
||||
*
|
||||
* @brief Contains a symmetric heap
|
||||
*
|
||||
* Every processing element allocates a symmetric heap. (For details on
|
||||
* the symmetric heap, refer to the OpenSHMEM specification.)
|
||||
*
|
||||
* The symmetric heap is allocated using fine-grained memory to allow
|
||||
* both host access and device access to the memory space.
|
||||
*
|
||||
* The symmetric heaps are visible to network by registering them as
|
||||
* InfiniBand memory regions. Every memory region has a remote key
|
||||
* which needs to be shared across the network (to access the memory
|
||||
* region).
|
||||
*/
|
||||
|
||||
#include <hip/hip_runtime_api.h>
|
||||
|
||||
#include "remote_heap_info.hpp"
|
||||
#include "single_heap.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class SymmetricHeap {
|
||||
/**
|
||||
* @brief Helper type for RemoteHeapInfo with MPI
|
||||
*/
|
||||
using RemoteHeapInfoType = RemoteHeapInfo<CommunicatorMPI>;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Allocates heap memory and returns ptr to caller
|
||||
*
|
||||
* @param[in,out] A pointer to memory handle
|
||||
* @param[in] Number of bytes of requested
|
||||
*/
|
||||
void malloc(void** ptr, size_t size) { single_heap_.malloc(ptr, size); }
|
||||
|
||||
/**
|
||||
* @brief Frees previously allocated network visible memory
|
||||
*
|
||||
* @param[in] Handle of previously allocated memory
|
||||
*/
|
||||
void free(void* ptr) { single_heap_.free(ptr); }
|
||||
|
||||
/**
|
||||
* @brief Accessor for local heap base
|
||||
*
|
||||
* @return Base address of the local symmetric heap
|
||||
*/
|
||||
__host__ char* get_local_heap_base() { return single_heap_.get_base_ptr(); }
|
||||
|
||||
/**
|
||||
* @brief Accessor method for heap size
|
||||
*/
|
||||
auto get_size() { return single_heap_.get_size(); }
|
||||
|
||||
/**
|
||||
* @brief Accessor method for heap_window_info_
|
||||
*/
|
||||
auto get_window_info() { return remote_heap_info_.get_window_info(); }
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap bases
|
||||
*
|
||||
* @return Vector containing the addresses of the symmetric heap bases
|
||||
*/
|
||||
__host__ const auto& get_heap_bases() {
|
||||
return remote_heap_info_.get_heap_bases();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Accessor for heap bases
|
||||
*
|
||||
* @return Vector containing the addresses of the symmetric heap bases
|
||||
*/
|
||||
__device__ auto get_heap_bases() {
|
||||
return remote_heap_info_.get_heap_bases();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns is the heap is allocated with managed memory
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
bool is_managed() { return single_heap_.is_managed(); }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Processing element's implementation of heap
|
||||
*/
|
||||
SingleHeap single_heap_{};
|
||||
|
||||
/**
|
||||
* @brief Implementation of remote heaps
|
||||
*/
|
||||
RemoteHeapInfoType remote_heap_info_{single_heap_.get_base_ptr(),
|
||||
single_heap_.get_size()};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_SYMMETRIC_HEAP_HPP_
|
||||
@@ -0,0 +1,194 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LIBRARY_SRC_MEMORY_WINDOW_INFO_HPP_
|
||||
#define LIBRARY_SRC_MEMORY_WINDOW_INFO_HPP_
|
||||
|
||||
#include <mpi.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* @file window_info.hpp
|
||||
*
|
||||
* @brief Contains information about symmetric heaps' windows
|
||||
*/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class WindowInfo {
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
WindowInfo() = default;
|
||||
|
||||
/**
|
||||
* @brief Primary constructor
|
||||
*/
|
||||
WindowInfo(MPI_Comm comm, void* start, size_t size)
|
||||
: comm_{comm},
|
||||
win_start_{start},
|
||||
win_end_{reinterpret_cast<char*>(start) + size} {
|
||||
up_win_ = std::unique_ptr<MPI_Win>(new MPI_Win);
|
||||
MPI_Win_create(win_start_, size, 1, MPI_INFO_NULL, comm_, up_win_.get());
|
||||
MPI_Win_lock_all(MPI_MODE_NOCHECK, *up_win_.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~WindowInfo() {
|
||||
if (up_win_) {
|
||||
MPI_Win_unlock_all(*up_win_.get());
|
||||
MPI_Win_free(up_win_.get());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*
|
||||
* @note Disabled due to up_win_
|
||||
*/
|
||||
WindowInfo(WindowInfo& other) = delete; // NOLINT
|
||||
|
||||
/**
|
||||
* @brief Const copy constructor
|
||||
*
|
||||
* @note Disabled due to up_win_
|
||||
*/
|
||||
WindowInfo(const WindowInfo& other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Copy assignment
|
||||
*
|
||||
* @note Disabled due to up_win_
|
||||
*/
|
||||
WindowInfo& operator=(WindowInfo other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
*/
|
||||
WindowInfo(WindowInfo&& other) = default;
|
||||
|
||||
/**
|
||||
* @brief Move assignment
|
||||
*/
|
||||
WindowInfo& operator=(WindowInfo&& other) = default;
|
||||
|
||||
/**
|
||||
* @brief Accessor for object in up_win_
|
||||
*
|
||||
* @return MPI_Win object
|
||||
*/
|
||||
MPI_Win get_win() const { return *up_win_.get(); }
|
||||
|
||||
/**
|
||||
* @brief Accessor for win_start_
|
||||
*
|
||||
* @return Raw start pointer
|
||||
*/
|
||||
void* get_start() const { return win_start_; }
|
||||
|
||||
/**
|
||||
* @brief Accessor for win_end_
|
||||
*
|
||||
* @return Raw end pointer
|
||||
*/
|
||||
void* get_end() const { return win_end_; }
|
||||
|
||||
/**
|
||||
* @brief Setter for object in up_win_
|
||||
*
|
||||
* @param[in] An MPI Window object
|
||||
*/
|
||||
void set_win(MPI_Win win) { *up_win_.get() = win; }
|
||||
|
||||
/**
|
||||
* @brief Setter for win_start_
|
||||
*
|
||||
* @param[in] Start raw pointer
|
||||
*/
|
||||
void set_start(void* start) { win_start_ = start; }
|
||||
|
||||
/**
|
||||
* @brief Setter for win_end_
|
||||
*
|
||||
* @param[in] End raw pointer
|
||||
*/
|
||||
void set_end(void* end) { win_end_ = end; }
|
||||
|
||||
/**
|
||||
* @brief Get offset between address and start of window
|
||||
*
|
||||
* @param[in] Address in raw pointer format
|
||||
*
|
||||
* @return Difference between dest and window start
|
||||
*/
|
||||
MPI_Aint get_offset(const void* dest) {
|
||||
assert(reinterpret_cast<char*>(const_cast<void*>(dest)) >=
|
||||
reinterpret_cast<char*>(win_start_));
|
||||
assert(reinterpret_cast<char*>(const_cast<void*>(dest)) >=
|
||||
reinterpret_cast<char*>(win_start_));
|
||||
assert(reinterpret_cast<char*>(const_cast<void*>(dest)) <
|
||||
reinterpret_cast<char*>(win_end_));
|
||||
|
||||
MPI_Aint dest_disp;
|
||||
MPI_Get_address(dest, &dest_disp);
|
||||
MPI_Aint start_disp;
|
||||
MPI_Get_address(win_start_, &start_disp);
|
||||
|
||||
return MPI_Aint_diff(dest_disp, start_disp);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief MPI Communicator
|
||||
*/
|
||||
MPI_Comm comm_{MPI_COMM_WORLD};
|
||||
|
||||
/**
|
||||
* @brief Owning pointer to MPI_Win
|
||||
*
|
||||
* The pointer is used to track which object is responsible for
|
||||
* releasing window resources during class destruction.
|
||||
*
|
||||
* This becomes an issue if objects of this class are move constructed
|
||||
* or move assigned.
|
||||
*/
|
||||
std::unique_ptr<MPI_Win> up_win_{nullptr};
|
||||
|
||||
/**
|
||||
* @brief Raw pointer marking the start of window
|
||||
*/
|
||||
void* win_start_{nullptr};
|
||||
|
||||
/**
|
||||
* @brief Raw pointer marking the end of window
|
||||
*/
|
||||
void* win_end_{nullptr};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // LIBRARY_SRC_MEMORY_WINDOW_INFO_HPP_
|
||||
Αναφορά σε νέο ζήτημα
Block a user