host/device/managed
mdspan
and accessors
Host, device, and managed mdspan
allow to express multi-dimensional views of the respective CUDA memory spaces as vocabulary types and prevent potential errors.
Types and Traits
template <typename Accessor>
using host_accessor;
template <typename Accessor>
using device_accessor;
template <typename Accessor>
using managed_accessor;
Alias types to create accessors tailored for the host, device, or managed memory spaces.
template <typename ElementType,
typename Extents,
typename LayoutPolicy = cuda::std::layout_right,
typename AccessorPolicy = cuda::std::default_accessor<_ElementType>>
using host_mdspan = cuda::std::mdspan<ElementType, Extents, LayoutPolicy, host_accessor<AccessorPolicy>>;
template <typename ElementType,
typename Extents,
typename LayoutPolicy = cuda::std::layout_right,
typename AccessorPolicy = cuda::std::default_accessor<_ElementType>>
using device_mdspan = cuda::std::mdspan<ElementType, Extents, LayoutPolicy, device_accessor<AccessorPolicy>>;
template <typename ElementType,
typename Extents,
typename LayoutPolicy = cuda::std::layout_right,
typename AccessorPolicy = cuda::std::default_accessor<_ElementType>>
using managed_mdspan = cuda::std::mdspan<ElementType, Extents, LayoutPolicy, managed_accessor<AccessorPolicy>>;
Alias types to create mdspan
with host, device, or managed accessors.
template <typename T>
inline constexpr bool is_host_accessor_v = /* true if T is a host accessor, false otherwise */
template <typename T>
inline constexpr bool is_device_accessor_v = /* true if T is a device accessor, false otherwise */
template <typename T>
inline constexpr bool is_managed_accessor_v = /* true if T is a managed accessor, false otherwise */
template <typename T>
inline constexpr bool is_host_accessible_v = /* true if T is a mdspan/accessor accessible from the host, false otherwise */
template <typename T>
inline constexpr bool is_device_accessible_v = /* true if T is a mdspan/accessor accessible from the device, false otherwise */
Features
Memory spaces
Host, device, and managed mdspan
can be created and “sliced” (cuda::std::submdspan
) on any memory space. However, access to a specific memory space is restricted to the respective accessor type.
|
Host memory |
Device memory |
---|---|---|
|
Allowed |
Compile error |
|
Compile error |
Allowed |
|
Allowed * |
Allowed * |
* the validity of the managed memory space is checked at run-time in debug mode (host-side).
Conversions
|
|
|
|
---|---|---|---|
|
Allowed |
Compile error |
Compile error |
|
Compile error |
Allowed |
Compile error |
|
Allowed |
Allowed |
Allowed |
Other mdspan |
Allowed |
Allowed |
Allowed |
Note: the conversion is explicit
if the base accessor is not directly convertible.
Example 1
cuda::host_mdspan
and cuda::device_mdspan
usage:
#include <cuda/mdspan>
using dim = cuda::std::dims<1>;
__global__ void kernel_d(cuda::device_mdspan<int, dim> md) {
md[0] = 0;
}
__global__ void kernel_h(cuda::host_mdspan<int, dim> md) {
// md[0] = 0; // compile error
}
__host__ void host_function_h(cuda::host_mdspan<int, dim> md) {
md[0] = 0;
}
__host__ void host_function_d(cuda::device_mdspan<int, dim> md) {
// md[0] = 0; // compile error
}
__host__ void host_function_m(cuda::managed_mdspan<int, dim> md) {
md[0] = 0;
}
int main() {
int* d_ptr;
cudaMalloc(&d_ptr, 4 * sizeof(int));
int h_ptr[4];
cuda::host_mdspan h_md{h_ptr};
cuda::device_mdspan d_md{d_ptr, 4};
kernel_d<<<1, 1>>>(d_md); // ok
// kernel_d<<<1, 1>>>(h_md); // compile error
host_function_h(h_md); // ok
host_function_d(h_md); // compile error
// host_function_m(h_md); // compile error
cudaFree(d_ptr);
}
Example 2
cuda::managed_mdspan
usage:
#include <cuda/mdspan>
using dim = cuda::std::dims<1>;
__global__ void kernel_d(cuda::device_mdspan<int, dim> md) {
md[0] = 0;
}
__host__ void host_function_h(cuda::host_mdspan<int, dim> md) {
md[0] = 0;
}
int main() {
int* m_ptr;
cudaMallocManaged(&m_ptr, 4 * sizeof(int));
cuda::managed_mdspan m_md{m_ptr, 4};
kernel_d<<<1, 1>>>(m_md); // ok
host_function_h(m_md); // ok
cuda::managed_mdspan m_md2{d_ptr, 4};
m_md2[0]; // run-time error
cudaFree(d_ptr);
}
Example 3
Conversion from other accessors:
#include <cuda/mdspan>
using dim = cuda::std::dims<1>;
int main() {
using cuda::std::layout_right;
using cuda::std::aligned_accessor;
int h_ptr[4];
cuda::std::mdspan md{h_ptr};
cuda::host_mdspan h_md = md; // ok
cuda::std::mdspan<int, dim, layout_right, aligned_accessor<int, 8>> md_a{h_ptr, 4};
// cuda::host_mdspan h_md = md_a; // compile-error
cuda::host_mdspan h_md{md_a}; // ok
}