12 #ifndef MFEM_MEM_MANAGER_HPP
13 #define MFEM_MEM_MANAGER_HPP
18 #include <type_traits>
120 template <
typename T>
183 explicit Memory(T *ptr,
int size,
bool own) {
Wrap(ptr, size, own); }
194 {
Wrap(ptr, size, mt, own); }
257 inline void New(
int size);
272 inline void Wrap(T *ptr,
int size,
bool own);
311 inline operator T*();
318 inline operator const T*()
const;
333 template <
typename U>
334 inline explicit operator U*();
344 template <
typename U>
345 inline explicit operator const U*()
const;
405 inline void CopyToHost(T *dest,
int size)
const;
427 template <
typename T>
friend class Memory;
439 static bool Exists() {
return exists; }
442 #ifdef MFEM_USE_UMPIRE
443 static const char *h_umpire_name;
444 static const char *d_umpire_name;
452 static void *New_(
void *h_tmp,
size_t bytes,
MemoryType mt,
unsigned &flags);
456 static void *Register_(
void *ptr,
void *h_ptr,
size_t bytes,
MemoryType mt,
457 bool own,
bool alias,
unsigned &flags);
460 static void Alias_(
void *base_h_ptr,
size_t offset,
size_t bytes,
461 unsigned base_flags,
unsigned &flags);
468 static bool MemoryClassCheck_(
MemoryClass mc,
void *h_ptr,
469 MemoryType h_mt,
size_t bytes,
unsigned flags);
477 size_t bytes,
unsigned &flags);
480 size_t bytes,
unsigned &flags);
483 size_t bytes,
unsigned &flags);
485 static void SyncAlias_(
const void *base_h_ptr,
void *alias_h_ptr,
486 size_t alias_bytes,
unsigned base_flags,
487 unsigned &alias_flags);
491 static MemoryType GetDeviceMemoryType_(
void *h_ptr);
494 static MemoryType GetHostMemoryType_(
void *h_ptr);
497 static void CheckHostMemoryType_(
MemoryType h_mt,
void *h_ptr);
501 static void Copy_(
void *dest_h_ptr,
const void *src_h_ptr,
size_t bytes,
502 unsigned src_flags,
unsigned &dest_flags);
506 static void CopyToHost_(
void *dest_h_ptr,
const void *src_h_ptr,
507 size_t bytes,
unsigned src_flags);
511 static void CopyFromHost_(
void *dest_h_ptr,
const void *src_h_ptr,
512 size_t bytes,
unsigned &dest_flags);
515 static bool IsKnown_(
const void *h_ptr);
519 static bool IsAlias_(
const void *h_ptr);
522 static int CompareHostAndDevice_(
void *h_ptr,
size_t size,
unsigned flags);
530 void InsertDevice(
void *d_ptr,
void *h_ptr,
size_t bytes,
534 void InsertAlias(
const void *base_ptr,
void *alias_ptr,
535 const size_t bytes,
const bool base_is_alias);
538 void Erase(
void *h_ptr,
bool free_dev_ptr =
true);
541 void EraseAlias(
void *alias_ptr);
545 void *GetDevicePtr(
const void *h_ptr,
size_t bytes,
bool copy_data);
549 void *GetAliasDevicePtr(
const void *alias_ptr,
size_t bytes,
bool copy_data);
553 void *GetHostPtr(
const void *d_ptr,
size_t bytes,
bool copy_data);
557 void *GetAliasHostPtr(
const void *alias_ptr,
size_t bytes,
bool copy_data);
570 #ifdef MFEM_USE_UMPIRE
581 bool IsKnown(
const void *h_ptr) {
return IsKnown_(h_ptr); }
584 bool IsAlias(
const void *h_ptr) {
return IsAlias_(h_ptr); }
604 template <
typename T>
608 h_mt = MemoryManager::host_mem_type;
613 template <
typename T>
622 template <
typename T>
626 flags = OWNS_HOST | VALID_HOST;
627 h_mt = MemoryManager::host_mem_type;
629 (T*)MemoryManager::New_(
nullptr, size*
sizeof(T), h_mt, flags);
632 template <
typename T>
636 const size_t bytes = size*
sizeof(T);
638 if (mt_host) { flags = OWNS_HOST | VALID_HOST; }
639 h_mt =
IsHostMemory(mt) ? mt : MemoryManager::GetDualMemoryType_(mt);
641 h_ptr = (mt_host) ? h_tmp: (T*)MemoryManager::New_(h_tmp, bytes, mt, flags);
644 template <
typename T>
649 const size_t bytes = size*
sizeof(T);
650 flags = (own ? OWNS_HOST : 0) | VALID_HOST;
651 h_mt = MemoryManager::host_mem_type;
653 if (own && MemoryManager::Exists())
654 { MFEM_VERIFY(h_mt == MemoryManager::GetHostMemoryType_(h_ptr),
""); }
657 { MemoryManager::Register_(ptr, ptr, bytes, h_mt, own,
false, flags); }
660 template <
typename T>
671 flags = (own ? OWNS_HOST : 0) | VALID_HOST;
677 h_mt = MemoryManager::GetDualMemoryType_(mt);
681 h_ptr = (T*)MemoryManager::Register_(ptr, h_ptr, size*
sizeof(T), mt,
685 template <
typename T>
690 h_ptr = base.
h_ptr + offset;
691 if (!(base.
flags & REGISTERED))
692 { flags = (base.
flags | ALIAS) & ~(OWNS_HOST | OWNS_DEVICE); }
695 const size_t s_bytes = size*
sizeof(T);
696 const size_t o_bytes = offset*
sizeof(T);
697 MemoryManager::Alias_(base.
h_ptr, o_bytes, s_bytes, base.
flags, flags);
701 template <
typename T>
704 const bool registered = flags & REGISTERED;
706 const bool std_delete = !registered && mt_host;
711 if (flags & OWNS_HOST) {
delete [] h_ptr; }
715 template <
typename T>
718 MFEM_ASSERT((flags & VALID_HOST) && !(flags & VALID_DEVICE),
719 "invalid host pointer access");
723 template <
typename T>
726 MFEM_ASSERT((flags & VALID_HOST),
"invalid host pointer access");
730 template <
typename T>
733 MFEM_ASSERT(Empty() ||
734 ((flags & VALID_HOST) &&
735 (std::is_const<T>::value || !(flags & VALID_DEVICE))),
736 "invalid host pointer access");
740 template <
typename T>
743 MFEM_ASSERT(Empty() || (flags & VALID_HOST),
"invalid host pointer access");
747 template <
typename T>
template <
typename U>
750 MFEM_ASSERT(Empty() ||
751 ((flags & VALID_HOST) &&
752 (std::is_const<U>::value || !(flags & VALID_DEVICE))),
753 "invalid host pointer access");
754 return reinterpret_cast<U*
>(h_ptr);
757 template <
typename T>
template <
typename U>
760 MFEM_ASSERT(Empty() || (flags & VALID_HOST),
"invalid host pointer access");
761 return reinterpret_cast<U*
>(h_ptr);
764 template <
typename T>
767 const size_t bytes = size *
sizeof(T);
768 if (!(flags & REGISTERED))
771 MemoryManager::Register_(h_ptr,
nullptr, capacity*
sizeof(T), h_mt,
772 flags & OWNS_HOST, flags & ALIAS, flags);
774 return (T*)MemoryManager::ReadWrite_(h_ptr, h_mt, mc, bytes, flags);
777 template <
typename T>
780 const size_t bytes = size *
sizeof(T);
781 if (!(flags & REGISTERED))
784 MemoryManager::Register_(h_ptr,
nullptr, capacity*
sizeof(T), h_mt,
785 flags & OWNS_HOST, flags & ALIAS, flags);
787 return (
const T*)MemoryManager::Read_(h_ptr, h_mt, mc, bytes, flags);
790 template <
typename T>
793 const size_t bytes = size *
sizeof(T);
794 if (!(flags & REGISTERED))
797 MemoryManager::Register_(h_ptr,
nullptr, capacity*
sizeof(T), h_mt,
798 flags & OWNS_HOST, flags & ALIAS, flags);
800 return (T*)MemoryManager::Write_(h_ptr, h_mt, mc, bytes, flags);
803 template <
typename T>
806 if (!(flags & REGISTERED) && (other.
flags & REGISTERED))
808 MFEM_ASSERT(h_ptr == other.
h_ptr &&
809 (flags & ALIAS) == (other.
flags & ALIAS),
811 flags = (flags | REGISTERED) & ~(OWNS_DEVICE | OWNS_INTERNAL);
813 flags = (flags & ~(VALID_HOST | VALID_DEVICE)) |
814 (other.
flags & (VALID_HOST | VALID_DEVICE));
817 template <
typename T>
821 MFEM_ASSERT(!(flags & REGISTERED) || (base.
flags & REGISTERED),
822 "invalid base state");
823 if (!(base.
flags & REGISTERED)) {
return; }
824 MemoryManager::SyncAlias_(base.
h_ptr, h_ptr, alias_size*
sizeof(T),
828 template <
typename T>
831 if (!(flags & VALID_DEVICE)) {
return h_mt; }
832 return MemoryManager::GetDeviceMemoryType_(h_ptr);
835 template <
typename T>
838 if (!(flags & REGISTERED) && !(src.
flags & REGISTERED))
840 if (h_ptr != src.
h_ptr && size != 0)
842 MFEM_ASSERT(h_ptr + size <= src || src + size <= h_ptr,
844 std::memcpy(h_ptr, src, size*
sizeof(T));
850 MemoryManager::Copy_(h_ptr, src.
h_ptr, size*
sizeof(T), src.
flags, flags);
854 template <
typename T>
857 if (!(flags & REGISTERED))
859 if (h_ptr != src && size != 0)
861 MFEM_ASSERT(h_ptr + size <= src || src + size <= h_ptr,
863 std::memcpy(h_ptr, src, size*
sizeof(T));
869 MemoryManager::CopyFromHost_(h_ptr, src, size*
sizeof(T), flags);
873 template <
typename T>
876 if (!(flags & REGISTERED))
878 if (h_ptr != dest && size != 0)
880 MFEM_ASSERT(h_ptr + size <= dest || dest + size <= h_ptr,
882 std::memcpy(dest, h_ptr, size*
sizeof(T));
887 MemoryManager::CopyToHost_(dest, h_ptr, size*
sizeof(T), flags);
897 template <
typename T>
903 template <
typename T>
906 if (!(flags & VALID_HOST) || !(flags & VALID_DEVICE)) {
return 0; }
907 return MemoryManager::CompareHostAndDevice_(h_ptr, size*
sizeof(T), flags);
916 #endif // MFEM_MEM_MANAGER_HPP
MemoryType h_mt
Host memory type.
Host memory; aligned at 64 bytes.
bool IsHostMemory(MemoryType mt)
Return true if the given memory type is in MemoryClass::HOST.
~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().
Device memory; using CUDA or HIP *Malloc and *Free.
const char * GetUmpireAllocatorHostName()
void PrintFlags() const
Print the internal flags.
Device memory; using Umpire.
const char * MemoryTypeName[MemoryTypeSize]
Memory type names, used during Device:: configuration.
void Delete()
Delete the owned pointers. The Memory is not reset by this method, i.e. it will, generally, not be Empty() after this call.
const char * GetUmpireAllocatorDeviceName()
Memory(T *ptr, int size, MemoryType mt, bool own)
Wrap an externally allocated pointer, ptr, of the given MemoryType.
static MemoryType GetHostMemoryType()
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...
void SetDevicePtrOwner(bool own) const
Set/clear the ownership flag for the device pointer. Ownership indicates whether the pointer will be ...
Host memory; allocated from a "host-debug" pool.
T * Write(MemoryClass mc, int size)
Get write-only access to the memory with the given MemoryClass.
void Configure(const MemoryType h_mt, const MemoryType d_mt)
Memory(int size)
Allocate host memory for size entries.
void UseDevice(bool use_dev) const
Set the internal device flag.
void CopyFrom(const Memory &src, int size)
Copy size entries from src to *this.
int PrintAliases(std::ostream &out=mfem::out)
Number of host and device memory types.
int Capacity() const
Return the size of the allocated memory.
int CompareHostAndDevice(int size) const
If both the host and the device data are valid, compare their contents.
Memory(int size, MemoryType mt)
Allocate memory for size entries with the given MemoryType mt.
MemoryType GetMemoryType() const
Return a MemoryType that is currently valid. If both the host and the device pointers are currently v...
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.
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...
void SetUmpireAllocatorNames(const char *h_name, const char *d_name)
Set the host and device UMpire allocator names.
void CopyFromHost(const T *src, int size)
Copy size entries from the host pointer src to *this.
void CopyTo(Memory &dest, int size) const
Copy size entries from *this to dest.
The memory manager class.
constexpr int DeviceMemoryType
constexpr int HostMemoryType
static MemoryType GetDeviceMemoryType()
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.
void Destroy()
Free all the device memories.
int PrintPtrs(std::ostream &out=mfem::out)
The host pointer will be deleted by Delete()
bool OwnsHostPtr() const
Return true if the host pointer is owned. Ownership indicates whether the pointer will be deleted by ...
void RegisterCheck(void *h_ptr)
Check if the host pointer has been registered in the memory manager.
constexpr int MemoryTypeSize
Static casts to 'int' and sizes of some useful memory types.
Memory & operator=(const Memory &orig)=default
Copy-assignment operator: default.
void Reset()
Reset the memory to be empty, ensuring that Delete() will be a no-op.
void ClearOwnerFlags() const
Clear the ownership flags for the host and device pointers, as well as any internal data allocated by...
void Init()
Initialize the memory manager.
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 Sync(const Memory &other) const
Copy the host/device pointer validity flags from other to *this.
bool IsKnown(const void *h_ptr)
Return true if the pointer is known by the memory manager.
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)
MemoryManager mm
The (single) global memory manager object.
T * h_ptr
Pointer to host memory. Not owned.
int capacity
Size of the allocated memory.
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...
bool Empty() const
Return true if the Memory object is empty, see Reset().
T * ReadWrite(MemoryClass mc, int size)
Get read-write access to the memory with the given MemoryClass.
MemoryType GetMemoryType(MemoryClass mc)
Return a suitable MemoryType for a given MemoryClass.
void CopyToHost(T *dest, int size) const
Copy size entries from *this to the host pointer dest.
Class used by MFEM to store pointers to host and/or device memory.
Memory()
Default constructor: no initialization.
bool OwnsDevicePtr() const
Return true if the device pointer is owned. Ownership indicates whether the pointer will be deleted b...
bool UseDevice() const
Read 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...
Host memory; using Umpire.
T & operator[](int idx)
Array subscript operator for host memory.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
MemoryClass operator*(MemoryClass mc1, MemoryClass mc2)
Return a suitable MemoryClass from a pair of MemoryClasses.
const T * Read(MemoryClass mc, int size) const
Get read-only access to the memory with the given MemoryClass.
MemoryClass
Memory classes identify sets of memory types.
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().