17 #include <unordered_map>
28 #define mfem_memalign(p,a,s) posix_memalign(p,a,s)
29 #define mfem_aligned_free free
31 #define mfem_memalign(p,a,s) (((*(p))=_aligned_malloc((s),(a))),*(p)?0:errno)
32 #define mfem_aligned_free _aligned_free
35 #ifdef MFEM_USE_UMPIRE
36 #include "umpire/Umpire.hpp"
39 #if defined(MFEM_USE_CUDA) && !defined(UMPIRE_ENABLE_CUDA)
40 #error "CUDA is not enabled in Umpire!"
43 #if defined(MFEM_USE_HIP) && !defined(UMPIRE_ENABLE_HIP)
44 #error "HIP is not enabled in Umpire!"
46 #endif // MFEM_USE_UMPIRE
64 MFEM_VERIFY(
false,
"");
85 MFEM_ABORT(
"invalid MemoryClass");
94 "d_mt = " << (
int)d_mt);
120 MFEM_VERIFY(sync,
"");
138 return std::max(mc1, mc2);
165 mutable bool h_rw, d_rw;
167 h_ptr(p), d_ptr(nullptr), bytes(b), h_mt(h), d_mt(d),
168 h_rw(true), d_rw(true) { }
183 typedef std::unordered_map<const void*, Memory> MemoryMap;
184 typedef std::unordered_map<const void*, Alias> AliasMap;
194 static internal::Maps *maps;
200 class HostMemorySpace
203 virtual ~HostMemorySpace() { }
204 virtual void Alloc(
void **ptr,
size_t bytes) { *ptr = std::malloc(bytes); }
205 virtual void Dealloc(
void *ptr) { std::free(ptr); }
206 virtual void Protect(
const Memory&,
size_t) { }
207 virtual void Unprotect(
const Memory&,
size_t) { }
208 virtual void AliasProtect(
const void*,
size_t) { }
209 virtual void AliasUnprotect(
const void*,
size_t) { }
213 class DeviceMemorySpace
216 virtual ~DeviceMemorySpace() { }
217 virtual void Alloc(Memory &base) { base.d_ptr = std::malloc(base.bytes); }
218 virtual void Dealloc(Memory &base) { std::free(base.d_ptr); }
219 virtual void Protect(
const Memory&) { }
220 virtual void Unprotect(
const Memory&) { }
221 virtual void AliasProtect(
const void*,
size_t) { }
222 virtual void AliasUnprotect(
const void*,
size_t) { }
223 virtual void *HtoD(
void *dst,
const void *src,
size_t bytes)
224 {
return std::memcpy(dst, src, bytes); }
225 virtual void *DtoD(
void *dst,
const void *src,
size_t bytes)
226 {
return std::memcpy(dst, src, bytes); }
227 virtual void *DtoH(
void *dst,
const void *src,
size_t bytes)
228 {
return std::memcpy(dst, src, bytes); }
232 class StdHostMemorySpace :
public HostMemorySpace { };
235 struct NoHostMemorySpace :
public HostMemorySpace
237 void Alloc(
void**,
const size_t) {
mfem_error(
"! Host Alloc error"); }
241 class Aligned32HostMemorySpace :
public HostMemorySpace
244 Aligned32HostMemorySpace(): HostMemorySpace() { }
245 void Alloc(
void **ptr,
size_t bytes)
246 {
if (mfem_memalign(ptr, 32, bytes) != 0) { throw ::std::bad_alloc(); } }
247 void Dealloc(
void *ptr) { mfem_aligned_free(ptr); }
251 class Aligned64HostMemorySpace :
public HostMemorySpace
254 Aligned64HostMemorySpace(): HostMemorySpace() { }
255 void Alloc(
void **ptr,
size_t bytes)
256 {
if (mfem_memalign(ptr, 64, bytes) != 0) { throw ::std::bad_alloc(); } }
257 void Dealloc(
void *ptr) { mfem_aligned_free(ptr); }
261 static uintptr_t pagesize = 0;
262 static uintptr_t pagemask = 0;
265 inline const void *MmuAddrR(
const void *ptr)
267 const uintptr_t addr = (uintptr_t) ptr;
268 return (addr & pagemask) ? (
void*) ((addr + pagesize) & ~pagemask) : ptr;
272 inline const void *MmuAddrP(
const void *ptr)
274 const uintptr_t addr = (uintptr_t) ptr;
275 return (
void*) (addr & ~pagemask);
279 inline uintptr_t MmuLengthR(
const void *ptr,
const size_t bytes)
282 const uintptr_t
a = (uintptr_t) ptr;
283 const uintptr_t A = (uintptr_t) MmuAddrR(ptr);
284 MFEM_ASSERT(a <= A,
"");
285 const uintptr_t
b = a + bytes;
286 const uintptr_t B = b & ~pagemask;
287 MFEM_ASSERT(B <= b,
"");
288 const uintptr_t length = B > A ? B - A : 0;
289 MFEM_ASSERT(length % pagesize == 0,
"");
294 inline uintptr_t MmuLengthP(
const void *ptr,
const size_t bytes)
297 const uintptr_t a = (uintptr_t) ptr;
298 const uintptr_t A = (uintptr_t) MmuAddrP(ptr);
299 MFEM_ASSERT(A <= a,
"");
300 const uintptr_t
b = a + bytes;
301 const uintptr_t B = b & pagemask ? (b + pagesize) & ~pagemask : b;
302 MFEM_ASSERT(b <= B,
"");
303 MFEM_ASSERT(B >= A,
"");
304 const uintptr_t length = B - A;
305 MFEM_ASSERT(length % pagesize == 0,
"");
310 static void MmuError(
int, siginfo_t *si,
void*)
314 const void *ptr = si->si_addr;
315 sprintf(str,
"Error while accessing address %p!", ptr);
316 mfem::out << std::endl <<
"An illegal memory access was made!";
321 static void MmuInit()
323 if (pagesize > 0) {
return; }
325 sa.sa_flags = SA_SIGINFO;
326 sigemptyset(&sa.sa_mask);
327 sa.sa_sigaction = MmuError;
328 if (sigaction(SIGBUS, &sa, NULL) == -1) {
mfem_error(
"SIGBUS"); }
329 if (sigaction(SIGSEGV, &sa, NULL) == -1) {
mfem_error(
"SIGSEGV"); }
330 pagesize = (uintptr_t) sysconf(_SC_PAGE_SIZE);
331 MFEM_ASSERT(pagesize > 0,
"pagesize must not be less than 1");
332 pagemask = pagesize - 1;
336 inline void MmuAlloc(
void **ptr,
const size_t bytes)
338 const size_t length = bytes == 0 ? 8 : bytes;
339 const int prot = PROT_READ | PROT_WRITE;
340 const int flags = MAP_ANONYMOUS | MAP_PRIVATE;
341 *ptr = ::mmap(NULL, length, prot, flags, -1, 0);
342 if (*ptr == MAP_FAILED) { throw ::std::bad_alloc(); }
346 inline void MmuDealloc(
void *ptr,
const size_t bytes)
348 const size_t length = bytes == 0 ? 8 : bytes;
349 if (::munmap(ptr, length) == -1) {
mfem_error(
"Dealloc error!"); }
353 inline void MmuProtect(
const void *ptr,
const size_t bytes)
355 static const bool mmu_protect_error = getenv(
"MFEM_MMU_PROTECT_ERROR");
356 if (!::mprotect(const_cast<void*>(ptr), bytes, PROT_NONE)) {
return; }
357 if (mmu_protect_error) {
mfem_error(
"MMU protection (NONE) error"); }
361 inline void MmuAllow(
const void *ptr,
const size_t bytes)
363 const int RW = PROT_READ | PROT_WRITE;
364 static const bool mmu_protect_error = getenv(
"MFEM_MMU_PROTECT_ERROR");
365 if (!::mprotect(const_cast<void*>(ptr), bytes, RW)) {
return; }
366 if (mmu_protect_error) {
mfem_error(
"MMU protection (R/W) error"); }
369 inline void MmuInit() { }
370 inline void MmuAlloc(
void **ptr,
const size_t bytes) { *ptr = std::malloc(bytes); }
371 inline void MmuDealloc(
void *ptr,
const size_t) { std::free(ptr); }
372 inline void MmuProtect(
const void*,
const size_t) { }
373 inline void MmuAllow(
const void*,
const size_t) { }
374 inline const void *MmuAddrR(
const void *a) {
return a; }
375 inline const void *MmuAddrP(
const void *a) {
return a; }
376 inline uintptr_t MmuLengthR(
const void*,
const size_t) {
return 0; }
377 inline uintptr_t MmuLengthP(
const void*,
const size_t) {
return 0; }
381 class MmuHostMemorySpace :
public HostMemorySpace
384 MmuHostMemorySpace(): HostMemorySpace() { MmuInit(); }
385 void Alloc(
void **ptr,
size_t bytes) { MmuAlloc(ptr, bytes); }
386 void Dealloc(
void *ptr) { MmuDealloc(ptr, maps->memories.at(ptr).bytes); }
387 void Protect(
const Memory& mem,
size_t bytes)
388 {
if (mem.h_rw) { mem.h_rw =
false; MmuProtect(mem.h_ptr, bytes); } }
389 void Unprotect(
const Memory &mem,
size_t bytes)
390 {
if (!mem.h_rw) { mem.h_rw =
true; MmuAllow(mem.h_ptr, bytes); } }
392 void AliasProtect(
const void *ptr,
size_t bytes)
393 { MmuProtect(MmuAddrR(ptr), MmuLengthR(ptr, bytes)); }
395 void AliasUnprotect(
const void *ptr,
size_t bytes)
396 { MmuAllow(MmuAddrP(ptr), MmuLengthP(ptr, bytes)); }
400 class UvmHostMemorySpace :
public HostMemorySpace
403 UvmHostMemorySpace(): HostMemorySpace() { }
404 void Alloc(
void **ptr,
size_t bytes) {
CuMallocManaged(ptr, bytes == 0 ? 8 : bytes); }
405 void Dealloc(
void *ptr) {
CuMemFree(ptr); }
409 class NoDeviceMemorySpace:
public DeviceMemorySpace
412 void Alloc(internal::Memory&) {
mfem_error(
"! Device Alloc"); }
413 void Dealloc(Memory&) {
mfem_error(
"! Device Dealloc"); }
414 void *HtoD(
void*,
const void*,
size_t) {
mfem_error(
"!HtoD");
return nullptr; }
415 void *DtoD(
void*,
const void*,
size_t) {
mfem_error(
"!DtoD");
return nullptr; }
416 void *DtoH(
void*,
const void*,
size_t) {
mfem_error(
"!DtoH");
return nullptr; }
420 class StdDeviceMemorySpace :
public DeviceMemorySpace { };
423 class CudaDeviceMemorySpace:
public DeviceMemorySpace
426 CudaDeviceMemorySpace(): DeviceMemorySpace() { }
427 void Alloc(Memory &base) {
CuMemAlloc(&base.d_ptr, base.bytes); }
428 void Dealloc(Memory &base) {
CuMemFree(base.d_ptr); }
429 void *HtoD(
void *dst,
const void *src,
size_t bytes)
431 void *DtoD(
void* dst,
const void* src,
size_t bytes)
433 void *DtoH(
void *dst,
const void *src,
size_t bytes)
438 class HostPinnedMemorySpace:
public HostMemorySpace
441 HostPinnedMemorySpace(): HostMemorySpace() { }
442 void Alloc(
void ** ptr,
size_t bytes)
override
451 void Dealloc(
void *ptr)
override
463 class HipDeviceMemorySpace:
public DeviceMemorySpace
466 HipDeviceMemorySpace(): DeviceMemorySpace() { }
467 void Alloc(Memory &base) {
HipMemAlloc(&base.d_ptr, base.bytes); }
468 void Dealloc(Memory &base) {
HipMemFree(base.d_ptr); }
469 void *HtoD(
void *dst,
const void *src,
size_t bytes)
471 void *DtoD(
void* dst,
const void* src,
size_t bytes)
473 void *DtoH(
void *dst,
const void *src,
size_t bytes)
478 class UvmCudaMemorySpace :
public DeviceMemorySpace
481 void Alloc(Memory &base) { base.d_ptr = base.h_ptr; }
482 void Dealloc(Memory&) { }
483 void *HtoD(
void *dst,
const void *src,
size_t bytes)
485 if (dst == src) { MFEM_STREAM_SYNC;
return dst; }
488 void *DtoD(
void* dst,
const void* src,
size_t bytes)
490 void *DtoH(
void *dst,
const void *src,
size_t bytes)
492 if (dst == src) { MFEM_STREAM_SYNC;
return dst; }
498 class MmuDeviceMemorySpace :
public DeviceMemorySpace
501 MmuDeviceMemorySpace(): DeviceMemorySpace() { }
502 void Alloc(Memory &m) { MmuAlloc(&m.d_ptr, m.bytes); }
503 void Dealloc(Memory &m) { MmuDealloc(m.d_ptr, m.bytes); }
504 void Protect(
const Memory &m)
505 {
if (m.d_rw) { m.d_rw =
false; MmuProtect(m.d_ptr, m.bytes); } }
506 void Unprotect(
const Memory &m)
507 {
if (!m.d_rw) { m.d_rw =
true; MmuAllow(m.d_ptr, m.bytes); } }
509 void AliasProtect(
const void *ptr,
size_t bytes)
510 { MmuProtect(MmuAddrR(ptr), MmuLengthR(ptr, bytes)); }
512 void AliasUnprotect(
const void *ptr,
size_t bytes)
513 { MmuAllow(MmuAddrP(ptr), MmuLengthP(ptr, bytes)); }
514 void *HtoD(
void *dst,
const void *src,
size_t bytes)
515 {
return std::memcpy(dst, src, bytes); }
516 void *DtoD(
void *dst,
const void *src,
size_t bytes)
517 {
return std::memcpy(dst, src, bytes); }
518 void *DtoH(
void *dst,
const void *src,
size_t bytes)
519 {
return std::memcpy(dst, src, bytes); }
522 #ifdef MFEM_USE_UMPIRE
523 class UmpireMemorySpace
526 umpire::ResourceManager &rm;
527 umpire::Allocator allocator;
528 bool owns_allocator{
false};
532 virtual ~UmpireMemorySpace() {
if (owns_allocator) { allocator.release(); } }
533 UmpireMemorySpace(
const char * name,
const char *
space)
534 : rm(umpire::ResourceManager::getInstance())
536 if (!rm.isAllocator(name))
538 allocator = rm.makeAllocator<umpire::strategy::DynamicPool>(
539 name, rm.getAllocator(space));
540 owns_allocator =
true;
544 allocator = rm.getAllocator(name);
545 owns_allocator =
false;
551 class UmpireHostMemorySpace :
public HostMemorySpace,
public UmpireMemorySpace
554 umpire::strategy::AllocationStrategy *strat;
556 UmpireHostMemorySpace(
const char * name)
558 UmpireMemorySpace(name,
"HOST"),
559 strat(allocator.getAllocationStrategy()) {}
560 void Alloc(
void **ptr,
size_t bytes)
override
561 { *ptr = allocator.allocate(bytes); }
562 void Dealloc(
void *ptr)
override { allocator.deallocate(ptr); }
563 void Insert(
void *ptr,
size_t bytes)
564 { rm.registerAllocation(ptr, {ptr, bytes, strat}); }
568 #if defined(MFEM_USE_CUDA) || defined(MFEM_USE_HIP)
569 class UmpireDeviceMemorySpace :
public DeviceMemorySpace,
570 public UmpireMemorySpace
573 UmpireDeviceMemorySpace(
const char * name)
574 : DeviceMemorySpace(),
575 UmpireMemorySpace(name,
"DEVICE") {}
576 void Alloc(Memory &base)
override
577 { base.d_ptr = allocator.allocate(base.bytes); }
578 void Dealloc(Memory &base)
override { rm.deallocate(base.d_ptr); }
579 void *HtoD(
void *dst,
const void *src,
size_t bytes)
override
589 void *DtoD(
void* dst,
const void* src,
size_t bytes)
override
599 void *DtoH(
void *dst,
const void *src,
size_t bytes)
override
611 class UmpireDeviceMemorySpace :
public NoDeviceMemorySpace
614 UmpireDeviceMemorySpace(
const char * ) {}
616 #endif // MFEM_USE_CUDA || MFEM_USE_HIP
617 #endif // MFEM_USE_UMPIRE
629 Ctrl(): host{
nullptr}, device{
nullptr} { }
635 mfem_error(
"Memory backends have already been configured!");
641 host[
static_cast<int>(
MT::HOST)] =
new StdHostMemorySpace();
642 host[
static_cast<int>(
MT::HOST_32)] =
new Aligned32HostMemorySpace();
643 host[
static_cast<int>(
MT::HOST_64)] =
new Aligned64HostMemorySpace();
647 host[
static_cast<int>(
MT::MANAGED)] =
new UvmHostMemorySpace();
651 device[
static_cast<int>(
MT::MANAGED)-shift] =
new UvmCudaMemorySpace();
661 const int mt_i =
static_cast<int>(mt);
663 if (!host[mt_i]) { host[mt_i] = NewHostCtrl(mt); }
664 MFEM_ASSERT(host[mt_i],
"Host memory controller is not configured!");
668 DeviceMemorySpace* Device(
const MemoryType mt)
671 MFEM_ASSERT(mt_i >= 0,
"");
673 if (!device[mt_i]) { device[mt_i] = NewDeviceCtrl(mt); }
674 MFEM_ASSERT(device[mt_i],
"Memory manager has not been configured!");
683 for (
int mt = mt_d; mt <
MemoryTypeSize; mt++) {
delete device[mt-mt_d]; }
687 HostMemorySpace* NewHostCtrl(
const MemoryType mt)
692 #ifdef MFEM_USE_UMPIRE
694 return new UmpireHostMemorySpace(
700 default: MFEM_ABORT(
"Unknown host memory controller!");
705 DeviceMemorySpace* NewDeviceCtrl(
const MemoryType mt)
709 #ifdef MFEM_USE_UMPIRE
711 return new UmpireDeviceMemorySpace(
714 return new UmpireDeviceMemorySpace(
723 #if defined(MFEM_USE_CUDA)
724 return new CudaDeviceMemorySpace();
725 #elif defined(MFEM_USE_HIP)
726 return new HipDeviceMemorySpace();
728 MFEM_ABORT(
"No device memory controller!");
732 default: MFEM_ABORT(
"Unknown device memory controller!");
740 static internal::Ctrl *ctrl;
742 void *MemoryManager::New_(
void *h_tmp,
size_t bytes,
MemoryType mt,
745 MFEM_ASSERT(exists,
"Internal error!");
764 void *MemoryManager::New_(
void *h_tmp,
size_t bytes,
MemoryType h_mt,
768 MFEM_ASSERT(exists,
"Internal error!");
769 MFEM_ASSERT(
IsHostMemory(h_mt),
"h_mt must be host type");
772 "d_mt must be device type, the same is h_mt, or DEFAULT");
779 if (h_tmp ==
nullptr) { ctrl->Host(h_mt)->Alloc(&h_ptr, bytes); }
780 else { h_ptr = h_tmp; }
784 mm.Insert(h_ptr, bytes, h_mt, d_mt);
788 CheckHostMemoryType_(h_mt, h_ptr,
false);
793 void *MemoryManager::Register_(
void *ptr,
void *h_tmp,
size_t bytes,
795 bool own,
bool alias,
unsigned &flags)
797 MFEM_CONTRACT_VAR(alias);
798 MFEM_ASSERT(exists,
"Internal error!");
799 MFEM_VERIFY(!alias,
"Cannot register an alias!");
807 MFEM_VERIFY_TYPES(h_mt, d_mt);
809 if (ptr ==
nullptr && h_tmp ==
nullptr)
811 MFEM_VERIFY(bytes == 0,
"internal error");
821 mm.Insert(h_ptr, bytes, h_mt, d_mt);
822 flags = (own ? flags |
Mem::OWNS_HOST : flags & ~Mem::OWNS_HOST) |
827 MFEM_VERIFY(ptr || bytes == 0,
828 "cannot register NULL device pointer with bytes = " << bytes);
829 if (h_tmp ==
nullptr) { ctrl->Host(h_mt)->Alloc(&h_ptr, bytes); }
830 else { h_ptr = h_tmp; }
831 mm.InsertDevice(ptr, h_ptr, bytes, h_mt, d_mt);
835 CheckHostMemoryType_(h_mt, h_ptr, alias);
839 void MemoryManager::Register2_(
void *h_ptr,
void *d_ptr,
size_t bytes,
841 bool own,
bool alias,
unsigned &flags)
843 MFEM_CONTRACT_VAR(alias);
844 MFEM_ASSERT(exists,
"Internal error!");
845 MFEM_ASSERT(!alias,
"Cannot register an alias!");
846 MFEM_VERIFY_TYPES(h_mt, d_mt);
848 if (h_ptr ==
nullptr && d_ptr ==
nullptr)
850 MFEM_VERIFY(bytes == 0,
"internal error");
856 MFEM_VERIFY(d_ptr || bytes == 0,
857 "cannot register NULL device pointer with bytes = " << bytes);
858 mm.InsertDevice(d_ptr, h_ptr, bytes, h_mt, d_mt);
863 CheckHostMemoryType_(h_mt, h_ptr, alias);
866 void MemoryManager::Alias_(
void *base_h_ptr,
size_t offset,
size_t bytes,
867 unsigned base_flags,
unsigned &flags)
869 mm.InsertAlias(base_h_ptr, (
char*)base_h_ptr + offset, bytes,
875 void MemoryManager::SetDeviceMemoryType_(
void *h_ptr,
unsigned flags,
878 MFEM_VERIFY(h_ptr,
"cannot set the device memory type: Memory is empty!");
879 if (!(flags & Mem::ALIAS))
881 auto mem_iter = maps->memories.find(h_ptr);
882 MFEM_VERIFY(mem_iter != maps->memories.end(),
"internal error");
883 internal::Memory &mem = mem_iter->second;
884 if (mem.d_mt == d_mt) {
return; }
885 MFEM_VERIFY(mem.d_ptr ==
nullptr,
"cannot set the device memory type:"
886 " device memory is allocated!");
891 auto alias_iter = maps->aliases.find(h_ptr);
892 MFEM_VERIFY(alias_iter != maps->aliases.end(),
"internal error");
893 internal::Alias &alias = alias_iter->second;
894 internal::Memory &base_mem = *alias.mem;
895 if (base_mem.d_mt == d_mt) {
return; }
896 MFEM_VERIFY(base_mem.d_ptr ==
nullptr,
897 "cannot set the device memory type:"
898 " alias' base device memory is allocated!");
899 base_mem.d_mt = d_mt;
910 MFEM_ASSERT(
IsHostMemory(h_mt),
"invalid h_mt = " << (
int)h_mt);
912 MFEM_ASSERT(!owns_device || owns_internal,
"invalid Memory state");
913 MFEM_ASSERT(registered || !(owns_host || owns_device || owns_internal),
914 "invalid Memory state");
915 if (!
mm.exists || !registered) {
return h_mt; }
921 MFEM_ASSERT(h_mt == maps->aliases.at(h_ptr).h_mt,
"");
922 mm.EraseAlias(h_ptr);
928 { ctrl->Host(h_mt)->Dealloc(h_ptr); }
932 MFEM_ASSERT(h_mt == maps->memories.at(h_ptr).h_mt,
"");
933 mm.Erase(h_ptr, owns_device);
939 void MemoryManager::DeleteDevice_(
void *h_ptr,
unsigned & flags)
944 mm.EraseDevice(h_ptr);
949 bool MemoryManager::MemoryClassCheck_(
MemoryClass mc,
void *h_ptr,
955 MFEM_VERIFY(bytes == 0,
"Trying to access NULL with size " << bytes);
959 if (!(flags & Mem::ALIAS))
961 auto iter = maps->memories.find(h_ptr);
962 MFEM_VERIFY(iter != maps->memories.end(),
"internal error");
963 d_mt = iter->second.d_mt;
967 auto iter = maps->aliases.find(h_ptr);
968 MFEM_VERIFY(iter != maps->aliases.end(),
"internal error");
969 d_mt = iter->second.mem->d_mt;
1006 size_t bytes,
unsigned &flags)
1008 if (h_ptr) { CheckHostMemoryType_(h_mt, h_ptr, flags & Mem::ALIAS); }
1009 if (bytes > 0) { MFEM_VERIFY(flags & Mem::REGISTERED,
""); }
1010 MFEM_ASSERT(MemoryClassCheck_(mc, h_ptr, h_mt, bytes, flags),
"");
1015 if (flags & Mem::ALIAS)
1016 {
return mm.GetAliasHostPtr(h_ptr, bytes, copy); }
1017 else {
return mm.GetHostPtr(h_ptr, bytes, copy); }
1023 if (flags & Mem::ALIAS)
1024 {
return mm.GetAliasDevicePtr(h_ptr, bytes, copy); }
1025 else {
return mm.GetDevicePtr(h_ptr, bytes, copy); }
1030 size_t bytes,
unsigned &flags)
1032 if (h_ptr) { CheckHostMemoryType_(h_mt, h_ptr, flags & Mem::ALIAS); }
1033 if (bytes > 0) { MFEM_VERIFY(flags & Mem::REGISTERED,
""); }
1034 MFEM_ASSERT(MemoryClassCheck_(mc, h_ptr, h_mt, bytes, flags),
"");
1039 if (flags & Mem::ALIAS)
1040 {
return mm.GetAliasHostPtr(h_ptr, bytes, copy); }
1041 else {
return mm.GetHostPtr(h_ptr, bytes, copy); }
1047 if (flags & Mem::ALIAS)
1048 {
return mm.GetAliasDevicePtr(h_ptr, bytes, copy); }
1049 else {
return mm.GetDevicePtr(h_ptr, bytes, copy); }
1054 size_t bytes,
unsigned &flags)
1056 if (h_ptr) { CheckHostMemoryType_(h_mt, h_ptr, flags & Mem::ALIAS); }
1057 if (bytes > 0) { MFEM_VERIFY(flags & Mem::REGISTERED,
""); }
1058 MFEM_ASSERT(MemoryClassCheck_(mc, h_ptr, h_mt, bytes, flags),
"");
1062 if (flags & Mem::ALIAS)
1063 {
return mm.GetAliasHostPtr(h_ptr, bytes,
false); }
1064 else {
return mm.GetHostPtr(h_ptr, bytes,
false); }
1069 if (flags & Mem::ALIAS)
1070 {
return mm.GetAliasDevicePtr(h_ptr, bytes,
false); }
1071 else {
return mm.GetDevicePtr(h_ptr, bytes,
false); }
1075 void MemoryManager::SyncAlias_(
const void *base_h_ptr,
void *alias_h_ptr,
1076 size_t alias_bytes,
unsigned base_flags,
1077 unsigned &alias_flags)
1081 MFEM_ASSERT(alias_flags & Mem::ALIAS,
"not an alias");
1082 if ((base_flags &
Mem::VALID_HOST) && !(alias_flags & Mem::VALID_HOST))
1084 mm.GetAliasHostPtr(alias_h_ptr, alias_bytes,
true);
1088 if (!(alias_flags & Mem::REGISTERED))
1090 mm.InsertAlias(base_h_ptr, alias_h_ptr, alias_bytes, base_flags & Mem::ALIAS);
1092 ~(Mem::OWNS_HOST | Mem::OWNS_DEVICE);
1094 mm.GetAliasDevicePtr(alias_h_ptr, alias_bytes,
true);
1100 MemoryType MemoryManager::GetDeviceMemoryType_(
void *h_ptr,
bool alias)
1106 auto iter = maps->memories.find(h_ptr);
1107 MFEM_ASSERT(iter != maps->memories.end(),
"internal error");
1108 return iter->second.d_mt;
1111 auto iter = maps->aliases.find(h_ptr);
1112 MFEM_ASSERT(iter != maps->aliases.end(),
"internal error");
1113 return iter->second.mem->d_mt;
1115 MFEM_ABORT(
"internal error");
1116 return MemoryManager::host_mem_type;
1119 MemoryType MemoryManager::GetHostMemoryType_(
void *h_ptr)
1121 if (!
mm.exists) {
return MemoryManager::host_mem_type; }
1122 if (
mm.
IsKnown(h_ptr)) {
return maps->memories.at(h_ptr).h_mt; }
1123 if (
mm.
IsAlias(h_ptr)) {
return maps->aliases.at(h_ptr).h_mt; }
1124 return MemoryManager::host_mem_type;
1127 void MemoryManager::Copy_(
void *dst_h_ptr,
const void *src_h_ptr,
1128 size_t bytes,
unsigned src_flags,
1129 unsigned &dst_flags)
1139 const bool dst_on_host =
1141 (!(dst_flags & Mem::VALID_DEVICE) ||
1144 dst_flags = dst_flags &
1147 const bool src_on_host =
1149 (!(src_flags & Mem::VALID_DEVICE) ||
1152 const void *src_d_ptr =
1153 src_on_host ? NULL :
1155 mm.GetAliasDevicePtr(src_h_ptr, bytes,
false) :
1156 mm.GetDevicePtr(src_h_ptr, bytes,
false));
1162 if (dst_h_ptr != src_h_ptr && bytes != 0)
1164 MFEM_ASSERT((
const char*)dst_h_ptr + bytes <= src_h_ptr ||
1165 (
const char*)src_h_ptr + bytes <= dst_h_ptr,
1167 std::memcpy(dst_h_ptr, src_h_ptr, bytes);
1172 if (dst_h_ptr != src_d_ptr && bytes != 0)
1174 internal::Memory &src_d_base = maps->memories.at(src_h_ptr);
1176 ctrl->Device(src_d_mt)->DtoH(dst_h_ptr, src_d_ptr, bytes);
1182 void *dest_d_ptr = (dst_flags &
Mem::ALIAS) ?
1183 mm.GetAliasDevicePtr(dst_h_ptr, bytes,
false) :
1184 mm.GetDevicePtr(dst_h_ptr, bytes,
false);
1187 const bool known =
mm.
IsKnown(dst_h_ptr);
1189 MFEM_VERIFY(alias||known,
"");
1191 maps->memories.at(dst_h_ptr).d_mt :
1192 maps->aliases.at(dst_h_ptr).mem->d_mt;
1193 ctrl->Device(d_mt)->HtoD(dest_d_ptr, src_h_ptr, bytes);
1197 if (dest_d_ptr != src_d_ptr && bytes != 0)
1199 const bool known =
mm.
IsKnown(dst_h_ptr);
1201 MFEM_VERIFY(alias||known,
"");
1203 maps->memories.at(dst_h_ptr).d_mt :
1204 maps->aliases.at(dst_h_ptr).mem->d_mt;
1205 ctrl->Device(d_mt)->DtoD(dest_d_ptr, src_d_ptr, bytes);
1211 void MemoryManager::CopyToHost_(
void *dest_h_ptr,
const void *src_h_ptr,
1212 size_t bytes,
unsigned src_flags)
1217 if (dest_h_ptr != src_h_ptr && bytes != 0)
1219 MFEM_ASSERT((
char*)dest_h_ptr + bytes <= src_h_ptr ||
1220 (
const char*)src_h_ptr + bytes <= dest_h_ptr,
1222 std::memcpy(dest_h_ptr, src_h_ptr, bytes);
1227 MFEM_ASSERT(IsKnown_(src_h_ptr),
"internal error");
1228 const void *src_d_ptr = (src_flags &
Mem::ALIAS) ?
1229 mm.GetAliasDevicePtr(src_h_ptr, bytes,
false) :
1230 mm.GetDevicePtr(src_h_ptr, bytes,
false);
1231 const internal::Memory &base = maps->memories.at(dest_h_ptr);
1233 ctrl->Device(d_mt)->DtoH(dest_h_ptr, src_d_ptr, bytes);
1237 void MemoryManager::CopyFromHost_(
void *dest_h_ptr,
const void *src_h_ptr,
1238 size_t bytes,
unsigned &dest_flags)
1243 if (dest_h_ptr != src_h_ptr && bytes != 0)
1245 MFEM_ASSERT((
char*)dest_h_ptr + bytes <= src_h_ptr ||
1246 (
const char*)src_h_ptr + bytes <= dest_h_ptr,
1248 std::memcpy(dest_h_ptr, src_h_ptr, bytes);
1253 void *dest_d_ptr = (dest_flags &
Mem::ALIAS) ?
1254 mm.GetAliasDevicePtr(dest_h_ptr, bytes,
false) :
1255 mm.GetDevicePtr(dest_h_ptr, bytes,
false);
1256 const internal::Memory &base = maps->memories.at(dest_h_ptr);
1258 ctrl->Device(d_mt)->HtoD(dest_d_ptr, src_h_ptr, bytes);
1260 dest_flags = dest_flags &
1264 bool MemoryManager::IsKnown_(
const void *h_ptr)
1266 return maps->memories.find(h_ptr) != maps->memories.end();
1269 bool MemoryManager::IsAlias_(
const void *h_ptr)
1271 return maps->aliases.find(h_ptr) != maps->aliases.end();
1274 void MemoryManager::Insert(
void *h_ptr,
size_t bytes,
1277 #ifdef MFEM_TRACK_MEM_MANAGER
1278 mfem::out <<
"[mfem memory manager]: registering h_ptr: " << h_ptr
1279 <<
", bytes: " << bytes << std::endl;
1283 MFEM_VERIFY(bytes == 0,
"Trying to add NULL with size " << bytes);
1286 MFEM_VERIFY_TYPES(h_mt, d_mt);
1290 maps->memories.emplace(h_ptr, internal::Memory(h_ptr, bytes, h_mt, d_mt));
1292 if (res.second ==
false)
1294 auto &m = res.first->second;
1295 MFEM_VERIFY(m.bytes >= bytes && m.h_mt == h_mt &&
1298 "Address already present with different attributes!");
1299 #ifdef MFEM_TRACK_MEM_MANAGER
1300 mfem::out <<
"[mfem memory manager]: repeated registration of h_ptr: "
1301 << h_ptr << std::endl;
1307 void MemoryManager::InsertDevice(
void *d_ptr,
void *h_ptr,
size_t bytes,
1311 MFEM_ASSERT(h_ptr != NULL,
"internal error");
1312 Insert(h_ptr, bytes, h_mt, d_mt);
1313 internal::Memory &mem = maps->memories.at(h_ptr);
1314 if (d_ptr == NULL && bytes != 0) { ctrl->Device(d_mt)->Alloc(mem); }
1315 else { mem.d_ptr = d_ptr; }
1318 void MemoryManager::InsertAlias(
const void *base_ptr,
void *alias_ptr,
1319 const size_t bytes,
const bool base_is_alias)
1321 size_t offset =
static_cast<size_t>(
static_cast<const char*
>(alias_ptr) -
1322 static_cast<const char*>(base_ptr));
1323 #ifdef MFEM_TRACK_MEM_MANAGER
1324 mfem::out <<
"[mfem memory manager]: registering alias of base_ptr: "
1325 << base_ptr <<
", offset: " << offset <<
", bytes: " << bytes
1326 <<
", base is alias: " << base_is_alias << std::endl;
1330 MFEM_VERIFY(offset == 0,
1331 "Trying to add alias to NULL at offset " << offset);
1336 const internal::Alias &alias = maps->aliases.at(base_ptr);
1337 MFEM_ASSERT(alias.mem,
"");
1338 base_ptr = alias.mem->h_ptr;
1339 offset += alias.offset;
1340 #ifdef MFEM_TRACK_MEM_MANAGER
1341 mfem::out <<
"[mfem memory manager]: real base_ptr: " << base_ptr
1345 internal::Memory &mem = maps->memories.at(base_ptr);
1346 MFEM_VERIFY(offset + bytes <= mem.bytes,
"invalid alias");
1348 maps->aliases.emplace(alias_ptr,
1349 internal::Alias{&mem, offset, 1, mem.h_mt});
1350 if (res.second ==
false)
1352 internal::Alias &alias = res.first->second;
1355 alias.offset = offset;
1356 alias.h_mt = mem.h_mt;
1361 void MemoryManager::Erase(
void *h_ptr,
bool free_dev_ptr)
1363 #ifdef MFEM_TRACK_MEM_MANAGER
1364 mfem::out <<
"[mfem memory manager]: un-registering h_ptr: " << h_ptr
1367 if (!h_ptr) {
return; }
1368 auto mem_map_iter = maps->memories.find(h_ptr);
1369 if (mem_map_iter == maps->memories.end()) {
mfem_error(
"Unknown pointer!"); }
1370 internal::Memory &mem = mem_map_iter->second;
1371 if (mem.d_ptr && free_dev_ptr) { ctrl->Device(mem.d_mt)->Dealloc(mem);}
1372 maps->memories.erase(mem_map_iter);
1375 void MemoryManager::EraseDevice(
void *h_ptr)
1377 if (!h_ptr) {
return; }
1378 auto mem_map_iter = maps->memories.find(h_ptr);
1379 if (mem_map_iter == maps->memories.end()) {
mfem_error(
"Unknown pointer!"); }
1380 internal::Memory &mem = mem_map_iter->second;
1381 if (mem.d_ptr) { ctrl->Device(mem.d_mt)->Dealloc(mem);}
1382 mem.d_ptr =
nullptr;
1385 void MemoryManager::EraseAlias(
void *alias_ptr)
1387 #ifdef MFEM_TRACK_MEM_MANAGER
1388 mfem::out <<
"[mfem memory manager]: un-registering alias_ptr: " << alias_ptr
1391 if (!alias_ptr) {
return; }
1392 auto alias_map_iter = maps->aliases.find(alias_ptr);
1393 if (alias_map_iter == maps->aliases.end()) {
mfem_error(
"Unknown alias!"); }
1394 internal::Alias &alias = alias_map_iter->second;
1395 if (--alias.counter) {
return; }
1396 maps->aliases.erase(alias_map_iter);
1399 void *MemoryManager::GetDevicePtr(
const void *h_ptr,
size_t bytes,
1404 MFEM_VERIFY(bytes == 0,
"Trying to access NULL with size " << bytes);
1407 internal::Memory &mem = maps->memories.at(h_ptr);
1410 MFEM_VERIFY_TYPES(h_mt, d_mt);
1414 if (mem.bytes) { ctrl->Device(d_mt)->Alloc(mem); }
1417 if (mem.d_ptr) { ctrl->Device(d_mt)->Unprotect(mem); }
1420 MFEM_ASSERT(bytes <= mem.bytes,
"invalid copy size");
1421 if (bytes) { ctrl->Device(d_mt)->HtoD(mem.d_ptr, h_ptr, bytes); }
1423 ctrl->Host(h_mt)->Protect(mem, bytes);
1427 void *MemoryManager::GetAliasDevicePtr(
const void *alias_ptr,
size_t bytes,
1432 MFEM_VERIFY(bytes == 0,
"Trying to access NULL with size " << bytes);
1435 auto &alias_map = maps->aliases;
1436 auto alias_map_iter = alias_map.find(alias_ptr);
1437 if (alias_map_iter == alias_map.end()) {
mfem_error(
"alias not found"); }
1438 const internal::Alias &alias = alias_map_iter->second;
1439 const size_t offset = alias.offset;
1440 internal::Memory &mem = *alias.mem;
1443 MFEM_VERIFY_TYPES(h_mt, d_mt);
1447 if (mem.bytes) { ctrl->Device(d_mt)->Alloc(mem); }
1449 void *alias_h_ptr =
static_cast<char*
>(mem.h_ptr) + offset;
1450 void *alias_d_ptr =
static_cast<char*
>(mem.d_ptr) + offset;
1451 MFEM_ASSERT(alias_h_ptr == alias_ptr,
"internal error");
1452 MFEM_ASSERT(offset + bytes <= mem.bytes,
"internal error");
1453 mem.d_rw = mem.h_rw =
false;
1454 if (mem.d_ptr) { ctrl->Device(d_mt)->AliasUnprotect(alias_d_ptr, bytes); }
1455 ctrl->Host(h_mt)->AliasUnprotect(alias_ptr, bytes);
1456 if (copy && mem.d_ptr)
1457 { ctrl->Device(d_mt)->HtoD(alias_d_ptr, alias_h_ptr, bytes); }
1458 ctrl->Host(h_mt)->AliasProtect(alias_ptr, bytes);
1462 void *MemoryManager::GetHostPtr(
const void *ptr,
size_t bytes,
bool copy)
1464 const internal::Memory &mem = maps->memories.at(ptr);
1465 MFEM_ASSERT(mem.h_ptr == ptr,
"internal error");
1466 MFEM_ASSERT(bytes <= mem.bytes,
"internal error")
1469 MFEM_VERIFY_TYPES(h_mt, d_mt);
1471 ctrl->Host(h_mt)->Unprotect(mem, bytes);
1472 if (mem.d_ptr) { ctrl->Device(d_mt)->Unprotect(mem); }
1473 if (copy && mem.d_ptr) { ctrl->Device(d_mt)->DtoH(mem.h_ptr, mem.d_ptr, bytes); }
1474 if (mem.d_ptr) { ctrl->Device(d_mt)->Protect(mem); }
1478 void *MemoryManager::GetAliasHostPtr(
const void *ptr,
size_t bytes,
1481 const internal::Alias &alias = maps->aliases.at(ptr);
1482 const internal::Memory *
const mem = alias.mem;
1485 MFEM_VERIFY_TYPES(h_mt, d_mt);
1486 void *alias_h_ptr =
static_cast<char*
>(mem->h_ptr) + alias.offset;
1487 void *alias_d_ptr = static_cast<char*>(mem->d_ptr) + alias.offset;
1488 MFEM_ASSERT(alias_h_ptr == ptr,
"internal error");
1490 ctrl->Host(h_mt)->AliasUnprotect(alias_h_ptr, bytes);
1491 if (mem->d_ptr) { ctrl->Device(d_mt)->AliasUnprotect(alias_d_ptr, bytes); }
1492 if (copy_data && mem->d_ptr)
1493 { ctrl->Device(d_mt)->DtoH(const_cast<void*>(ptr), alias_d_ptr, bytes); }
1494 if (mem->d_ptr) { ctrl->Device(d_mt)->AliasProtect(alias_d_ptr, bytes); }
1500 if (exists) {
return; }
1501 maps =
new internal::Maps();
1502 ctrl =
new internal::Ctrl();
1513 MFEM_VERIFY(!configured,
"changing the dual MemoryTypes is not allowed after"
1514 " MemoryManager configuration!");
1515 UpdateDualMemoryType(mt, dual_mt);
1521 "invalid MemoryType, mt = " << (
int)mt);
1523 "invalid dual MemoryType, dual_mt = " << (
int)dual_mt);
1528 dual_map[(int)mt] = dual_mt;
1536 "invalid (mt, dual_mt) pair: ("
1545 MemoryManager::UpdateDualMemoryType(host_mt, device_mt);
1546 MemoryManager::UpdateDualMemoryType(device_mt, host_mt);
1551 MemoryManager::UpdateDualMemoryType(
1556 host_mem_type = host_mt;
1557 device_mem_type = device_mt;
1563 MFEM_VERIFY(exists,
"MemoryManager has already been destroyed!");
1564 #ifdef MFEM_TRACK_MEM_MANAGER
1565 size_t num_memories = maps->memories.size();
1566 size_t num_aliases = maps->aliases.size();
1567 if (num_memories != 0 || num_aliases != 0)
1569 MFEM_WARNING(
"...\n\t number of registered pointers: " << num_memories
1570 <<
"\n\t number of registered aliases : " << num_aliases);
1575 mfem::out <<
"Destroying the MemoryManager ...\n"
1576 <<
"remaining registered pointers : "
1577 << maps->memories.size() <<
'\n'
1578 <<
"remaining registered aliases : "
1579 << maps->aliases.size() <<
'\n';
1581 for (
auto& n : maps->memories)
1583 internal::Memory &mem = n.second;
1585 if (mem_h_ptr) { ctrl->Host(mem.h_mt)->Dealloc(mem.h_ptr); }
1586 if (mem.d_ptr) { ctrl->Device(mem.d_mt)->Dealloc(mem); }
1588 delete maps; maps =
nullptr;
1589 delete ctrl; ctrl =
nullptr;
1610 for (
const auto& n : maps->memories)
1612 const internal::Memory &mem = n.second;
1613 out <<
"\nkey " << n.first <<
", "
1614 <<
"h_ptr " << mem.h_ptr <<
", "
1615 <<
"d_ptr " << mem.d_ptr;
1618 if (maps->memories.size() > 0) { out << std::endl; }
1625 for (
const auto& n : maps->aliases)
1627 const internal::Alias &alias = n.second;
1628 out <<
"\nalias: key " << n.first <<
", "
1629 <<
"h_ptr " << alias.mem->h_ptr <<
", "
1630 <<
"offset " << alias.offset <<
", "
1631 <<
"counter " << alias.counter;
1634 if (maps->aliases.size() > 0) { out << std::endl; }
1638 int MemoryManager::CompareHostAndDevice_(
void *h_ptr,
size_t size,
1642 mm.GetAliasDevicePtr(h_ptr, size,
false) :
1643 mm.GetDevicePtr(h_ptr, size,
false);
1644 char *h_buf =
new char[size];
1645 #ifdef MFEM_USE_CUDA
1650 std::memcpy(h_buf, d_ptr, size);
1652 int res = std::memcmp(h_ptr, h_buf, size);
1662 <<
"\n registered = " << bool(flags & Mem::REGISTERED)
1663 <<
"\n owns host = " << bool(flags & Mem::OWNS_HOST)
1664 <<
"\n owns device = " << bool(flags & Mem::OWNS_DEVICE)
1665 <<
"\n owns internal = " << bool(flags & Mem::OWNS_INTERNAL)
1666 <<
"\n valid host = " << bool(flags & Mem::VALID_HOST)
1667 <<
"\n valid device = " << bool(flags & Mem::VALID_DEVICE)
1668 <<
"\n device flag = " << bool(flags & Mem::USE_DEVICE)
1669 <<
"\n alias = " << bool(flags & Mem::ALIAS)
1673 void MemoryManager::CheckHostMemoryType_(
MemoryType h_mt,
void *h_ptr,
1676 if (!
mm.exists) {
return;}
1679 auto it = maps->memories.find(h_ptr);
1680 MFEM_VERIFY(it != maps->memories.end(),
1681 "host pointer is not registered: h_ptr = " << h_ptr);
1682 MFEM_VERIFY(h_mt == it->second.h_mt,
"host pointer MemoryType mismatch");
1686 auto it = maps->aliases.find(h_ptr);
1687 MFEM_VERIFY(it != maps->aliases.end(),
1688 "alias pointer is not registered: h_ptr = " << h_ptr);
1689 MFEM_VERIFY(h_mt == it->second.h_mt,
"alias pointer MemoryType mismatch");
1695 bool MemoryManager::exists =
false;
1696 bool MemoryManager::configured =
false;
1713 MemoryType::HOST_UMPIRE
1716 #ifdef MFEM_USE_UMPIRE
1717 const char * MemoryManager::h_umpire_name =
"MFEM_HOST";
1718 const char * MemoryManager::d_umpire_name =
"MFEM_DEVICE";
1719 const char * MemoryManager::d_umpire_2_name =
"MFEM_DEVICE_2";
1725 "host-std",
"host-32",
"host-64",
"host-debug",
"host-umpire",
"host-pinned",
1726 #if defined(MFEM_USE_CUDA)
1729 #elif defined(MFEM_USE_HIP)
1737 #if defined(MFEM_USE_CUDA)
1740 #elif defined(MFEM_USE_HIP)
void * CuMemcpyHtoD(void *dst, const void *src, size_t bytes)
Copies memory from Host to Device and returns destination ptr.
void * CuMemFree(void *dptr)
Frees device memory and returns destination ptr.
Host memory; aligned at 64 bytes.
bool IsHostMemory(MemoryType mt)
Return true if the given memory type is in MemoryClass::HOST.
Device memory; using CUDA or HIP *Malloc and *Free.
void * CuMemFreeHostPinned(void *ptr)
Frees page-locked (pinned) host memory and returns destination ptr.
void PrintFlags() const
Print the internal flags.
static const char * GetUmpireHostAllocatorName()
Get the host Umpire allocator name used with MemoryType::HOST_UMPIRE.
const char * MemoryTypeName[MemoryTypeSize]
Memory type names, used during Device:: configuration.
static MemoryType GetHostMemoryType()
Host memory; allocated from a "host-debug" pool.
void Configure(const MemoryType h_mt, const MemoryType d_mt)
Configure the Memory manager with given default host and device types. This method will be called whe...
Host memory: pinned (page-locked)
int PrintAliases(std::ostream &out=mfem::out)
int CompareHostAndDevice(int size) const
If both the host and the device data are valid, compare their contents.
bool IsAlias(const void *h_ptr)
Return true if the pointer is known by the memory manager as an alias.
bool MemoryClassContainsType(MemoryClass mc, MemoryType mt)
Return true iff the MemoryType mt is contained in the MemoryClass mc.
void * HipMemFreeHostPinned(void *ptr)
Frees page-locked (pinned) host memory and returns destination ptr.
void * CuMallocManaged(void **dptr, size_t bytes)
Allocates managed device memory.
Host memory; aligned at 32 bytes.
static MemoryType GetDualMemoryType(MemoryType mt)
Return the dual MemoryType of the given one, mt.
constexpr int DeviceMemoryType
static const char * GetUmpireDeviceAllocatorName()
Get the device Umpire allocator name used with MemoryType::DEVICE_UMPIRE.
void * HipMemAllocHostPinned(void **ptr, size_t bytes)
Allocates page-locked (pinned) host memory.
constexpr int HostMemoryType
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
static MemoryType GetDeviceMemoryType()
void * HipMemFree(void *dptr)
Frees device memory.
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()
void * CuMemcpyDtoD(void *dst, const void *src, size_t bytes)
Copies memory from Device to Device.
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.
void * HipMemcpyDtoH(void *dst, const void *src, size_t bytes)
Copies memory from Device to Host.
static const char * GetUmpireDevice2AllocatorName()
Get the device Umpire allocator name used with MemoryType::DEVICE_UMPIRE_2.
void * HipMemAlloc(void **dptr, size_t bytes)
Allocates device memory.
double p(const Vector &x, double t)
static void SetDualMemoryType(MemoryType mt, MemoryType dual_mt)
Set the dual memory type of mt to be dual_mt.
void Init()
Initialize the memory manager.
MemoryType
Memory types supported by MFEM.
bool IsKnown(const void *h_ptr)
Return true if the pointer is known by the memory manager.
constexpr int HostMemoryTypeSize
bool IsDeviceMemory(MemoryType mt)
Return true if the given memory type is in MemoryClass::DEVICE.
MemoryManager mm
The (single) global memory manager object.
Host memory; using new[] and delete[].
void * HipMemcpyHtoD(void *dst, const void *src, size_t bytes)
Copies memory from Host to Device.
MemoryType GetMemoryType(MemoryClass mc)
Return a suitable MemoryType for a given MemoryClass.
void * CuMemAllocHostPinned(void **ptr, size_t bytes)
Allocates page-locked (pinned) host memory.
void * HipMemcpyDtoD(void *dst, const void *src, size_t bytes)
Copies memory from Device to Device.
constexpr int DeviceMemoryTypeSize
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.
void * CuMemAlloc(void **dptr, size_t bytes)
Allocates device memory and returns destination ptr.
MemoryClass
Memory classes identify sets of memory types.
void * CuMemcpyDtoH(void *dst, const void *src, size_t bytes)
Copies memory from Device to Host.
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().