17 #include <unordered_map> 29 #define mfem_memalign(p,a,s) posix_memalign(p,a,s) 30 #define mfem_aligned_free free 32 #define mfem_memalign(p,a,s) (((*(p))=_aligned_malloc((s),(a))),*(p)?0:errno) 33 #define mfem_aligned_free _aligned_free 36 #ifdef MFEM_USE_UMPIRE 37 #include <umpire/Umpire.hpp> 38 #include <umpire/strategy/QuickPool.hpp> 41 #if defined(MFEM_USE_CUDA) && !defined(UMPIRE_ENABLE_CUDA) 42 #error "CUDA is not enabled in Umpire!" 45 #if defined(MFEM_USE_HIP) && !defined(UMPIRE_ENABLE_HIP) 46 #error "HIP is not enabled in Umpire!" 48 #endif // MFEM_USE_UMPIRE 51 #define MAP_ANONYMOUS MAP_ANON 70 MFEM_VERIFY(
false,
"");
91 MFEM_ABORT(
"invalid MemoryClass");
100 "d_mt = " << (
int)d_mt);
126 MFEM_VERIFY(sync,
"");
144 return std::max(mc1, mc2);
171 mutable bool h_rw, d_rw;
173 h_ptr(
p), d_ptr(nullptr), bytes(
b), h_mt(h), d_mt(d),
174 h_rw(true), d_rw(true) { }
189 typedef std::unordered_map<const void*, Memory> MemoryMap;
190 typedef std::unordered_map<const void*, Alias> AliasMap;
200 static internal::Maps *maps;
206 class HostMemorySpace
209 virtual ~HostMemorySpace() { }
210 virtual void Alloc(
void **ptr,
size_t bytes) { *ptr = std::malloc(bytes); }
211 virtual void Dealloc(
void *ptr) { std::free(ptr); }
212 virtual void Protect(
const Memory&,
size_t) { }
213 virtual void Unprotect(
const Memory&,
size_t) { }
214 virtual void AliasProtect(
const void*,
size_t) { }
215 virtual void AliasUnprotect(
const void*,
size_t) { }
219 class DeviceMemorySpace
222 virtual ~DeviceMemorySpace() { }
223 virtual void Alloc(Memory &base) { base.d_ptr = std::malloc(base.bytes); }
224 virtual void Dealloc(Memory &base) { std::free(base.d_ptr); }
225 virtual void Protect(
const Memory&) { }
226 virtual void Unprotect(
const Memory&) { }
227 virtual void AliasProtect(
const void*,
size_t) { }
228 virtual void AliasUnprotect(
const void*,
size_t) { }
229 virtual void *HtoD(
void *dst,
const void *src,
size_t bytes)
230 {
return std::memcpy(dst, src, bytes); }
231 virtual void *DtoD(
void *dst,
const void *src,
size_t bytes)
232 {
return std::memcpy(dst, src, bytes); }
233 virtual void *DtoH(
void *dst,
const void *src,
size_t bytes)
234 {
return std::memcpy(dst, src, bytes); }
238 class StdHostMemorySpace :
public HostMemorySpace { };
241 struct NoHostMemorySpace :
public HostMemorySpace
243 void Alloc(
void**,
const size_t) {
mfem_error(
"! Host Alloc error"); }
247 class Aligned32HostMemorySpace :
public HostMemorySpace
250 Aligned32HostMemorySpace(): HostMemorySpace() { }
251 void Alloc(
void **ptr,
size_t bytes)
252 {
if (mfem_memalign(ptr, 32, bytes) != 0) { throw ::std::bad_alloc(); } }
253 void Dealloc(
void *ptr) { mfem_aligned_free(ptr); }
257 class Aligned64HostMemorySpace :
public HostMemorySpace
260 Aligned64HostMemorySpace(): HostMemorySpace() { }
261 void Alloc(
void **ptr,
size_t bytes)
262 {
if (mfem_memalign(ptr, 64, bytes) != 0) { throw ::std::bad_alloc(); } }
263 void Dealloc(
void *ptr) { mfem_aligned_free(ptr); }
267 static uintptr_t pagesize = 0;
268 static uintptr_t pagemask = 0;
271 inline const void *MmuAddrR(
const void *ptr)
273 const uintptr_t addr = (uintptr_t) ptr;
274 return (addr & pagemask) ? (
void*) ((addr + pagesize) & ~pagemask) : ptr;
278 inline const void *MmuAddrP(
const void *ptr)
280 const uintptr_t addr = (uintptr_t) ptr;
281 return (
void*) (addr & ~pagemask);
285 inline uintptr_t MmuLengthR(
const void *ptr,
const size_t bytes)
288 const uintptr_t
a = (uintptr_t) ptr;
289 const uintptr_t A = (uintptr_t) MmuAddrR(ptr);
290 MFEM_ASSERT(
a <= A,
"");
291 const uintptr_t
b =
a + bytes;
292 const uintptr_t B =
b & ~pagemask;
293 MFEM_ASSERT(B <=
b,
"");
294 const uintptr_t length = B > A ? B - A : 0;
295 MFEM_ASSERT(length % pagesize == 0,
"");
300 inline uintptr_t MmuLengthP(
const void *ptr,
const size_t bytes)
303 const uintptr_t
a = (uintptr_t) ptr;
304 const uintptr_t A = (uintptr_t) MmuAddrP(ptr);
305 MFEM_ASSERT(A <=
a,
"");
306 const uintptr_t
b =
a + bytes;
307 const uintptr_t B =
b & pagemask ? (
b + pagesize) & ~pagemask :
b;
308 MFEM_ASSERT(
b <= B,
"");
309 MFEM_ASSERT(B >= A,
"");
310 const uintptr_t length = B - A;
311 MFEM_ASSERT(length % pagesize == 0,
"");
316 static void MmuError(
int, siginfo_t *si,
void*)
318 constexpr
size_t buf_size = 64;
321 const void *ptr = si->si_addr;
322 snprintf(str, buf_size,
"Error while accessing address %p!", ptr);
323 mfem::out << std::endl <<
"An illegal memory access was made!";
328 static void MmuInit()
330 if (pagesize > 0) {
return; }
332 sa.sa_flags = SA_SIGINFO;
333 sigemptyset(&sa.sa_mask);
334 sa.sa_sigaction = MmuError;
335 if (sigaction(SIGBUS, &sa, NULL) == -1) {
mfem_error(
"SIGBUS"); }
336 if (sigaction(SIGSEGV, &sa, NULL) == -1) {
mfem_error(
"SIGSEGV"); }
337 pagesize = (uintptr_t) sysconf(_SC_PAGE_SIZE);
338 MFEM_ASSERT(pagesize > 0,
"pagesize must not be less than 1");
339 pagemask = pagesize - 1;
343 inline void MmuAlloc(
void **ptr,
const size_t bytes)
345 const size_t length = bytes == 0 ? 8 : bytes;
346 const int prot = PROT_READ | PROT_WRITE;
347 const int flags = MAP_ANONYMOUS | MAP_PRIVATE;
348 *ptr = ::mmap(NULL, length, prot, flags, -1, 0);
349 if (*ptr == MAP_FAILED) { throw ::std::bad_alloc(); }
353 inline void MmuDealloc(
void *ptr,
const size_t bytes)
355 const size_t length = bytes == 0 ? 8 : bytes;
356 if (::munmap(ptr, length) == -1) {
mfem_error(
"Dealloc error!"); }
360 inline void MmuProtect(
const void *ptr,
const size_t bytes)
362 static const bool mmu_protect_error = getenv(
"MFEM_MMU_PROTECT_ERROR");
363 if (!::mprotect(const_cast<void*>(ptr), bytes, PROT_NONE)) {
return; }
364 if (mmu_protect_error) {
mfem_error(
"MMU protection (NONE) error"); }
368 inline void MmuAllow(
const void *ptr,
const size_t bytes)
370 const int RW = PROT_READ | PROT_WRITE;
371 static const bool mmu_protect_error = getenv(
"MFEM_MMU_PROTECT_ERROR");
372 if (!::mprotect(const_cast<void*>(ptr), bytes, RW)) {
return; }
373 if (mmu_protect_error) {
mfem_error(
"MMU protection (R/W) error"); }
376 inline void MmuInit() { }
377 inline void MmuAlloc(
void **ptr,
const size_t bytes) { *ptr = std::malloc(bytes); }
378 inline void MmuDealloc(
void *ptr,
const size_t) { std::free(ptr); }
379 inline void MmuProtect(
const void*,
const size_t) { }
380 inline void MmuAllow(
const void*,
const size_t) { }
381 inline const void *MmuAddrR(
const void *
a) {
return a; }
382 inline const void *MmuAddrP(
const void *
a) {
return a; }
383 inline uintptr_t MmuLengthR(
const void*,
const size_t) {
return 0; }
384 inline uintptr_t MmuLengthP(
const void*,
const size_t) {
return 0; }
388 class MmuHostMemorySpace :
public HostMemorySpace
391 MmuHostMemorySpace(): HostMemorySpace() { MmuInit(); }
392 void Alloc(
void **ptr,
size_t bytes) { MmuAlloc(ptr, bytes); }
393 void Dealloc(
void *ptr) { MmuDealloc(ptr, maps->memories.at(ptr).bytes); }
394 void Protect(
const Memory& mem,
size_t bytes)
395 {
if (mem.h_rw) { mem.h_rw =
false; MmuProtect(mem.h_ptr, bytes); } }
396 void Unprotect(
const Memory &mem,
size_t bytes)
397 {
if (!mem.h_rw) { mem.h_rw =
true; MmuAllow(mem.h_ptr, bytes); } }
399 void AliasProtect(
const void *ptr,
size_t bytes)
400 { MmuProtect(MmuAddrR(ptr), MmuLengthR(ptr, bytes)); }
402 void AliasUnprotect(
const void *ptr,
size_t bytes)
403 { MmuAllow(MmuAddrP(ptr), MmuLengthP(ptr, bytes)); }
407 class UvmHostMemorySpace :
public HostMemorySpace
410 UvmHostMemorySpace(): HostMemorySpace() { }
411 void Alloc(
void **ptr,
size_t bytes) {
CuMallocManaged(ptr, bytes == 0 ? 8 : bytes); }
412 void Dealloc(
void *ptr) {
CuMemFree(ptr); }
416 class NoDeviceMemorySpace:
public DeviceMemorySpace
419 void Alloc(internal::Memory&) {
mfem_error(
"! Device Alloc"); }
420 void Dealloc(Memory&) {
mfem_error(
"! Device Dealloc"); }
421 void *HtoD(
void*,
const void*,
size_t) {
mfem_error(
"!HtoD");
return nullptr; }
422 void *DtoD(
void*,
const void*,
size_t) {
mfem_error(
"!DtoD");
return nullptr; }
423 void *DtoH(
void*,
const void*,
size_t) {
mfem_error(
"!DtoH");
return nullptr; }
427 class StdDeviceMemorySpace :
public DeviceMemorySpace { };
430 class CudaDeviceMemorySpace:
public DeviceMemorySpace
433 CudaDeviceMemorySpace(): DeviceMemorySpace() { }
434 void Alloc(Memory &base) {
CuMemAlloc(&base.d_ptr, base.bytes); }
435 void Dealloc(Memory &base) {
CuMemFree(base.d_ptr); }
436 void *HtoD(
void *dst,
const void *src,
size_t bytes)
438 void *DtoD(
void* dst,
const void* src,
size_t bytes)
440 void *DtoH(
void *dst,
const void *src,
size_t bytes)
445 class HostPinnedMemorySpace:
public HostMemorySpace
448 HostPinnedMemorySpace(): HostMemorySpace() { }
449 void Alloc(
void ** ptr,
size_t bytes)
override 458 void Dealloc(
void *ptr)
override 470 class HipDeviceMemorySpace:
public DeviceMemorySpace
473 HipDeviceMemorySpace(): DeviceMemorySpace() { }
474 void Alloc(Memory &base) {
HipMemAlloc(&base.d_ptr, base.bytes); }
475 void Dealloc(Memory &base) {
HipMemFree(base.d_ptr); }
476 void *HtoD(
void *dst,
const void *src,
size_t bytes)
478 void *DtoD(
void* dst,
const void* src,
size_t bytes)
483 void *DtoH(
void *dst,
const void *src,
size_t bytes)
488 class UvmCudaMemorySpace :
public DeviceMemorySpace
491 void Alloc(Memory &base) { base.d_ptr = base.h_ptr; }
492 void Dealloc(Memory&) { }
493 void *HtoD(
void *dst,
const void *src,
size_t bytes)
495 if (dst == src) { MFEM_STREAM_SYNC;
return dst; }
498 void *DtoD(
void* dst,
const void* src,
size_t bytes)
500 void *DtoH(
void *dst,
const void *src,
size_t bytes)
502 if (dst == src) { MFEM_STREAM_SYNC;
return dst; }
508 class MmuDeviceMemorySpace :
public DeviceMemorySpace
511 MmuDeviceMemorySpace(): DeviceMemorySpace() { }
512 void Alloc(Memory &m) { MmuAlloc(&m.d_ptr, m.bytes); }
513 void Dealloc(Memory &m) { MmuDealloc(m.d_ptr, m.bytes); }
514 void Protect(
const Memory &m)
515 {
if (m.d_rw) { m.d_rw =
false; MmuProtect(m.d_ptr, m.bytes); } }
516 void Unprotect(
const Memory &m)
517 {
if (!m.d_rw) { m.d_rw =
true; MmuAllow(m.d_ptr, m.bytes); } }
519 void AliasProtect(
const void *ptr,
size_t bytes)
520 { MmuProtect(MmuAddrR(ptr), MmuLengthR(ptr, bytes)); }
522 void AliasUnprotect(
const void *ptr,
size_t bytes)
523 { MmuAllow(MmuAddrP(ptr), MmuLengthP(ptr, bytes)); }
524 void *HtoD(
void *dst,
const void *src,
size_t bytes)
525 {
return std::memcpy(dst, src, bytes); }
526 void *DtoD(
void *dst,
const void *src,
size_t bytes)
527 {
return std::memcpy(dst, src, bytes); }
528 void *DtoH(
void *dst,
const void *src,
size_t bytes)
529 {
return std::memcpy(dst, src, bytes); }
532 #ifdef MFEM_USE_UMPIRE 533 class UmpireMemorySpace
536 umpire::ResourceManager &rm;
537 umpire::Allocator allocator;
538 bool owns_allocator{
false};
542 virtual ~UmpireMemorySpace() {
if (owns_allocator) { allocator.release(); } }
543 UmpireMemorySpace(
const char * name,
const char *
space)
544 : rm(umpire::ResourceManager::getInstance())
546 if (!rm.isAllocator(name))
548 allocator = rm.makeAllocator<umpire::strategy::QuickPool>(
549 name, rm.getAllocator(
space));
550 owns_allocator =
true;
554 allocator = rm.getAllocator(name);
555 owns_allocator =
false;
561 class UmpireHostMemorySpace :
public HostMemorySpace,
public UmpireMemorySpace
564 umpire::strategy::AllocationStrategy *strat;
566 UmpireHostMemorySpace(
const char * name)
568 UmpireMemorySpace(name,
"HOST"),
569 strat(allocator.getAllocationStrategy()) {}
570 void Alloc(
void **ptr,
size_t bytes)
override 571 { *ptr = allocator.allocate(bytes); }
572 void Dealloc(
void *ptr)
override { allocator.deallocate(ptr); }
573 void Insert(
void *ptr,
size_t bytes)
574 { rm.registerAllocation(ptr, {ptr, bytes, strat}); }
578 #if defined(MFEM_USE_CUDA) || defined(MFEM_USE_HIP) 579 class UmpireDeviceMemorySpace :
public DeviceMemorySpace,
580 public UmpireMemorySpace
583 UmpireDeviceMemorySpace(
const char * name)
584 : DeviceMemorySpace(),
585 UmpireMemorySpace(name,
"DEVICE") {}
586 void Alloc(Memory &base)
override 587 { base.d_ptr = allocator.allocate(base.bytes); }
588 void Dealloc(Memory &base)
override { rm.deallocate(base.d_ptr); }
589 void *HtoD(
void *dst,
const void *src,
size_t bytes)
override 599 void *DtoD(
void* dst,
const void* src,
size_t bytes)
override 612 void *DtoH(
void *dst,
const void *src,
size_t bytes)
override 624 class UmpireDeviceMemorySpace :
public NoDeviceMemorySpace
627 UmpireDeviceMemorySpace(
const char * ) {}
629 #endif // MFEM_USE_CUDA || MFEM_USE_HIP 630 #endif // MFEM_USE_UMPIRE 642 Ctrl(): host{
nullptr}, device{
nullptr} { }
648 mfem_error(
"Memory backends have already been configured!");
654 host[
static_cast<int>(
MT::HOST)] =
new StdHostMemorySpace();
655 host[
static_cast<int>(
MT::HOST_32)] =
new Aligned32HostMemorySpace();
656 host[
static_cast<int>(
MT::HOST_64)] =
new Aligned64HostMemorySpace();
660 host[
static_cast<int>(
MT::MANAGED)] =
new UvmHostMemorySpace();
664 device[
static_cast<int>(
MT::MANAGED)-shift] =
new UvmCudaMemorySpace();
674 const int mt_i =
static_cast<int>(mt);
676 if (!host[mt_i]) { host[mt_i] = NewHostCtrl(mt); }
677 MFEM_ASSERT(host[mt_i],
"Host memory controller is not configured!");
681 DeviceMemorySpace* Device(
const MemoryType mt)
684 MFEM_ASSERT(mt_i >= 0,
"");
686 if (!device[mt_i]) { device[mt_i] = NewDeviceCtrl(mt); }
687 MFEM_ASSERT(device[mt_i],
"Memory manager has not been configured!");
696 for (
int mt = mt_d; mt <
MemoryTypeSize; mt++) {
delete device[mt-mt_d]; }
700 HostMemorySpace* NewHostCtrl(
const MemoryType mt)
705 #ifdef MFEM_USE_UMPIRE 707 return new UmpireHostMemorySpace(
713 default: MFEM_ABORT(
"Unknown host memory controller!");
718 DeviceMemorySpace* NewDeviceCtrl(
const MemoryType mt)
722 #ifdef MFEM_USE_UMPIRE 724 return new UmpireDeviceMemorySpace(
727 return new UmpireDeviceMemorySpace(
736 #if defined(MFEM_USE_CUDA) 737 return new CudaDeviceMemorySpace();
738 #elif defined(MFEM_USE_HIP) 739 return new HipDeviceMemorySpace();
741 MFEM_ABORT(
"No device memory controller!");
745 default: MFEM_ABORT(
"Unknown device memory controller!");
753 static internal::Ctrl *ctrl;
755 void *MemoryManager::New_(
void *h_tmp,
size_t bytes,
MemoryType mt,
758 MFEM_ASSERT(exists,
"Internal error!");
777 void *MemoryManager::New_(
void *h_tmp,
size_t bytes,
MemoryType h_mt,
781 MFEM_ASSERT(exists,
"Internal error!");
782 MFEM_ASSERT(
IsHostMemory(h_mt),
"h_mt must be host type");
785 "d_mt must be device type, the same is h_mt, or DEFAULT");
792 if (h_tmp ==
nullptr) { ctrl->Host(h_mt)->Alloc(&h_ptr, bytes); }
793 else { h_ptr = h_tmp; }
797 mm.Insert(h_ptr, bytes, h_mt, d_mt);
801 CheckHostMemoryType_(h_mt, h_ptr,
false);
806 void *MemoryManager::Register_(
void *ptr,
void *h_tmp,
size_t bytes,
808 bool own,
bool alias,
unsigned &flags)
810 MFEM_ASSERT(exists,
"Internal error!");
818 MFEM_VERIFY_TYPES(h_mt, d_mt);
820 if (ptr ==
nullptr && h_tmp ==
nullptr)
822 MFEM_VERIFY(bytes == 0,
"internal error");
826 MFEM_VERIFY(!alias,
"Cannot register an alias!");
834 mm.Insert(h_ptr, bytes, h_mt, d_mt);
835 flags = (own ? flags |
Mem::OWNS_HOST : flags & ~Mem::OWNS_HOST) |
840 MFEM_VERIFY(ptr || bytes == 0,
841 "cannot register NULL device pointer with bytes = " << bytes);
842 if (h_tmp ==
nullptr) { ctrl->Host(h_mt)->Alloc(&h_ptr, bytes); }
843 else { h_ptr = h_tmp; }
844 mm.InsertDevice(ptr, h_ptr, bytes, h_mt, d_mt);
848 CheckHostMemoryType_(h_mt, h_ptr, alias);
852 void MemoryManager::Register2_(
void *h_ptr,
void *d_ptr,
size_t bytes,
854 bool own,
bool alias,
unsigned &flags,
855 unsigned valid_flags)
857 MFEM_CONTRACT_VAR(alias);
858 MFEM_ASSERT(exists,
"Internal error!");
859 MFEM_ASSERT(!alias,
"Cannot register an alias!");
860 MFEM_VERIFY_TYPES(h_mt, d_mt);
862 if (h_ptr ==
nullptr && d_ptr ==
nullptr)
864 MFEM_VERIFY(bytes == 0,
"internal error");
870 MFEM_VERIFY(d_ptr || bytes == 0,
871 "cannot register NULL device pointer with bytes = " << bytes);
872 mm.InsertDevice(d_ptr, h_ptr, bytes, h_mt, d_mt);
877 CheckHostMemoryType_(h_mt, h_ptr, alias);
880 void MemoryManager::Alias_(
void *base_h_ptr,
size_t offset,
size_t bytes,
881 unsigned base_flags,
unsigned &flags)
883 mm.InsertAlias(base_h_ptr, (
char*)base_h_ptr + offset, bytes,
889 void MemoryManager::SetDeviceMemoryType_(
void *h_ptr,
unsigned flags,
892 MFEM_VERIFY(h_ptr,
"cannot set the device memory type: Memory is empty!");
895 auto mem_iter = maps->memories.find(h_ptr);
896 MFEM_VERIFY(mem_iter != maps->memories.end(),
"internal error");
897 internal::Memory &mem = mem_iter->second;
898 if (mem.d_mt == d_mt) {
return; }
899 MFEM_VERIFY(mem.d_ptr ==
nullptr,
"cannot set the device memory type:" 900 " device memory is allocated!");
905 auto alias_iter = maps->aliases.find(h_ptr);
906 MFEM_VERIFY(alias_iter != maps->aliases.end(),
"internal error");
907 internal::Alias &alias = alias_iter->second;
908 internal::Memory &base_mem = *alias.mem;
909 if (base_mem.d_mt == d_mt) {
return; }
910 MFEM_VERIFY(base_mem.d_ptr ==
nullptr,
911 "cannot set the device memory type:" 912 " alias' base device memory is allocated!");
913 base_mem.d_mt = d_mt;
917 void MemoryManager::Delete_(
void *h_ptr,
MemoryType h_mt,
unsigned flags)
924 MFEM_ASSERT(
IsHostMemory(h_mt),
"invalid h_mt = " << (
int)h_mt);
926 MFEM_ASSERT(!owns_device || owns_internal,
"invalid Memory state");
931 MFEM_ASSERT(registered || !(owns_host || owns_device || owns_internal) ||
932 (!(owns_device || owns_internal) && h_ptr ==
nullptr),
933 "invalid Memory state");
934 if (!
mm.exists || !registered) {
return; }
940 MFEM_ASSERT(h_mt == maps->aliases.at(h_ptr).h_mt,
"");
941 mm.EraseAlias(h_ptr);
947 { ctrl->Host(h_mt)->Dealloc(h_ptr); }
951 MFEM_ASSERT(h_mt == maps->memories.at(h_ptr).h_mt,
"");
952 mm.Erase(h_ptr, owns_device);
957 void MemoryManager::DeleteDevice_(
void *h_ptr,
unsigned & flags)
962 mm.EraseDevice(h_ptr);
967 bool MemoryManager::MemoryClassCheck_(
MemoryClass mc,
void *h_ptr,
973 MFEM_VERIFY(bytes == 0,
"Trying to access NULL with size " << bytes);
979 auto iter = maps->memories.find(h_ptr);
980 MFEM_VERIFY(iter != maps->memories.end(),
"internal error");
981 d_mt = iter->second.d_mt;
985 auto iter = maps->aliases.find(h_ptr);
986 MFEM_VERIFY(iter != maps->aliases.end(),
"internal error");
987 d_mt = iter->second.mem->d_mt;
1024 size_t bytes,
unsigned &flags)
1026 if (h_ptr) { CheckHostMemoryType_(h_mt, h_ptr, flags &
Mem::ALIAS); }
1028 MFEM_ASSERT(MemoryClassCheck_(mc, h_ptr, h_mt, bytes, flags),
"");
1034 {
return mm.GetAliasHostPtr(h_ptr, bytes, copy); }
1035 else {
return mm.GetHostPtr(h_ptr, bytes, copy); }
1042 {
return mm.GetAliasDevicePtr(h_ptr, bytes, copy); }
1043 else {
return mm.GetDevicePtr(h_ptr, bytes, copy); }
1048 size_t bytes,
unsigned &flags)
1050 if (h_ptr) { CheckHostMemoryType_(h_mt, h_ptr, flags &
Mem::ALIAS); }
1052 MFEM_ASSERT(MemoryClassCheck_(mc, h_ptr, h_mt, bytes, flags),
"");
1058 {
return mm.GetAliasHostPtr(h_ptr, bytes, copy); }
1059 else {
return mm.GetHostPtr(h_ptr, bytes, copy); }
1066 {
return mm.GetAliasDevicePtr(h_ptr, bytes, copy); }
1067 else {
return mm.GetDevicePtr(h_ptr, bytes, copy); }
1072 size_t bytes,
unsigned &flags)
1074 if (h_ptr) { CheckHostMemoryType_(h_mt, h_ptr, flags &
Mem::ALIAS); }
1076 MFEM_ASSERT(MemoryClassCheck_(mc, h_ptr, h_mt, bytes, flags),
"");
1081 {
return mm.GetAliasHostPtr(h_ptr, bytes,
false); }
1082 else {
return mm.GetHostPtr(h_ptr, bytes,
false); }
1088 {
return mm.GetAliasDevicePtr(h_ptr, bytes,
false); }
1089 else {
return mm.GetDevicePtr(h_ptr, bytes,
false); }
1093 void MemoryManager::SyncAlias_(
const void *base_h_ptr,
void *alias_h_ptr,
1094 size_t alias_bytes,
unsigned base_flags,
1095 unsigned &alias_flags)
1099 MFEM_ASSERT(alias_flags &
Mem::ALIAS,
"not an alias");
1102 mm.GetAliasHostPtr(alias_h_ptr, alias_bytes,
true);
1108 mm.InsertAlias(base_h_ptr, alias_h_ptr, alias_bytes, base_flags &
Mem::ALIAS);
1112 mm.GetAliasDevicePtr(alias_h_ptr, alias_bytes,
true);
1118 MemoryType MemoryManager::GetDeviceMemoryType_(
void *h_ptr,
bool alias)
1124 auto iter = maps->memories.find(h_ptr);
1125 MFEM_ASSERT(iter != maps->memories.end(),
"internal error");
1126 return iter->second.d_mt;
1129 auto iter = maps->aliases.find(h_ptr);
1130 MFEM_ASSERT(iter != maps->aliases.end(),
"internal error");
1131 return iter->second.mem->d_mt;
1133 MFEM_ABORT(
"internal error");
1134 return MemoryManager::host_mem_type;
1137 MemoryType MemoryManager::GetHostMemoryType_(
void *h_ptr)
1139 if (!
mm.exists) {
return MemoryManager::host_mem_type; }
1140 if (
mm.
IsKnown(h_ptr)) {
return maps->memories.at(h_ptr).h_mt; }
1141 if (
mm.
IsAlias(h_ptr)) {
return maps->aliases.at(h_ptr).h_mt; }
1142 return MemoryManager::host_mem_type;
1145 void MemoryManager::Copy_(
void *dst_h_ptr,
const void *src_h_ptr,
1146 size_t bytes,
unsigned src_flags,
1147 unsigned &dst_flags)
1157 const bool dst_on_host =
1162 dst_flags = dst_flags &
1165 const bool src_on_host =
1170 const void *src_d_ptr =
1171 src_on_host ? NULL :
1173 mm.GetAliasDevicePtr(src_h_ptr, bytes,
false) :
1174 mm.GetDevicePtr(src_h_ptr, bytes,
false));
1180 if (dst_h_ptr != src_h_ptr && bytes != 0)
1182 MFEM_ASSERT((
const char*)dst_h_ptr + bytes <= src_h_ptr ||
1183 (
const char*)src_h_ptr + bytes <= dst_h_ptr,
1185 std::memcpy(dst_h_ptr, src_h_ptr, bytes);
1190 if (dst_h_ptr != src_d_ptr && bytes != 0)
1192 internal::Memory &src_d_base = maps->memories.at(src_h_ptr);
1194 ctrl->Device(src_d_mt)->DtoH(dst_h_ptr, src_d_ptr, bytes);
1200 void *dest_d_ptr = (dst_flags &
Mem::ALIAS) ?
1201 mm.GetAliasDevicePtr(dst_h_ptr, bytes,
false) :
1202 mm.GetDevicePtr(dst_h_ptr, bytes,
false);
1205 const bool known =
mm.
IsKnown(dst_h_ptr);
1207 MFEM_VERIFY(alias||known,
"");
1209 maps->memories.at(dst_h_ptr).d_mt :
1210 maps->aliases.at(dst_h_ptr).mem->d_mt;
1211 ctrl->Device(d_mt)->HtoD(dest_d_ptr, src_h_ptr, bytes);
1215 if (dest_d_ptr != src_d_ptr && bytes != 0)
1217 const bool known =
mm.
IsKnown(dst_h_ptr);
1219 MFEM_VERIFY(alias||known,
"");
1221 maps->memories.at(dst_h_ptr).d_mt :
1222 maps->aliases.at(dst_h_ptr).mem->d_mt;
1223 ctrl->Device(d_mt)->DtoD(dest_d_ptr, src_d_ptr, bytes);
1229 void MemoryManager::CopyToHost_(
void *dest_h_ptr,
const void *src_h_ptr,
1230 size_t bytes,
unsigned src_flags)
1235 if (dest_h_ptr != src_h_ptr && bytes != 0)
1237 MFEM_ASSERT((
char*)dest_h_ptr + bytes <= src_h_ptr ||
1238 (
const char*)src_h_ptr + bytes <= dest_h_ptr,
1240 std::memcpy(dest_h_ptr, src_h_ptr, bytes);
1245 MFEM_ASSERT(IsKnown_(src_h_ptr),
"internal error");
1246 const void *src_d_ptr = (src_flags &
Mem::ALIAS) ?
1247 mm.GetAliasDevicePtr(src_h_ptr, bytes,
false) :
1248 mm.GetDevicePtr(src_h_ptr, bytes,
false);
1249 const internal::Memory &base = maps->memories.at(dest_h_ptr);
1251 ctrl->Device(d_mt)->DtoH(dest_h_ptr, src_d_ptr, bytes);
1255 void MemoryManager::CopyFromHost_(
void *dest_h_ptr,
const void *src_h_ptr,
1256 size_t bytes,
unsigned &dest_flags)
1261 if (dest_h_ptr != src_h_ptr && bytes != 0)
1263 MFEM_ASSERT((
char*)dest_h_ptr + bytes <= src_h_ptr ||
1264 (
const char*)src_h_ptr + bytes <= dest_h_ptr,
1266 std::memcpy(dest_h_ptr, src_h_ptr, bytes);
1271 void *dest_d_ptr = (dest_flags &
Mem::ALIAS) ?
1272 mm.GetAliasDevicePtr(dest_h_ptr, bytes,
false) :
1273 mm.GetDevicePtr(dest_h_ptr, bytes,
false);
1274 const internal::Memory &base = maps->memories.at(dest_h_ptr);
1276 ctrl->Device(d_mt)->HtoD(dest_d_ptr, src_h_ptr, bytes);
1278 dest_flags = dest_flags &
1282 bool MemoryManager::IsKnown_(
const void *h_ptr)
1284 return maps->memories.find(h_ptr) != maps->memories.end();
1287 bool MemoryManager::IsAlias_(
const void *h_ptr)
1289 return maps->aliases.find(h_ptr) != maps->aliases.end();
1292 void MemoryManager::Insert(
void *h_ptr,
size_t bytes,
1295 #ifdef MFEM_TRACK_MEM_MANAGER 1296 mfem::out <<
"[mfem memory manager]: registering h_ptr: " << h_ptr
1297 <<
", bytes: " << bytes << std::endl;
1301 MFEM_VERIFY(bytes == 0,
"Trying to add NULL with size " << bytes);
1304 MFEM_VERIFY_TYPES(h_mt, d_mt);
1308 maps->memories.emplace(h_ptr, internal::Memory(h_ptr, bytes, h_mt, d_mt));
1310 if (res.second ==
false)
1312 auto &m = res.first->second;
1313 MFEM_VERIFY(m.bytes >= bytes && m.h_mt == h_mt &&
1316 "Address already present with different attributes!");
1317 #ifdef MFEM_TRACK_MEM_MANAGER 1318 mfem::out <<
"[mfem memory manager]: repeated registration of h_ptr: " 1319 << h_ptr << std::endl;
1325 void MemoryManager::InsertDevice(
void *d_ptr,
void *h_ptr,
size_t bytes,
1329 MFEM_ASSERT(h_ptr != NULL,
"internal error");
1330 Insert(h_ptr, bytes, h_mt, d_mt);
1331 internal::Memory &mem = maps->memories.at(h_ptr);
1332 if (d_ptr == NULL && bytes != 0) { ctrl->Device(d_mt)->Alloc(mem); }
1333 else { mem.d_ptr = d_ptr; }
1336 void MemoryManager::InsertAlias(
const void *base_ptr,
void *alias_ptr,
1337 const size_t bytes,
const bool base_is_alias)
1339 size_t offset =
static_cast<size_t>(
static_cast<const char*
>(alias_ptr) -
1340 static_cast<const char*>(base_ptr));
1341 #ifdef MFEM_TRACK_MEM_MANAGER 1342 mfem::out <<
"[mfem memory manager]: registering alias of base_ptr: " 1343 << base_ptr <<
", offset: " << offset <<
", bytes: " << bytes
1344 <<
", base is alias: " << base_is_alias << std::endl;
1348 MFEM_VERIFY(offset == 0,
1349 "Trying to add alias to NULL at offset " << offset);
1354 const internal::Alias &alias = maps->aliases.at(base_ptr);
1355 MFEM_ASSERT(alias.mem,
"");
1356 base_ptr = alias.mem->h_ptr;
1357 offset += alias.offset;
1358 #ifdef MFEM_TRACK_MEM_MANAGER 1359 mfem::out <<
"[mfem memory manager]: real base_ptr: " << base_ptr
1363 internal::Memory &mem = maps->memories.at(base_ptr);
1364 MFEM_VERIFY(offset + bytes <= mem.bytes,
"invalid alias");
1366 maps->aliases.emplace(alias_ptr,
1367 internal::Alias{&mem, offset, 1, mem.h_mt});
1368 if (res.second ==
false)
1370 internal::Alias &alias = res.first->second;
1373 alias.offset = offset;
1374 alias.h_mt = mem.h_mt;
1379 void MemoryManager::Erase(
void *h_ptr,
bool free_dev_ptr)
1381 #ifdef MFEM_TRACK_MEM_MANAGER 1382 mfem::out <<
"[mfem memory manager]: un-registering h_ptr: " << h_ptr
1385 if (!h_ptr) {
return; }
1386 auto mem_map_iter = maps->memories.find(h_ptr);
1387 if (mem_map_iter == maps->memories.end()) {
mfem_error(
"Unknown pointer!"); }
1388 internal::Memory &mem = mem_map_iter->second;
1389 if (mem.d_ptr && free_dev_ptr) { ctrl->Device(mem.d_mt)->Dealloc(mem);}
1390 maps->memories.erase(mem_map_iter);
1393 void MemoryManager::EraseDevice(
void *h_ptr)
1395 if (!h_ptr) {
return; }
1396 auto mem_map_iter = maps->memories.find(h_ptr);
1397 if (mem_map_iter == maps->memories.end()) {
mfem_error(
"Unknown pointer!"); }
1398 internal::Memory &mem = mem_map_iter->second;
1399 if (mem.d_ptr) { ctrl->Device(mem.d_mt)->Dealloc(mem);}
1400 mem.d_ptr =
nullptr;
1403 void MemoryManager::EraseAlias(
void *alias_ptr)
1405 #ifdef MFEM_TRACK_MEM_MANAGER 1406 mfem::out <<
"[mfem memory manager]: un-registering alias_ptr: " << alias_ptr
1409 if (!alias_ptr) {
return; }
1410 auto alias_map_iter = maps->aliases.find(alias_ptr);
1411 if (alias_map_iter == maps->aliases.end()) {
mfem_error(
"Unknown alias!"); }
1412 internal::Alias &alias = alias_map_iter->second;
1413 if (--alias.counter) {
return; }
1414 maps->aliases.erase(alias_map_iter);
1417 void *MemoryManager::GetDevicePtr(
const void *h_ptr,
size_t bytes,
1422 MFEM_VERIFY(bytes == 0,
"Trying to access NULL with size " << bytes);
1425 internal::Memory &mem = maps->memories.at(h_ptr);
1428 MFEM_VERIFY_TYPES(h_mt, d_mt);
1432 if (mem.bytes) { ctrl->Device(d_mt)->Alloc(mem); }
1435 if (mem.d_ptr) { ctrl->Device(d_mt)->Unprotect(mem); }
1438 MFEM_ASSERT(bytes <= mem.bytes,
"invalid copy size");
1439 if (bytes) { ctrl->Device(d_mt)->HtoD(mem.d_ptr, h_ptr, bytes); }
1441 ctrl->Host(h_mt)->Protect(mem, bytes);
1445 void *MemoryManager::GetAliasDevicePtr(
const void *alias_ptr,
size_t bytes,
1450 MFEM_VERIFY(bytes == 0,
"Trying to access NULL with size " << bytes);
1453 auto &alias_map = maps->aliases;
1454 auto alias_map_iter = alias_map.find(alias_ptr);
1455 if (alias_map_iter == alias_map.end()) {
mfem_error(
"alias not found"); }
1456 const internal::Alias &alias = alias_map_iter->second;
1457 const size_t offset = alias.offset;
1458 internal::Memory &mem = *alias.mem;
1461 MFEM_VERIFY_TYPES(h_mt, d_mt);
1465 if (mem.bytes) { ctrl->Device(d_mt)->Alloc(mem); }
1467 void *alias_h_ptr =
static_cast<char*
>(mem.h_ptr) + offset;
1468 void *alias_d_ptr =
static_cast<char*
>(mem.d_ptr) + offset;
1469 MFEM_ASSERT(alias_h_ptr == alias_ptr,
"internal error");
1470 MFEM_ASSERT(offset + bytes <= mem.bytes,
"internal error");
1471 mem.d_rw = mem.h_rw =
false;
1472 if (mem.d_ptr) { ctrl->Device(d_mt)->AliasUnprotect(alias_d_ptr, bytes); }
1473 ctrl->Host(h_mt)->AliasUnprotect(alias_ptr, bytes);
1474 if (copy && mem.d_ptr)
1475 { ctrl->Device(d_mt)->HtoD(alias_d_ptr, alias_h_ptr, bytes); }
1476 ctrl->Host(h_mt)->AliasProtect(alias_ptr, bytes);
1480 void *MemoryManager::GetHostPtr(
const void *ptr,
size_t bytes,
bool copy)
1482 const internal::Memory &mem = maps->memories.at(ptr);
1483 MFEM_ASSERT(mem.h_ptr == ptr,
"internal error");
1484 MFEM_ASSERT(bytes <= mem.bytes,
"internal error")
1487 MFEM_VERIFY_TYPES(h_mt, d_mt);
1489 ctrl->Host(h_mt)->Unprotect(mem, bytes);
1490 if (mem.d_ptr) { ctrl->Device(d_mt)->Unprotect(mem); }
1491 if (copy && mem.d_ptr) { ctrl->Device(d_mt)->DtoH(mem.h_ptr, mem.d_ptr, bytes); }
1492 if (mem.d_ptr) { ctrl->Device(d_mt)->Protect(mem); }
1496 void *MemoryManager::GetAliasHostPtr(
const void *ptr,
size_t bytes,
1499 const internal::Alias &alias = maps->aliases.at(ptr);
1500 const internal::Memory *
const mem = alias.mem;
1503 MFEM_VERIFY_TYPES(h_mt, d_mt);
1504 void *alias_h_ptr =
static_cast<char*
>(mem->h_ptr) + alias.offset;
1505 void *alias_d_ptr = static_cast<char*>(mem->d_ptr) + alias.offset;
1506 MFEM_ASSERT(alias_h_ptr == ptr,
"internal error");
1508 ctrl->Host(h_mt)->AliasUnprotect(alias_h_ptr, bytes);
1509 if (mem->d_ptr) { ctrl->Device(d_mt)->AliasUnprotect(alias_d_ptr, bytes); }
1510 if (copy_data && mem->d_ptr)
1511 { ctrl->Device(d_mt)->DtoH(const_cast<void*>(ptr), alias_d_ptr, bytes); }
1512 if (mem->d_ptr) { ctrl->Device(d_mt)->AliasProtect(alias_d_ptr, bytes); }
1518 if (exists) {
return; }
1519 maps =
new internal::Maps();
1520 ctrl =
new internal::Ctrl();
1531 MFEM_VERIFY(!configured,
"changing the dual MemoryTypes is not allowed after" 1532 " MemoryManager configuration!");
1533 UpdateDualMemoryType(mt, dual_mt);
1539 "invalid MemoryType, mt = " << (
int)mt);
1541 "invalid dual MemoryType, dual_mt = " << (
int)dual_mt);
1546 dual_map[(int)mt] = dual_mt;
1554 "invalid (mt, dual_mt) pair: (" 1563 MemoryManager::UpdateDualMemoryType(host_mt, device_mt);
1564 MemoryManager::UpdateDualMemoryType(device_mt, host_mt);
1569 MemoryManager::UpdateDualMemoryType(
1574 host_mem_type = host_mt;
1575 device_mem_type = device_mt;
1581 MFEM_VERIFY(exists,
"MemoryManager has already been destroyed!");
1582 #ifdef MFEM_TRACK_MEM_MANAGER 1583 size_t num_memories = maps->memories.size();
1584 size_t num_aliases = maps->aliases.size();
1585 if (num_memories != 0 || num_aliases != 0)
1587 MFEM_WARNING(
"...\n\t number of registered pointers: " << num_memories
1588 <<
"\n\t number of registered aliases : " << num_aliases);
1593 mfem::out <<
"Destroying the MemoryManager ...\n" 1594 <<
"remaining registered pointers : " 1595 << maps->memories.size() <<
'\n' 1596 <<
"remaining registered aliases : " 1597 << maps->aliases.size() <<
'\n';
1599 for (
auto& n : maps->memories)
1601 internal::Memory &mem = n.second;
1603 if (mem_h_ptr) { ctrl->Host(mem.h_mt)->Dealloc(mem.h_ptr); }
1604 if (mem.d_ptr) { ctrl->Device(mem.d_mt)->Dealloc(mem); }
1606 delete maps; maps =
nullptr;
1607 delete ctrl; ctrl =
nullptr;
1628 for (
const auto& n : maps->memories)
1630 const internal::Memory &mem = n.second;
1631 os <<
"\nkey " << n.first <<
", " 1632 <<
"h_ptr " << mem.h_ptr <<
", " 1633 <<
"d_ptr " << mem.d_ptr;
1636 if (maps->memories.size() > 0) { os << std::endl; }
1643 for (
const auto& n : maps->aliases)
1645 const internal::Alias &alias = n.second;
1646 os <<
"\nalias: key " << n.first <<
", " 1647 <<
"h_ptr " << alias.mem->h_ptr <<
", " 1648 <<
"offset " << alias.offset <<
", " 1649 <<
"counter " << alias.counter;
1652 if (maps->aliases.size() > 0) { os << std::endl; }
1656 int MemoryManager::CompareHostAndDevice_(
void *h_ptr,
size_t size,
1660 mm.GetAliasDevicePtr(h_ptr, size,
false) :
1661 mm.GetDevicePtr(h_ptr, size,
false);
1662 char *h_buf =
new char[size];
1663 #if defined(MFEM_USE_CUDA) 1665 #elif defined(MFEM_USE_HIP) 1668 std::memcpy(h_buf, d_ptr, size);
1670 int res = std::memcmp(h_ptr, h_buf, size);
1680 <<
"\n registered = " << bool(flags & Mem::Registered)
1681 <<
"\n owns host = " << bool(flags & Mem::OWNS_HOST)
1682 <<
"\n owns device = " << bool(flags & Mem::OWNS_DEVICE)
1683 <<
"\n owns internal = " << bool(flags & Mem::OWNS_INTERNAL)
1684 <<
"\n valid host = " << bool(flags & Mem::VALID_HOST)
1685 <<
"\n valid device = " << bool(flags & Mem::VALID_DEVICE)
1686 <<
"\n device flag = " << bool(flags & Mem::USE_DEVICE)
1687 <<
"\n alias = " << bool(flags & Mem::ALIAS)
1691 void MemoryManager::CheckHostMemoryType_(
MemoryType h_mt,
void *h_ptr,
1694 if (!
mm.exists) {
return;}
1697 auto it = maps->memories.find(h_ptr);
1698 MFEM_VERIFY(it != maps->memories.end(),
1699 "host pointer is not registered: h_ptr = " << h_ptr);
1700 MFEM_VERIFY(h_mt == it->second.h_mt,
"host pointer MemoryType mismatch");
1704 auto it = maps->aliases.find(h_ptr);
1705 MFEM_VERIFY(it != maps->aliases.end(),
1706 "alias pointer is not registered: h_ptr = " << h_ptr);
1707 MFEM_VERIFY(h_mt == it->second.h_mt,
"alias pointer MemoryType mismatch");
1713 bool MemoryManager::exists =
false;
1714 bool MemoryManager::configured =
false;
1734 #ifdef MFEM_USE_UMPIRE 1735 const char * MemoryManager::h_umpire_name =
"MFEM_HOST";
1736 const char * MemoryManager::d_umpire_name =
"MFEM_DEVICE";
1737 const char * MemoryManager::d_umpire_2_name =
"MFEM_DEVICE_2";
1743 "host-std",
"host-32",
"host-64",
"host-debug",
"host-umpire",
"host-pinned",
1744 #if defined(MFEM_USE_CUDA) 1747 #elif defined(MFEM_USE_HIP) 1755 #if defined(MFEM_USE_CUDA) 1758 #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.
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.
void * CuMemFreeHostPinned(void *ptr)
Frees page-locked (pinned) host memory and returns destination ptr.
static const char * GetUmpireHostAllocatorName()
Get the host Umpire allocator name used with MemoryType::HOST_UMPIRE.
static MemoryType GetHostMemoryType()
Host memory; allocated from a "host-debug" pool.
MemoryManager mm
The (single) global memory manager object.
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)
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 * HipMemcpyDtoDAsync(void *dst, const void *src, size_t bytes)
Copies memory from Device to Device.
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.
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.
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.
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.
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.
Host memory; using new[] and delete[].
void * HipMemcpyHtoD(void *dst, const void *src, size_t bytes)
Copies memory from Host to Device.
void PrintFlags() const
Print the internal flags.
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.
constexpr int DeviceMemoryTypeSize
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().