Introspection¶
When writing code to run on computers with a complex memory hierarchy, one of the most difficult things can be keeping track of where each pointer has been allocated. Umpire’s instrospection capability keeps track of this information, as well as other useful bits and pieces you might want to know.
The umpire::ResourceManager
can be used to find the allocator
associated with an address:
auto found_allocator = rm.getAllocator(data);
Once you have this, it’s easy to query things like the name of the Allocator or
find out the associated umpire::Platform
, which can help
you decide where to operate on this data:
std::cout << "According to the ResourceManager, the Allocator used is " << found_allocator.getName()
<< ", which has the Platform " << static_cast<int>(found_allocator.getPlatform()) << std::endl;
You can also find out how big the allocation is, in case you forgot:
std::cout << "The size of the allocation is << " << found_allocator.getSize(data) << std::endl;
Remember that these functions will work on any allocation made using an
Allocator or umpire::TypedAllocator
.
//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-23, Lawrence Livermore National Security, LLC and Umpire
// project contributors. See the COPYRIGHT file for details.
//
// SPDX-License-Identifier: (MIT)
//////////////////////////////////////////////////////////////////////////////
#include "umpire/Allocator.hpp"
#include "umpire/ResourceManager.hpp"
int main(int, char**)
{
constexpr std::size_t SIZE = 1024;
auto& rm = umpire::ResourceManager::getInstance();
const std::string destinations[] = {
"HOST"
#if defined(UMPIRE_ENABLE_DEVICE)
,
"DEVICE"
#endif
#if defined(UMPIRE_ENABLE_UM)
,
"UM"
#endif
#if defined(UMPIRE_ENABLE_PINNED)
,
"PINNED"
#endif
};
for (auto& destination : destinations) {
auto allocator = rm.getAllocator(destination);
double* data = static_cast<double*>(allocator.allocate(SIZE * sizeof(double)));
std::cout << "Allocated " << (SIZE * sizeof(double)) << " bytes using the " << allocator.getName() << " allocator."
<< std::endl;
// _sphinx_tag_tut_getallocator_start
auto found_allocator = rm.getAllocator(data);
// _sphinx_tag_tut_getallocator_end
// _sphinx_tag_tut_getinfo_start
std::cout << "According to the ResourceManager, the Allocator used is " << found_allocator.getName()
<< ", which has the Platform " << static_cast<int>(found_allocator.getPlatform()) << std::endl;
// _sphinx_tag_tut_getinfo_end
// _sphinx_tag_tut_getsize_start
std::cout << "The size of the allocation is << " << found_allocator.getSize(data) << std::endl;
// _sphinx_tag_tut_getsize_end
allocator.deallocate(data);
}
return 0;
}