Using a Naming Shim with IPC Shared Memory¶
A name is required in order to allocate memory with IPC Shared Memory Allocators. However, using a unique name for each allocator can get tricky, especially when dealing with many MPI tasks and in an integrated code set-up.
Thus, the umpire::strategy::NamingShim strategy was created to make it a bit
easier to set up and use the IPC Shared Memory Allocator.
The NamingShim allows you to call allocate with only 1 argument for the size in bytes.
In other words, it allows you to allocate from shared mem without providing a name.
Note
Why the word “shim”? In software development, a “shim” refers to a small piece of code that bridges the gap between two different APIs, frameworks, or libraries. It’s primary purpose is to provide a consistent interface or behavior while hiding the underlying differences. Since this strategy acts as a shim to hide the requirement of a unique name from the user, we call it the NamingShim.
Below is a complete example of using the NamingShim with the IPC Shared Memory Allocator.
//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and Umpire
// project contributors. See the COPYRIGHT file for details.
//
// SPDX-License-Identifier: (MIT)
//////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include "umpire/Allocator.hpp"
#include "umpire/ResourceManager.hpp"
#include "umpire/Umpire.hpp"
#include "umpire/config.hpp"
#include "umpire/resource/HostSharedMemoryResource.hpp"
#include "umpire/strategy/NamingShim.hpp"
#include "umpire/util/MemoryResourceTraits.hpp"
int main(int, char**)
{
auto& rm = umpire::ResourceManager::getInstance();
auto traits{umpire::get_default_resource_traits("SHARED")};
traits.size = 1 * 1024 * 1024; // Maximum size of this Allocator
traits.scope = umpire::MemoryResourceTraits::shared_scope::node; // default
auto node_allocator{rm.makeResource("SHARED::node_allocator", traits)};
auto shim{rm.makeAllocator<umpire::strategy::NamingShim>("shim", node_allocator)};
void* ptr = shim.allocate(1024);
std::cout << "Ptr = " << ptr << std::endl;
std::cout << "Total Memory Allocated: " << umpire::get_total_bytes_allocated() << std::endl;
shim.deallocate(ptr);
}