Gromacs
2018.8
|
#include <gromacs/gpu_utils/hostallocator.h>
Policy class for configuring gmx::Allocator, to manage allocations of memory that may be needed for e.g. GPU transfers.
This allocator has state, so is most useful in cases where it is not known at compile time whether the allocated memory will be transferred to some device. It will increase the size of containers that use it. If the GROMACS build is configured with CUDA support, then memory will be allocated with PageAlignedAllocator, and that page pinned to physical memory if the pinning mode has been activated. If pinning mode is deactivated, or the GROMACS build does not support CUDA, then the memory will be allocated with AlignedAllocator. The pin() and unpin() methods work with the CUDA build, and silently do nothing otherwise. In future, we may modify or generalize this to work differently in other cases.
The intended use is to configure gmx::Allocator with this class as its policy class, and then to use e.g. std::vector::get_allocator().getPolicy() to control whether the allocation policy should activate its pinning mode. The policy object can also be used to explicitly pin() and unpin() the buffer when it is using PinningPolicy::CanBePinned. The policy object is returned by value (as required by the C++ standard for get_allocator(), which copies a std::shared_ptr, so the policy object should be retrieved sparingly, e.g. only upon resize of the allocation. (Normal operation of the vector, e.g. during resize, incurs only the cost of the pointer indirection needed to consult the current state of the allocation policy.)
Classes | |
class | Impl |
Private implementation class. More... | |
Public Types | |
using | propagate_on_container_copy_assignment = std::true_type |
Specify an allocator trait so that the stateful allocator should propagate. | |
using | propagate_on_container_move_assignment = std::true_type |
Specify an allocator trait so that the stateful allocator should propagate. | |
using | propagate_on_container_swap = std::true_type |
Specify an allocator trait so that the stateful allocator should propagate. | |
Public Member Functions | |
HostAllocationPolicy () | |
Default constructor. | |
std::size_t | alignment () |
Return the alignment size currently used by the active pinning policy. | |
void * | malloc (std::size_t bytes) const noexcept |
Allocate and perhaps pin page-aligned memory suitable for e.g. GPU transfers. More... | |
void | free (void *buffer) const noexcept |
Free the memory, after unpinning (if appropriate). More... | |
void | pin () const noexcept |
Pin the allocation to physical memory, if appropriate. More... | |
void | unpin () const noexcept |
Unpin the allocation, if appropriate. More... | |
PinningPolicy | pinningPolicy () const |
Return the current pinning policy (which is semi-independent of whether the buffer is actually pinned). More... | |
Friends | |
template<class T > | |
void | changePinningPolicy (HostVector< T > *v, PinningPolicy pinningPolicy) |
Declare as a friend function the only supported way to change the pinning policy. More... | |
|
noexcept |
Free the memory, after unpinning (if appropriate).
buffer | Memory pointer previously returned from gmx::HostAllocationPolicy::malloc() |
Does not throw.
|
noexcept |
Allocate and perhaps pin page-aligned memory suitable for e.g. GPU transfers.
Before attempting to allocate, unpin() is called. After a successful allocation, pin() is called. (Whether these do things depends on the PinningPolicy that is in effect.)
bytes | Amount of memory (bytes) to allocate. It is valid to ask for 0 bytes, which will return a non-null pointer that is properly aligned and padded (but that you should not use). |
Does not throw.
|
noexcept |
Pin the allocation to physical memory, if appropriate.
If the allocation policy is not in pinning mode, or the allocation is empty, ot the allocation is already pinned, then do nothing.
Does not throw.
PinningPolicy gmx::HostAllocationPolicy::pinningPolicy | ( | ) | const |
Return the current pinning policy (which is semi-independent of whether the buffer is actually pinned).
Does not throw.
|
noexcept |
Unpin the allocation, if appropriate.
Regardless of the allocation policy, unpin the memory if previously pinned, otherwise do nothing.
Does not throw.
|
friend |
Declare as a friend function the only supported way to change the pinning policy.
When the pinning policy changes, we want the state of the allocation to match the new policy. However, that requires a copy and swap of the buffers, which can only take place at the level of the container. So we wrap the required operations in a helper friend function.
Of course, if there is no allocation because the vector is empty, then nothing will change.
If the vector has contents, then a full reallocation and buffer copy are needed if the policy change requires tighter restrictions, and desirable even if the policy change requires looser restrictions. That cost is OK, because GROMACS will do this operation very rarely (e.g. when auto-tuning and deciding to switch whether a task will run on a GPU, or not).