Getting Started

This page provides information on how to quickly get up and running with Umpire.

Installation

Umpire is hosted on GitHub here. To clone the repo into your local working space, type:

$ git clone --recursive https://github.com/LLNL/Umpire.git

The --recursive argument is required to ensure that the BLT submodule is also checked out. BLT is the build system we use for Umpire.

Building Umpire

Umpire uses CMake and BLT to handle builds. Make sure that you have a modern compiler loaded and the configuration is as simple as:

$ mkdir build && cd build
$ cmake ../

By default, Umpire will only support host memory. Additional backends for device support can be enabled using the options detailed in Advanced Configuration. CMake will provide output about which compiler is being used and the values of other options. Once CMake has completed, Umpire can be built with Make:

$ make

For more advanced configuration options, see Advanced Configuration.

Installing Umpire

To install Umpire, just run:

$ make install

Umpire install files to the lib, include and bin directories of the CMAKE_INSTALL_PREFIX. Additionally, Umpire installs a CMake configuration file that can help you use Umpire in other projects. By setting umpire_DIR to point to the root of your Umpire installation, you can call find_package(umpire) inside your CMake project and Umpire will be automatically detected and available for use.

Basic Usage

Let’s take a quick tour through Umpire’s most important features. A complete listing you can compile is included at the bottom of the page. First, let’s grab an Allocator and allocate some memory. This is the interface through which you will want to access data:

auto& rm = umpire::ResourceManager::getInstance();
umpire::Allocator allocator = rm.getAllocator("HOST");

float* my_data = static_cast<float*>(allocator.allocate(100*sizeof(float));

This code grabs the default allocator for the host memory, and uses it to allocate an array of 100 floats. We can ask for different Allocators to allocate memory in different places. Let’s ask for a device allocator:

umpire::Allocator device_allocator = rm.getAllocator("DEVICE");

float* my_data_device = static_cast<float*>(device_allocator.allocate(100*sizeof(float));

This code gets the default device allocator, and uses it to allocate an array of 100 floats. Remember, since this is a device pointer, there is no guarantee you will be able to access it on the host. Luckily, Umpire’s ResourceManager can copy one pointer to another transparently. Let’s copy the data from our first pointer to the DEVICE-allocated pointer.

rm.copy(my_data, my_data_device);

To free any memory allocated, you can use the deallocate function of the Allocator, or the ResourceManager. Asking the ResourceManager to deallocate memory is slower, but useful if you don’t know how or where an allocation was made:

allocator.deallocate(my_data); // deallocate using Allocator
rm.deallocate(my_data_device); // deallocate using ResourceManager