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);
430 inline operator T*();
437 inline operator const T*()
const;
452 template <
typename U>
453 inline explicit operator U*();
463 template <
typename U>
464 inline explicit operator const U*()
const;
536 inline void CopyToHost(T *dest,
int size)
const;
550 static constexpr std::size_t def_align_bytes_()
553 return alignof(max_align_t);
555 static constexpr std::size_t def_align_bytes = def_align_bytes_();
556 static constexpr std::size_t new_align_bytes =
557 alignof(T) > def_align_bytes ?
alignof(T) : def_align_bytes;
559 template <std::
size_t align_bytes,
bool dummy = true>
struct Alloc
561 #if __cplusplus < 201703L 562 static inline T *
New(std::size_t)
565 MFEM_ASSERT(
false,
"overaligned type cannot use MemoryType::HOST");
569 static inline T *
New(std::size_t size) {
return new T[size]; }
573 #if __cplusplus < 201703L 574 template<
bool dummy>
struct Alloc<def_align_bytes,dummy>
576 static inline T *
New(std::size_t size) {
return new T[size]; }
581 static inline T *NewHOST(std::size_t size)
583 return Alloc<new_align_bytes>::New(size);
598 template <
typename T>
friend class Memory;
610 static bool Exists() {
return exists; }
621 static bool configured;
624 #ifdef MFEM_USE_UMPIRE 625 static const char * h_umpire_name;
626 static const char * d_umpire_name;
627 static const char * d_umpire_2_name;
635 static void *New_(
void *h_tmp,
size_t bytes,
MemoryType mt,
unsigned &
flags);
642 static void *Register_(
void *ptr,
void *
h_ptr,
size_t bytes,
MemoryType mt,
643 bool own,
bool alias,
unsigned &
flags);
646 static void Register2_(
void *
h_ptr,
void *d_ptr,
size_t bytes,
648 bool own,
bool alias,
unsigned &
flags);
651 static void Alias_(
void *base_h_ptr,
size_t offset,
size_t bytes,
652 unsigned base_flags,
unsigned &
flags);
654 static void SetDeviceMemoryType_(
void *
h_ptr,
unsigned flags,
661 static void DeleteDevice_(
void *
h_ptr,
unsigned &
flags);
670 size_t bytes,
unsigned &
flags);
673 size_t bytes,
unsigned &
flags);
676 size_t bytes,
unsigned &
flags);
678 static void SyncAlias_(
const void *base_h_ptr,
void *alias_h_ptr,
679 size_t alias_bytes,
unsigned base_flags,
680 unsigned &alias_flags);
694 static void Copy_(
void *dest_h_ptr,
const void *src_h_ptr,
size_t bytes,
695 unsigned src_flags,
unsigned &dest_flags);
699 static void CopyToHost_(
void *dest_h_ptr,
const void *src_h_ptr,
700 size_t bytes,
unsigned src_flags);
704 static void CopyFromHost_(
void *dest_h_ptr,
const void *src_h_ptr,
705 size_t bytes,
unsigned &dest_flags);
708 static bool IsKnown_(
const void *
h_ptr);
712 static bool IsAlias_(
const void *
h_ptr);
715 static int CompareHostAndDevice_(
void *
h_ptr,
size_t size,
unsigned flags);
724 void InsertDevice(
void *d_ptr,
void *
h_ptr,
size_t bytes,
728 void InsertAlias(
const void *base_ptr,
void *alias_ptr,
729 const size_t bytes,
const bool base_is_alias);
732 void Erase(
void *
h_ptr,
bool free_dev_ptr =
true);
735 void EraseDevice(
void *
h_ptr);
738 void EraseAlias(
void *alias_ptr);
742 void *GetDevicePtr(
const void *
h_ptr,
size_t bytes,
bool copy_data);
746 void *GetAliasDevicePtr(
const void *alias_ptr,
size_t bytes,
bool copy_data);
750 void *GetHostPtr(
const void *d_ptr,
size_t bytes,
bool copy_data);
754 void *GetAliasHostPtr(
const void *alias_ptr,
size_t bytes,
bool copy_data);
783 {
return dual_map[(int)mt]; }
802 #ifdef MFEM_USE_UMPIRE 828 void RegisterCheck(
void *
h_ptr);
841 #ifdef MFEM_USE_ENZYME 844 MemoryManager::Delete_(mem, MT,
flags);
846 __attribute__((used))
847 inline static void* __enzyme_allocation_like1[4] = {(
void*)
static_cast<void*(*)(
void*,
size_t,
MemoryType,
unsigned&)
>(MemoryManager::New_),
848 (
void*)1, (
void*)
"-1,2,3", (
void*)myfree
850 __attribute__((used))
851 inline static void* __enzyme_allocation_like2[4] = {(
void*)
static_cast<void*(*)(
void*,
size_t,
MemoryType,
MemoryType,
unsigned,
unsigned&)
>(MemoryManager::New_),
852 (
void*)1, (
void*)
"-1,2,4", (
void*)MemoryManager::Delete_
854 __attribute__((used))
855 inline static void* __enzyme_function_like[2] = {(
void*)MemoryManager::Delete_, (
void*)
"free"};
862 template <
typename T>
871 template <
typename T>
880 template <
typename T>
887 (T*)MemoryManager::New_(
nullptr, size*
sizeof(T),
h_mt,
flags);
890 template <
typename T>
894 const size_t bytes = size*
sizeof(T);
899 h_ptr = (mt_host) ? h_tmp : (T*)MemoryManager::New_(h_tmp, bytes, mt,
flags);
902 template <
typename T>
906 const size_t bytes = size*
sizeof(T);
907 this->h_mt = host_mt;
909 h_ptr = (T*)MemoryManager::New_(h_tmp, bytes, host_mt, device_mt,
913 template <
typename T>
921 if (own && MemoryManager::Exists())
924 MFEM_VERIFY(
h_mt == h_ptr_mt,
925 "h_mt = " << (
int)
h_mt <<
", h_ptr_mt = " << (
int)h_ptr_mt);
930 const size_t bytes = size*
sizeof(T);
931 MemoryManager::Register_(ptr, ptr, bytes,
h_mt, own,
false,
flags);
935 template <
typename T>
956 h_ptr = (T*)MemoryManager::Register_(ptr,
h_ptr, size*
sizeof(T), mt,
960 template <
typename T>
968 const size_t bytes = size*
sizeof(T);
970 MemoryManager::Register2_(
h_ptr, d_ptr, bytes,
h_mt, d_mt,
974 template <
typename T>
977 MFEM_ASSERT(0 <= offset,
"invalid offset = " << offset);
978 MFEM_ASSERT(0 <= size,
"invalid size = " << size);
979 MFEM_ASSERT(offset + size <= base.
capacity,
980 "invalid offset + size = " << offset + size
981 <<
" > base capacity = " << base.
capacity);
995 MemoryManager::Exists()
1000 MemoryManager::Register_(base.
h_ptr,
nullptr, base.
capacity*
sizeof(T),
1012 const size_t s_bytes = size*
sizeof(T);
1013 const size_t o_bytes = offset*
sizeof(T);
1014 MemoryManager::Alias_(base.
h_ptr, o_bytes, s_bytes, base.
flags,
flags);
1017 template <
typename T>
1026 MemoryManager::SetDeviceMemoryType_(
h_ptr,
flags, d_mt);
1029 template <
typename T>
1034 const bool std_delete = !registered && mt_host;
1048 template <
typename T>
1054 MemoryManager::DeleteDevice_((
void*)
h_ptr,
flags);
1058 template <
typename T>
1062 "invalid host pointer access");
1066 template <
typename T>
1073 template <
typename T>
1076 MFEM_ASSERT(
Empty() ||
1079 "invalid host pointer access");
1083 template <
typename T>
1090 template <
typename T>
template <
typename U>
1093 MFEM_ASSERT(
Empty() ||
1096 "invalid host pointer access");
1097 return reinterpret_cast<U*
>(
h_ptr);
1100 template <
typename T>
template <
typename U>
1104 return reinterpret_cast<U*
>(
h_ptr);
1107 template <
typename T>
1110 const size_t bytes = size *
sizeof(T);
1117 return (T*)MemoryManager::ReadWrite_(
h_ptr,
h_mt, mc, bytes,
flags);
1120 template <
typename T>
1123 const size_t bytes = size *
sizeof(T);
1130 return (
const T*)MemoryManager::Read_(
h_ptr,
h_mt, mc, bytes,
flags);
1133 template <
typename T>
1136 const size_t bytes = size *
sizeof(T);
1146 template <
typename T>
1160 template <
typename T>
1165 "invalid base state");
1167 MemoryManager::SyncAlias_(base.
h_ptr,
h_ptr, alias_size*
sizeof(T),
1171 template <
typename T>
1178 template <
typename T>
1185 template <
typename T>
1191 template <
typename T>
1197 template <
typename T>
1207 std::memcpy(
h_ptr, src, size*
sizeof(T));
1217 template <
typename T>
1220 MFEM_VERIFY(
capacity>=size,
"Incorrect size");
1223 if (
h_ptr != src && size != 0)
1225 MFEM_ASSERT(
h_ptr + size <= src || src + size <=
h_ptr,
1227 std::memcpy(
h_ptr, src, size*
sizeof(T));
1233 MemoryManager::CopyFromHost_(
h_ptr, src, size*
sizeof(T),
flags);
1237 template <
typename T>
1240 MFEM_VERIFY(
capacity>=size,
"Incorrect size");
1244 template <
typename T>
1247 MFEM_VERIFY(
capacity>=size,
"Incorrect size");
1250 if (
h_ptr != dest && size != 0)
1252 MFEM_ASSERT(
h_ptr + size <= dest || dest + size <=
h_ptr,
1254 std::memcpy(dest,
h_ptr, size*
sizeof(T));
1259 MemoryManager::CopyToHost_(dest,
h_ptr, size*
sizeof(T),
flags);
1269 template <
typename T>
1275 template <
typename T>
1279 return MemoryManager::CompareHostAndDevice_(
h_ptr, size*
sizeof(T),
flags);
1288 #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...