cuda::resource_ref
: a type-constrained resource wrapper
With the property design depicted in cuda::get_property, a library has flexibility in checking constraints and querying custom properties. However, there is also a cost in providing function templates for a potentially wide range of inputs. Depending on the number of different memory resources, both compile time and binary size might increase considerably.
The type-erased resource_ref
and async_resource_ref
resource wrappers aid in efficiently coalescing such APIs
into a single function.
void* do_allocate_async(cuda::mr::async_resource_ref<> resource, std::size_t size, std::size_t align, cuda::stream_ref stream) {
return resource.allocate_async(size, align, stream);
}
my_async_memory_resource resource;
my_async_memory_resource* pointer_to_resource = &resource;
void* from_reference = do_allocate_async(resource, 1337, 256, cuda::stream_ref{});
void* from_ptr = do_allocate_async(pointer_to_resource, 1337, 256, cuda::stream_ref{});
Note that do_allocate_async
is not a template anymore but a plain old function. The wrapper
cuda::mr::{async_}resource_ref<>
is constructible from any non-const reference or pointer to a memory resource that
satisfies cuda::mr::{async_}resource
.
Properties may also be passed to cuda::mr::{async_}resource_ref
just as with cuda::mr::resource_with
.
struct required_alignment{};
void* do_allocate_async_with_alignment(cuda::mr::async_resource_ref<required_alignment> resource, std::size_t size, cuda::stream_ref stream) {
return resource.allocate_async(size, cuda::mr::get_property(resource, required_alignment), stream);
}
However, the type erasure comes with the cost that arbitrary properties cannot be queried:
struct required_alignment{};
void* buggy_allocate_async_with_alignment(cuda::mr::async_resource_ref<> resource, std::size_t size, cuda::stream_ref stream) {
if constexpr (cuda::has_property<required_alignment>) { // BUG: This will always be false
return resource.allocate_async(size, cuda::mr::get_property(resource, required_alignment), stream);
} else {
return resource.allocate_async(size, my_default_alignment, stream);
}
}
So, choose wisely. If your library has a well-defined set of fixed properties that you expect to always be available,
then cuda::mr::{async_}resource_ref
is an amazing tool to improve compile times and binary size. If you need a
flexible interface then constraining through cuda::mr::{async_}resource_with
is the proper solution.