Tile

The ct::tile type represents an immutable multi-dimensional array of scalars with a statically known shape. Tiles have value semantics.

Example

The following code builds a tile containing the following elements:

\[\begin{split}\begin{pmatrix} 0 & 1 \\ 2 & 3 \end{pmatrix}\end{split}\]

The tile can be copied and the two copies remain independent. There is typically no performance overhead for copying tiles even if the tile contains a large number of elements.

namespace ct = ::cuda::tiles;
using i32x2x2 = ct::tile<int, ct::shape<2, 2>>;

auto x = ct::iota<i32x2x2>();

// Performs a deep copy of 'x' to 'y'.
auto y = x;

cuda::tiles::tile

template<ct::scalar E, ct::tile_shape S>
struct tile final;

A specializations \(T\) of ct::tile satisfies the following requirements:

  • std::copyable<T> 1

  • std::is_nothrow_move_constructible_v<T> 2

  • std::is_nothrow_move_assignable_v<T> 2

  • std::is_nothrow_swappable_v<T> 2

All specializations of ct::tile are trivially copyable. 3

The object size of a specialization ct::tile<E, S> is the product of the object size of \(E\) and the shape size of \(S\). The alignment of ct::tile<E, S> is the alignment of \(E\).

The program is ill-formed if \(E\) or \(S\) are cv-qualified.

The values of a tile are the possible combinations of the values of \(E\) that may be arranged into a shape specified by \(S\). The value representation of the tile (for example, the in memory arrangement of elements) is unspecified.

Exposition Only Member

unsigned char __data[/* see below */];

For the purposes of defining the implicitly generated special member functions, the tile type contains an exposition only member __data. The number of elements of __data and its alignment are equal to the object size and alignment of the tile as specified in ct::tile.

Unless constructed through the default constructor, objects 4 of type \(E\) exist in the storage of __data and such objects are appropriately copied, moved or destroyed when the relevant special member function is invoked.

Member Aliases

using shape_type = S;

Indicates the tile shape of \(T\).

using element_type = E;

Indicates the element type of \(T\).

using rank_type = typename S::rank_type;

Indicates type used for indexing the dimensions of \(T\).

using index_type = typename S::index_type;

Indicates the index_type of the tile shape \(S\).

Default Constructor

tile() = default;

Constructs an instance of \(T\) whose elements are uninitialized. The only valid operation on the constructed object is destruction or overwrite by copy or move assignment. All other operations generate undefined behavior.

Conversions from Tile Like

template<ct::tile_like O>
requires ct::tile_convertible_to<O, tile>
__tile__ explicit(!ct::non_narrowing_tile_convertible_to<O, tile>) tile(O other) noexcept;

Constructs an instance of \(T\) from a tile like object other which is tile convertible to \(T\). The constructed tile’s value is the value produced by the (possibly narrowing) tile conversion of other to \(T\).

Example

In the following example, the first tile is constructed from a scalar and the second tile is constructed from the conversion of another tile.

namespace ct = ::cuda::tiles;
ct::tile<int, ct::shape<>> x{2};

auto y = ct::full<ct::tile<int, ct::shape<4, 4>>>(2);

// Tile conversion from integers to floats
ct::tile<float, ct::shape<4, 4>> z{y};

Construction from a Constant Array CUDA 13.5

template<ct::scalar SrcE, size_t N0>
requires ct::scalar_convertible_to<SrcE, E> && /* atomic constraint */
__tile__ explicit(!ct::non_narrowing_scalar_convertible_to<SrcE, E>) consteval tile(const SrcE (&values)[N0]) noexcept;
template<ct::scalar SrcE, size_t N0, size_t N1>
requires ct::scalar_convertible_to<SrcE, E> && /* atomic constraint */
__tile__ explicit(!ct::non_narrowing_scalar_convertible_to<SrcE, E>) consteval tile(const SrcE (&values)[N0][N1]) noexcept;
template<ct::scalar SrcE, size_t N0, size_t N1, size_t N2>
requires ct::scalar_convertible_to<SrcE, E> && /* atomic constraint */
__tile__ explicit(!ct::non_narrowing_scalar_convertible_to<SrcE, E>) consteval tile(const SrcE (&values)[N0][N1][N2]) noexcept;
template<ct::scalar SrcE, size_t N0, size_t N1, size_t N2, size_t N3>
requires ct::scalar_convertible_to<SrcE, E> && /* atomic constraint */
__tile__ explicit(!ct::non_narrowing_scalar_convertible_to<SrcE, E>) consteval tile(const SrcE (&values)[N0][N1][N2][N3]) noexcept;
template<ct::scalar SrcE, size_t N0, size_t N1, size_t N2, size_t N3, size_t N4>
requires ct::scalar_convertible_to<SrcE, E> && /* atomic constraint */
__tile__ explicit(!ct::non_narrowing_scalar_convertible_to<SrcE, E>) consteval tile(const SrcE (&values)[N0][N1][N2][N3][N4]) noexcept;

