Skip to content

Full GPU support for axom::Array#695

Merged
joshessman-llnl merged 22 commits intodevelopfrom
feature/essman/gpu_array
Nov 9, 2021
Merged

Full GPU support for axom::Array#695
joshessman-llnl merged 22 commits intodevelopfrom
feature/essman/gpu_array

Conversation

@joshessman-llnl
Copy link
Member

@joshessman-llnl joshessman-llnl commented Oct 27, 2021

Summary

  • This PR is a feature
  • It does the following:
    • Extends Array and in particular ArrayView to run on the GPU
    • Adds a MemorySpace parameter to allow users to optionally lock down the memory space of an Array at compile-time

Remaining tasks (non-exhaustive):

  • Multidim indexing/tests
  • Documentation updates

New docs:
https://axom.readthedocs.io/en/feature-essman-gpu_array/axom/core/docs/sphinx/core_containers.html#using-arrays-in-gpu-code

@joshessman-llnl joshessman-llnl added the Core Issues related to Axom's 'core' component label Oct 27, 2021
@joshessman-llnl joshessman-llnl mentioned this pull request Oct 27, 2021
20 tasks
@publixsubfan publixsubfan mentioned this pull request Oct 28, 2021
7 tasks
@joshessman-llnl joshessman-llnl changed the title WIP: Full GPU support for axom::Array Full GPU support for axom::Array Nov 2, 2021
Copy link
Member

@agcapps agcapps left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very good, Josh. I had a few questions, one of which (mismatch of memory space template parameter with constructor-specified allocator) may need more documentation or testing. I think I'm ready to approve once you've clarified those things.

Comment on lines +29 to +31
* This abstraction is not implemented using Umpire's MemoryResourceType enum
* in order to also include a "Dynamic" option as a default template parameter
* for Array-like types
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this note!

@agcapps
Copy link
Member

agcapps commented Nov 3, 2021

And thank you for the link to the branch's docs on readthedocs. That is very helpful when reviewing documentation.

Co-authored-by: Arlie Capps <48997041+agcapps@users.noreply.github.com>
* \brief Exchanges the contents of this Array with the other.
*/
void swap(Array<T, DIM>& other);
void swap(Array<T, DIM, SPACE>& other);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be extended to accept Array other from other memory spaces as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add a swap function between memory spaces but I'd be curious to hear what some use cases might be for this - in the general case you'd have to copy both sets of data between memory spaces, so I think the only thing you'd really be swapping are the housekeeping/metadata variables.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be useful for memory spaces that are compatible.
E.g. a Dynamic space that happens to be device memory (via umpire) and a Device space ?

: ArrayBase<T, DIM, Array<T, DIM, SPACE>>(
static_cast<const ArrayBase<T, DIM, Array<T, DIM, SPACE>>&>(other))
, m_allocator_id(SPACE == MemorySpace::Dynamic
? allocator_id
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if allocator_id is from the correct memory space, but a different pool?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an Umpire expert by any means but I believe in this case we'd have to do some introspection on the allocator to try to track down its "parent allocator"?

Copy link
Member

@kennyweiss kennyweiss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @joshessman-llnl -- this is really nice and highly anticipated!

Please see my comments for some minor suggestions/corrections.

Comment on lines +138 to +155
#ifdef AXOM_USE_UMPIRE
// If we have Umpire, we can try and see what space the pointer is allocated in
// Probably not worth checking this if SPACE != Dynamic, we *could* error out
// if e.g., the user gives a host pointer to ArrayView<T, DIM, Device>, but even
// Thrust doesn't guard against this.

// FIXME: Is it worth trying to get rid of this at compile time?
// (using a workaround since we don't have "if constexpr")
if(SPACE == MemorySpace::Dynamic)
{
auto& rm = umpire::ResourceManager::getInstance();
if(rm.hasAllocator(data))
{
auto alloc = rm.getAllocator(data);
m_allocator_id = alloc.getId();
}
}
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible suggestion: Would it make sense to fold this into the getAllocatorID function for <SPACE == Dynamic> ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm probably missing something but I'm not clear on how getAllocatorID comes into play here - were you envisioning an overload getAllocatorID(T* ptr) that encapsulates the pointer introspection?

// _iteration_end
}

#ifdef __CUDACC__
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heads-up @bmhan12 -- we'll want to extend this example to support hip

/// \brief Translates between the MemorySpace enum and Umpire allocator IDs
template <MemorySpace SPACE>
inline int getAllocatorID();

Copy link
Member

@kennyweiss kennyweiss Nov 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor (optional): It might be useful to have a utility function of the form:

bool areSpacesCompatible(MemorySpace space1, MemorySpace space2);

And possibly also:

#ifdef AXOM_USE_UMPIRE
bool areSpacesCompatible(MemorySpace SPACE, int allocatorID);
#endif

Copy link
Member Author

@joshessman-llnl joshessman-llnl Nov 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can understand the utility of the second function (in particular, relating to @kanye-quest's comment about pooled allocators and also converting/swapping from Dynamic -> another space) but I'm not sure where/how the first one would be used.

@rhornung67 rhornung67 added this to the Feb 2022 Release milestone Nov 8, 2021
blt_add_executable(
NAME ${exe_name}_cuda_on_ex
blt_add_executable(
NAME core_acceleration_cuda_on_ex
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch...

@joshessman-llnl joshessman-llnl force-pushed the feature/essman/gpu_array branch from 21c5f45 to 37f6409 Compare November 9, 2021 13:16
@joshessman-llnl joshessman-llnl merged commit 3999cf2 into develop Nov 9, 2021
@joshessman-llnl joshessman-llnl deleted the feature/essman/gpu_array branch November 9, 2021 14:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Core Issues related to Axom's 'core' component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants