12 #ifndef MFEM_MEM_MANAGER_HPP 13 #define MFEM_MEM_MANAGER_HPP 18 #include <type_traits> 21 #include <HYPRE_config.h> 159 template <
typename T>
223 if (
this == &orig) {
return *
this; }
250 explicit Memory(T *ptr,
int size,
bool own) {
Wrap(ptr, size, own); }
261 {
Wrap(ptr, size, mt, own); }
324 inline void New(
int size);
354 inline void Wrap(T *ptr,
int size,
bool own);
391 bool valid_host =
false,
bool valid_device =
true);
436 inline operator T*();
443 inline operator const T*()
const;
458 template <
typename U>
459 inline explicit operator U*();
469 template <
typename U>
470 inline explicit operator const U*()
const;
542 inline void CopyToHost(T *dest,
int size)
const;
556 static constexpr std::size_t def_align_bytes_()
559 return alignof(max_align_t);
561 static constexpr std::size_t def_align_bytes = def_align_bytes_();
562 static constexpr std::size_t new_align_bytes =
563 alignof(T) > def_align_bytes ?
alignof(T) : def_align_bytes;
565 template <std::
size_t align_bytes,
bool dummy = true>
struct Alloc
567 #if __cplusplus < 201703L 568 static inline T *
New(std::size_t)
571 MFEM_ASSERT(
false,
"overaligned type cannot use MemoryType::HOST");
575 static inline T *
New(std::size_t size) {
return new T[size]; }
579 #if __cplusplus < 201703L 580 template<
bool dummy>
struct Alloc<def_align_bytes,dummy>
582 static inline T *
New(std::size_t size) {
return new T[size]; }
587 static inline T *NewHOST(std::size_t size)
589 return Alloc<new_align_bytes>::New(size);
604 template <
typename T>
friend class Memory;
616 static bool Exists() {
return exists; }
627 static bool configured;
630 #ifdef MFEM_USE_UMPIRE 631 static const char * h_umpire_name;
632 static const char * d_umpire_name;
633 static const char * d_umpire_2_name;
641 static void *New_(
void *h_tmp,
size_t bytes,
MemoryType mt,
unsigned &
flags);
648 static void *Register_(
void *ptr,
void *
h_ptr,
size_t bytes,
MemoryType mt,
649 bool own,
bool alias,
unsigned &
flags);
652 static void Register2_(
void *
h_ptr,
void *d_ptr,
size_t bytes,
654 bool own,
bool alias,
unsigned &
flags,
655 unsigned valid_flags);
658 static void Alias_(
void *base_h_ptr,
size_t offset,
size_t bytes,
659 unsigned base_flags,
unsigned &
flags);
661 static void SetDeviceMemoryType_(
void *
h_ptr,
unsigned flags,
668 static void DeleteDevice_(
void *
h_ptr,
unsigned &
flags);
677 size_t bytes,
unsigned &
flags);
680 size_t bytes,
unsigned &
flags);
683 size_t bytes,
unsigned &
flags);
685 static void SyncAlias_(
const void *base_h_ptr,
void *alias_h_ptr,
686 size_t alias_bytes,
unsigned base_flags,
687 unsigned &alias_flags);
701 static void Copy_(
void *dest_h_ptr,
const void *src_h_ptr,
size_t bytes,
702 unsigned src_flags,
unsigned &dest_flags);
706 static void CopyToHost_(
void *dest_h_ptr,
const void *src_h_ptr,
707 size_t bytes,
unsigned src_flags);
711 static void CopyFromHost_(
void *dest_h_ptr,
const void *src_h_ptr,
712 size_t bytes,
unsigned &dest_flags);
715 static bool IsKnown_(
const void *
h_ptr);
719 static bool IsAlias_(
const void *
h_ptr);
722 static int CompareHostAndDevice_(
void *
h_ptr,
size_t size,
unsigned flags);
731 void InsertDevice(
void *d_ptr,
void *
h_ptr,
size_t bytes,
735 void InsertAlias(
const void *base_ptr,
void *alias_ptr,
736 const size_t bytes,
const bool base_is_alias);
739 void Erase(
void *
h_ptr,
bool free_dev_ptr =
true);
742 void EraseDevice(
void *
h_ptr);
745 void EraseAlias(
void *alias_ptr);
749 void *GetDevicePtr(
const void *
h_ptr,
size_t bytes,
bool copy_data);
753 void *GetAliasDevicePtr(
const void *alias_ptr,
size_t bytes,
bool copy_data);
757 void *GetHostPtr(
const void *d_ptr,
size_t bytes,
bool copy_data);
761 void *GetAliasHostPtr(
const void *alias_ptr,
size_t bytes,
bool copy_data);
790 {
return dual_map[(int)mt]; }
809 #ifdef MFEM_USE_UMPIRE 835 void RegisterCheck(
void *
h_ptr);
848 #ifdef MFEM_USE_ENZYME 851 MemoryManager::Delete_(mem, MT,
flags);
853 __attribute__((used))
854 inline static void* __enzyme_allocation_like1[4] = {(
void*)
static_cast<void*(*)(
void*,
size_t,
MemoryType,
unsigned&)
>(MemoryManager::New_),
855 (
void*)1, (
void*)
"-1,2,3", (
void*)myfree
857 __attribute__((used))
858 inline static void* __enzyme_allocation_like2[4] = {(
void*)
static_cast<void*(*)(
void*,
size_t,
MemoryType,
MemoryType,
unsigned,
unsigned&)
>(MemoryManager::New_),
859 (
void*)1, (
void*)
"-1,2,4", (
void*)MemoryManager::Delete_
861 __attribute__((used))
862 inline static void* __enzyme_function_like[2] = {(
void*)MemoryManager::Delete_, (
void*)
"free"};
869 template <
typename T>
878 template <
typename T>
887 template <
typename T>
894 (T*)MemoryManager::New_(
nullptr, size*
sizeof(T),
h_mt,
flags);
897 template <
typename T>
901 const size_t bytes = size*
sizeof(T);
906 h_ptr = (mt_host) ? h_tmp : (T*)MemoryManager::New_(h_tmp, bytes, mt,
flags);
909 template <
typename T>
913 const size_t bytes = size*
sizeof(T);
914 this->h_mt = host_mt;
916 h_ptr = (T*)MemoryManager::New_(h_tmp, bytes, host_mt, device_mt,
920 template <
typename T>
928 if (own && MemoryManager::Exists())
931 MFEM_VERIFY(
h_mt == h_ptr_mt,
932 "h_mt = " << (
int)
h_mt <<
", h_ptr_mt = " << (
int)h_ptr_mt);
937 const size_t bytes = size*
sizeof(T);
938 MemoryManager::Register_(ptr, ptr, bytes,
h_mt, own,
false,
flags);
942 template <
typename T>
963 h_ptr = (T*)MemoryManager::Register_(ptr,
h_ptr, size*
sizeof(T), mt,
967 template <
typename T>
969 bool own,
bool valid_host,
bool valid_device)
976 MFEM_ASSERT(valid_host || valid_device,
"");
977 const size_t bytes = size*
sizeof(T);
979 MemoryManager::Register2_(
h_ptr, d_ptr, bytes,
h_mt, d_mt,
984 template <
typename T>
987 MFEM_ASSERT(0 <= offset,
"invalid offset = " << offset);
988 MFEM_ASSERT(0 <= size,
"invalid size = " << size);
989 MFEM_ASSERT(offset + size <= base.
capacity,
990 "invalid offset + size = " << offset + size
991 <<
" > base capacity = " << base.
capacity);
1005 MemoryManager::Exists()
1010 MemoryManager::Register_(base.
h_ptr,
nullptr, base.
capacity*
sizeof(T),
1022 const size_t s_bytes = size*
sizeof(T);
1023 const size_t o_bytes = offset*
sizeof(T);
1024 MemoryManager::Alias_(base.
h_ptr, o_bytes, s_bytes, base.
flags,
flags);
1027 template <
typename T>
1036 MemoryManager::SetDeviceMemoryType_(
h_ptr,
flags, d_mt);
1039 template <
typename T>
1044 const bool std_delete = !registered && mt_host;
1058 template <
typename T>
1064 MemoryManager::DeleteDevice_((
void*)
h_ptr,
flags);
1068 template <
typename T>
1072 "invalid host pointer access");
1076 template <
typename T>
1083 template <
typename T>
1086 MFEM_ASSERT(
Empty() ||
1089 "invalid host pointer access");
1093 template <
typename T>
1100 template <
typename T>
template <
typename U>
1103 MFEM_ASSERT(
Empty() ||
1106 "invalid host pointer access");
1107 return reinterpret_cast<U*
>(
h_ptr);
1110 template <
typename T>
template <
typename U>
1114 return reinterpret_cast<U*
>(
h_ptr);
1117 template <
typename T>
1120 const size_t bytes = size *
sizeof(T);
1127 return (T*)MemoryManager::ReadWrite_(
h_ptr,
h_mt, mc, bytes,
flags);
1130 template <
typename T>
1133 const size_t bytes = size *
sizeof(T);
1140 return (
const T*)MemoryManager::Read_(
h_ptr,
h_mt, mc, bytes,
flags);
1143 template <
typename T>
1146 const size_t bytes = size *
sizeof(T);
1156 template <
typename T>
1170 template <
typename T>
1175 "invalid base state");
1177 MemoryManager::SyncAlias_(base.
h_ptr,
h_ptr, alias_size*
sizeof(T),
1181 template <
typename T>
1188 template <
typename T>
1195 template <
typename T>
1201 template <
typename T>
1207 template <
typename T>
1217 std::memcpy(
h_ptr, src, size*
sizeof(T));
1227 template <
typename T>
1230 MFEM_VERIFY(
capacity>=size,
"Incorrect size");
1233 if (
h_ptr != src && size != 0)
1235 MFEM_ASSERT(
h_ptr + size <= src || src + size <=
h_ptr,
1237 std::memcpy(
h_ptr, src, size*
sizeof(T));
1243 MemoryManager::CopyFromHost_(
h_ptr, src, size*
sizeof(T),
flags);
1247 template <
typename T>
1250 MFEM_VERIFY(
capacity>=size,
"Incorrect size");
1254 template <
typename T>
1257 MFEM_VERIFY(
capacity>=size,
"Incorrect size");
1260 if (
h_ptr != dest && size != 0)
1262 MFEM_ASSERT(
h_ptr + size <= dest || dest + size <=
h_ptr,
1264 std::memcpy(dest,
h_ptr, size*
sizeof(T));
1269 MemoryManager::CopyToHost_(dest,
h_ptr, size*
sizeof(T),
flags);
1279 template <
typename T>
1285 template <
typename T>
1289 return MemoryManager::CompareHostAndDevice_(
h_ptr, size*
sizeof(T),
flags);
1298 #endif // MFEM_MEM_MANAGER_HPP MemoryType h_mt
Host memory type.
const T * Read(MemoryClass mc, int size) const
Get read-only access to the memory with the given MemoryClass.
Host memory; aligned at 64 bytes.
bool IsHostMemory(MemoryType mt)
Return true if the given memory type is in MemoryClass::HOST.
bool DeviceIsValid() const
Return true if device pointer is valid.
~Memory()=default
Destructor: default.
friend void MemoryPrintFlags(unsigned flags)
Print the state of a Memory object based on its internal flags. Useful in a debugger. See also Memory<T>::PrintFlags().
int CompareHostAndDevice(int size) const
If both the host and the device data are valid, compare their contents.
Device memory; using CUDA or HIP *Malloc and *Free.
static const char * GetUmpireHostAllocatorName()
Get the host Umpire allocator name used with MemoryType::HOST_UMPIRE.
void Delete()
Delete the owned pointers and reset the Memory object.
MemoryType GetHostMemoryType() const
Return the host MemoryType of the Memory object.
Memory(T *ptr, int size, MemoryType mt, bool own)
Wrap an externally allocated pointer, ptr, of the given MemoryType.
static MemoryType GetHostMemoryType()
static void myfree(void *mem, MemoryType MT, unsigned &flags)
Host memory; allocated from a "host-debug" pool.
MemoryManager mm
The (single) global memory manager object.
T * Write(MemoryClass mc, int size)
Get write-only access to the memory with the given MemoryClass.
Memory(int size)
Allocate host memory for size entries.
Host memory: pinned (page-locked)
void CopyFrom(const Memory &src, int size)
Copy size entries from src to *this.
Memory & operator=(Memory &&orig)
Number of host and device memory types.
bool HostIsValid() const
Return true if host pointer is valid.
Memory(int size, MemoryType mt)
Allocate memory for size entries with the given MemoryType mt.
unsigned flags
Bit flags defined from the FlagMask enum.
bool IsAlias(const void *h_ptr)
Return true if the pointer is known by the memory manager as an alias.
class if defined(__alignas_is_defined) alignas(double) RowNode
bool MemoryClassContainsType(MemoryClass mc, MemoryType mt)
Return true iff the MemoryType mt is contained in the MemoryClass mc.
Host memory; aligned at 32 bytes.
void Wrap(T *ptr, int size, bool own)
Wrap an externally allocated host pointer, ptr with the current host memory type returned by MemoryMa...
const char * MemoryTypeName[MemoryTypeSize]
Memory type names, used during Device:: configuration.
static MemoryType GetDualMemoryType(MemoryType mt)
Return the dual MemoryType of the given one, mt.
void SetDevicePtrOwner(bool own) const
Set/clear the ownership flag for the device pointer. Ownership indicates whether the pointer will be ...
void CopyFromHost(const T *src, int size)
Copy size entries from the host pointer src to *this.
bool Empty() const
Return true if the Memory object is empty, see Reset().
constexpr int DeviceMemoryType
static const char * GetUmpireDeviceAllocatorName()
Get the device Umpire allocator name used with MemoryType::DEVICE_UMPIRE.
void Sync(const Memory &other) const
Copy the host/device pointer validity flags from other to *this.
constexpr int HostMemoryType
static MemoryType GetDeviceMemoryType()
void SyncAlias(const Memory &base, int alias_size) const
Update the alias Memory *this to match the memory location (all valid locations) of its base Memory...
Memory(const Memory &base, int offset, int size)
Alias constructor. Create a Memory object that points inside the Memory object base.
Ownership flag for internal Memory data.
The host pointer will be deleted by Delete()
constexpr int MemoryTypeSize
Static casts to 'int' and sizes of some useful memory types.
Memory & operator=(const Memory &orig)=default
Copy-assignment operator: default.
int Capacity() const
Return the size of the allocated memory.
bool OwnsDevicePtr() const
Return true if the device pointer is owned. Ownership indicates whether the pointer will be deleted b...
void Reset()
Reset the memory to be empty, ensuring that Delete() will be a no-op.
void CopyToHost(T *dest, int size) const
Copy size entries from *this to the host pointer dest.
static const char * GetUmpireDevice2AllocatorName()
Get the device Umpire allocator name used with MemoryType::DEVICE_UMPIRE_2.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
MemoryType
Memory types supported by MFEM.
void SetHostPtrOwner(bool own) const
Set/clear the ownership flag for the host pointer. Ownership indicates whether the pointer will be de...
void SetDeviceMemoryType(MemoryType d_mt)
Set the device MemoryType to be used by the Memory object.
bool IsKnown(const void *h_ptr)
Return true if the pointer is known by the memory manager.
void DeleteDevice(bool copy_to_host=true)
Delete the device pointer, if owned. If copy_to_host is true and the data is valid only on device...
A class to initialize the size of a Tensor.
constexpr int HostMemoryTypeSize
void MakeAlias(const Memory &base, int offset, int size)
Create a memory object that points inside the memory object base.
bool IsDeviceMemory(MemoryType mt)
Return true if the given memory type is in MemoryClass::DEVICE.
static void SetUmpireDevice2AllocatorName(const char *d_name)
Set the device Umpire allocator name used with MemoryType::DEVICE_UMPIRE_2.
T * h_ptr
Pointer to host memory. Not owned.
int capacity
Size of the allocated memory.
Memory(int size, MemoryType h_mt, MemoryType d_mt)
Allocate memory for size entries with the given host MemoryType h_mt and device MemoryType d_mt...
Host memory; using new[] and delete[].
void New(int size)
Allocate host memory for size entries with the current host memory type returned by MemoryManager::Ge...
void PrintFlags() const
Print the internal flags.
MemoryType GetDeviceMemoryType() const
Return the device MemoryType of the Memory object. If the device MemoryType is not set...
void ClearOwnerFlags() const
Clear the ownership flags for the host and device pointers, as well as any internal data allocated by...
T * ReadWrite(MemoryClass mc, int size)
Get read-write access to the memory with the given MemoryClass.
friend class MemoryManager
MemoryType GetMemoryType(MemoryClass mc)
Return a suitable MemoryType for a given MemoryClass.
Class used by MFEM to store pointers to host and/or device memory.
static void SetUmpireHostAllocatorName(const char *h_name)
Set the host Umpire allocator name used with MemoryType::HOST_UMPIRE.
bool OwnsHostPtr() const
Return true if the host pointer is owned. Ownership indicates whether the pointer will be deleted by ...
void CopyTo(Memory &dest, int size) const
Copy size entries from *this to dest.
bool UseDevice() const
Read the internal device flag.
void UseDevice(bool use_dev) const
Set the internal device flag.
constexpr int DeviceMemoryTypeSize
Memory(T *ptr, int size, bool own)
Wrap an externally allocated host pointer, ptr with the current host memory type returned by MemoryMa...
T & operator[](int idx)
Array subscript operator for host memory.
MemoryClass operator*(MemoryClass mc1, MemoryClass mc2)
Return a suitable MemoryClass from a pair of MemoryClasses.
static void SetUmpireDeviceAllocatorName(const char *d_name)
Set the device Umpire allocator name used with MemoryType::DEVICE_UMPIRE.
MemoryClass
Memory classes identify sets of memory types.
MemoryType GetMemoryType() const
Return a MemoryType that is currently valid. If both the host and the device pointers are currently v...