Constructs an instance of \(T\) from a braced list of compile-time constant scalar values; one overload is provided for each rank in the inclusive range \([1, 5]\), taking an \(r\)-dimensional array whose nesting matches the rank of \(S\). The element of the constructed tile at index \((i_0, \ldots, i_{r-1})\) is the scalar conversion of values[i0]...[ir-1] to the element type \(E\). The constructor is explicit when that conversion is narrowing, so a narrowing source is accepted in direct-initialization but rejected in copy-initialization.

The atomic constraint validates that \(E\) is not a pointer type and that the extents N0, ..., Nr-1 of values equal the extents of \(S\) in order.

Because the constructor is consteval, every value in values shall be a constant expression; a tile whose elements depend on runtime state cannot be constructed with this constructor.

Example

The following example constructs a rank-1 tile and a rank-2 tile from braced lists of compile-time constant values, including a tile whose element type differs from that of the source values.

namespace ct = ::cuda::tiles;
// A rank-1 tile built from a braced list of compile-time constant values.
ct::tile<int, ct::shape<4>> v({1, 2, 3, 4});

// The nested braces of a rank-2 tile match its shape.
ct::tile<float, ct::shape<2, 2>> m({{0.0f, 1.0f}, {2.0f, 3.0f}});

// Each source value is converted to the element type. A narrowing source
// (here int -> signed char) is accepted in direct-initialization.
ct::tile<signed char, ct::shape<4>> b({1, 2, 3, 4});

Conversions to Scalars

template<ct::scalar O>
requires ct::scalar_convertible_to<E, O> && /* atomic constraint */
__tile__ explicit(!ct::non_narrowing_scalar_convertible_to<E, O>) operator O() noexcept;

Converts the singleton tiles \(T\) to the scalar type \(O\). The value of the resulting object is the scalar conversion of the unique element of the source tile. The atomic constraint validates that the tile size of \(T\) is \(1\).

Example

The following example converts a two dimensional singleton tile to a scalar of differing element type.

namespace ct = ::cuda::tiles;
using f32x1x1 = ct::tile<float, ct::shape<1, 1>>;
f32x1x1 x = ct::full<f32x1x1>(2.0f);

double y{x}; // Performs scalar conversion

Deduction Guide

template<ct::scalar O>
tile(O) -> tile<remove-cv-t<O>, ct::shape<>>;

Deduction guide which enables CTAD from scalar arguments.

Example

The following example invokes the tile conversion constructor to produce a tile of type ct::tile<int, ct::shape<>>.

namespace ct = ::cuda::tiles;
ct::tile x{2};
template<ct::scalar E, size_t N0>
tile(const E (&)[N0]) -> tile<remove-cv-t<E>, ct::shape<N0>>;
template<ct::scalar E, size_t N0, size_t N1>
tile(const E (&)[N0][N1]) -> tile<remove-cv-t<E>, ct::shape<N0, N1>>;
template<ct::scalar E, size_t N0, size_t N1, size_t N2>
tile(const E (&)[N0][N1][N2]) -> tile<remove-cv-t<E>, ct::shape<N0, N1, N2>>;
template<ct::scalar E, size_t N0, size_t N1, size_t N2, size_t N3>
tile(const E (&)[N0][N1][N2][N3]) -> tile<remove-cv-t<E>, ct::shape<N0, N1, N2, N3>>;
template<ct::scalar E, size_t N0, size_t N1, size_t N2, size_t N3, size_t N4>
tile(const E (&)[N0][N1][N2][N3][N4]) -> tile<remove-cv-t<E>, ct::shape<N0, N1, N2, N3, N4>>;

CUDA 13.5 Deduction guides which enable CTAD from a (possibly nested) constant array argument, one per rank in the inclusive range \([1, 5]\). The extents of the array become the extents of the deduced tile shape in order, so a nested braced list produces a multi-dimensional tile.

Example

The following example uses CTAD to produce a tile of type ct::tile<int, ct::shape<2, 4>> from a nested braced list.

namespace ct = ::cuda::tiles;
// The outer braced list has 2 elements and each inner list has 4, so CTAD
// deduces ct::tile<int, ct::shape<2, 4>> (2 rows of 4 columns).
ct::tile x({{0, 1, 2, 3}, {10, 11, 12, 13}});

Footnotes

1

See § 18.6 [concepts.object] of ISO/IEC 14882:2024

2(1,2,3)

See § 21.3.3 [meta.type.synop] of ISO/IEC 14882:2024

3

See § 6.8.1 [basic.types.general] of ISO/IEC 14882:2024

4

See § 6.7.2 [intro.object] of ISO/IEC 14882:2024