10template <
typename Tag,
typename Group,
typename T>
11inline constexpr void trmm(
const Group& group,
16 const int row_extent = operand.
c.
rows();
17 const int col_extent = operand.
c.
cols();
22 for (
int row_step = 0; row_step < row_extent; ++row_step) {
23 const int row = effective_lower ? (row_extent - 1 - row_step) : row_step;
24 for (
int col = 0; col < col_extent; ++col) {
26 for (
int k = local_id; k < contract_extent; k += local_size) {
38 for (
int col_step = 0; col_step < col_extent; ++col_step) {
39 const int col = effective_lower ? col_step : (col_extent - 1 - col_step);
40 for (
int row = 0; row < row_extent; ++row) {
42 for (
int k = local_id; k < contract_extent; k += local_size) {
57template <
typename Item,
typename T>
58inline constexpr void trmm(
const Item& item,
62 const auto sg = item.get_sub_group();
67 const int row_extent = operand.
c.
rows();
68 const int col_extent = operand.
c.
cols();
72 const int col_tiles = (col_extent + sg_size - 1) / sg_size;
73 const int row_tiles = (row_extent + rows_per_sg - 1) / rows_per_sg;
75 for (
int linear_tile = sg_id; linear_tile < row_tiles * col_tiles; linear_tile += total_sg) {
76 const int tile_row = linear_tile / col_tiles;
77 const int tile_col = linear_tile % col_tiles;
78 const int base_row = tile_row * rows_per_sg;
79 const int base_col = tile_col * sg_size;
80 const int col = base_col + lane;
81 std::array<T, detail::subgroup::kMaxMatrixRowsPerSubgroup> partials{};
82 std::array<int, detail::subgroup::kMaxMatrixRowsPerSubgroup> begins{};
83 std::array<int, detail::subgroup::kMaxMatrixRowsPerSubgroup> ends{};
84 const int col_begin = transform.
side ==
Side::Right && col < col_extent ?
92 for (
int row_offset = 0; row_offset < rows_per_sg; ++row_offset) {
93 const int row = base_row + row_offset;
94 if (row >= row_extent) {
102 for (
int k_base = 0; k_base < contract_extent; k_base += tile_k) {
103 const int tile_extent = std::min(tile_k, contract_extent - k_base);
106 for (
int tile_offset = 0; tile_offset < tile_extent; ++tile_offset) {
107 const int k = k_base + tile_offset;
108 const T b_value = col < col_extent ? operand.
b(k, col) : T(0);
109 for (
int row_offset = 0; row_offset < rows_per_sg; ++row_offset) {
110 const int row = base_row + row_offset;
111 if (row >= row_extent || col >= col_extent) {
114 if (k < begins[
static_cast<std::size_t
>(row_offset)] || k >= ends[
static_cast<std::size_t
>(row_offset)]) {
119 partials[
static_cast<std::size_t
>(row_offset)] += a_value * b_value;
123 for (
int tile_offset = 0; tile_offset < tile_extent; ++tile_offset) {
124 const int k = k_base + tile_offset;
125 if (k < col_begin || k >= col_end) {
129 for (
int row_offset = 0; row_offset < rows_per_sg; ++row_offset) {
130 const int row = base_row + row_offset;
131 const T b_lane = row < row_extent && lane == row_offset ? operand.
b(row, k) : T(0);
133 if (row >= row_extent || col >= col_extent) {
136 partials[
static_cast<std::size_t
>(row_offset)] += b_value * a_value;
142 if (col < col_extent) {
143 for (
int row_offset = 0; row_offset < rows_per_sg; ++row_offset) {
144 const int row = base_row + row_offset;
145 if (row >= row_extent) {
154template <
typename Item,
typename T>
164 const int row_extent = operand.
c.
rows();
165 const int col_extent = operand.
c.
cols();
173 for (
int tile_row = tile_row_start; tile_row < row_tiles; tile_row += tile_row_stride) {
174 for (
int tile_col = tile_col_start; tile_col < col_tiles; tile_col += tile_col_stride) {
192 if (tile_count > 0) {
193 auto lhs_loader = [&](
int tile_r,
int global_k) {
195 if (global_row >= row_extent) {
200 operand.
b(global_row, global_k);
202 auto rhs_loader = [&](
int tile_c,
int global_k) {
204 if (global_col >= col_extent) {
208 operand.
b(global_k, global_col) :
224 sycl::group_barrier(item.get_group());
226 for (
int tile_idx = 0; tile_idx < tile_count; ++tile_idx) {
227 const int next_tile_idx = tile_idx + 1;
229 const int current_tile_extent = std::min(
kRegisterMatrixTileK, tile_contract_end - current_k_base);
233 if (next_tile_idx < tile_count) {
262 if (next_tile_idx < tile_count) {
266 sycl::group_barrier(item.get_group());
268 sycl::group_barrier(item.get_sub_group());
282 sycl::group_barrier(item.get_group());
296template <
typename Tag, DeviceBlasPolicy Policy,
typename T>
300 bool aliased =
false) {
301 assert(row_extent >= 0 && col_extent >= 0 &&
"device::trmm workspace query expects non-negative matrix extents");
306 const int contract_extent = Tag::side ==
Side::Left ? row_extent : col_extent;
313template <
typename Tag, DeviceBlasPolicy Policy,
typename Exec,
typename T>
317 T* workspace =
nullptr) {
318 const TriangularTransform transform{.side = Tag::side, .uplo = Tag::uplo, .trans = Tag::trans, .diag = Tag::diag};
323 const int row_extent = operand.
c.
rows();
324 const int col_extent = operand.
c.
cols();
327 if (!aliased && register_workspace !=
nullptr &&
329 std::same_as<std::remove_cvref_t<Exec>, sycl::nd_item<3>>) {
371inline constexpr void trmm(
const Group& group,
374 T* workspace =
nullptr) {
386inline constexpr void trmm(
const Group& group,
389 T* workspace =
nullptr) {
413 bool aliased =
false) {
433 bool aliased =
false) {
444inline constexpr void trmm(
const Group& group,
450 T* workspace =
nullptr) {
462inline constexpr void trmm(
const Group& group,
468 T* workspace =
nullptr) {
469 trmm<Policy, SideV, UploV, TransV, DiagV>(group, a,
make_matmat_operand(b, c, alpha, beta), workspace);
Policy
Synchronous or asynchronous execution policy.
constexpr std::size_t trmm_workspace_elements(const DeviceBlasLaunchInfo &launch, int row_extent, int col_extent, bool aliased=false)
Local memory, in elements of T, that trmm() can use for this launch and shape.
constexpr MatrixMatrixOperand< T > make_matmat_operand(const KernelMatrixView< T, MatrixFormat::Dense > &b, const KernelMatrixView< T, MatrixFormat::Dense > &c, T alpha=T(1), T beta=T(0))
Builds a MatrixMatrixOperand.
DeviceBlasPolicy
Which implementation family a device BLAS call may use.
constexpr void trmm(const Group &group, const KernelMatrixView< T, MatrixFormat::Dense > &a, MatrixMatrixOperand< T > operand, T *workspace=nullptr)
Triangular matrix-matrix product (Left) or (Right).
@ Auto
any eligible path; the sub-group fast paths accept sub-group size 16 or 32
Transpose
The operator op() applied to an operand: op(A) = A, A^T or A^H.
Diag
Whether a triangular operand's diagonal is read or assumed to be one.
Uplo
Which triangle of a symmetric, Hermitian or triangular operand is referenced.
Side
Side on which a special operand multiplies: op(A) * B or B * op(A).
@ NonUnit
The stored diagonal is used.
@ Upper
The upper triangle (i <= j).
@ Lower
The lower triangle (i >= j).
@ Right
The special operand is on the right.
@ Left
The special operand is on the left.
T select_from_group(Group g, T x, Id id)
sycl::select_from_group for any trivially copyable T. Collective.
constexpr void trmm(const Group &group, const KernelMatrixView< T, MatrixFormat::Dense > &a, MatrixMatrixOperand< T > operand)
constexpr bool can_use_matrix_fast_path(const Item &item, int row_extent, int col_extent, int contract_extent, DeviceBlasPolicy policy)
constexpr void trmm(const Item &item, const KernelMatrixView< T, MatrixFormat::Dense > &a, MatrixMatrixOperand< T > operand, TriangularTransform transform)
constexpr int triangular_begin(int index, int extent, TriangularTransform transform, Side side)
constexpr int kRegisterMatrixTileN
constexpr int triangular_end(int index, int extent, TriangularTransform transform, Side side)
constexpr int subgroup_group_id(const Item &item)
constexpr int kRegisterMatrixTileK
constexpr int matrix_tile_group_row(const Item &)
constexpr int kRegisterMatrixLocalCols
constexpr void trmm_register_tiled(const Item &item, const KernelMatrixView< T, MatrixFormat::Dense > &a, MatrixMatrixOperand< T > operand, TriangularTransform transform, RegisterMatrixWorkspace< T > *workspace)
constexpr int subgroup_size(const Item &item)
constexpr int kRegisterMatrixRhsStages
constexpr int matrix_tile_group_col(const Item &)
constexpr int matrix_rows_per_subgroup(int row_extent, int total_sg, int sg_size, int contract_extent, Side side)
constexpr void write_register_matrix_tile(MatrixMatrixOperand< T > operand, int row_base, int col_base, int row_extent, int col_extent, const RegisterMatrixAccumTile< T > &accum)
constexpr int kRegisterMatrixThreadTileRows
constexpr void load_register_matrix_stage(const Item &item, RegisterMatrixWorkspace< T > *workspace, int linear_tid, int subgroup_id, int lhs_stage, int rhs_stage, bool load_lhs, bool load_rhs, int k_base, int tile_extent, LhsLoader &&lhs_loader, RhsLoader &&rhs_loader)
constexpr int matrix_tile_k(int contract_extent, int sg_size, Side side)
constexpr int matrix_tile_group_row_stride(const Item &)
constexpr int matrix_tile_group_col_stride(const Item &)
constexpr int register_matrix_rhs_stage(int tile_idx)
constexpr int register_matrix_lhs_stage(int tile_idx)
constexpr bool can_use_matrix_register_fast_path(const Item &item, int row_extent, int col_extent, int contract_extent, DeviceBlasPolicy policy)
constexpr int kRegisterMatrixTileM
constexpr int subgroup_local_id(const Item &item)
constexpr int triangular_tile_end(int row_base, int row_extent, int col_base, int col_extent, int contract_extent, TriangularTransform transform)
constexpr void accumulate_register_matrix_stage(const Item &item, const RegisterMatrixWorkspace< T > *workspace, int subgroup_id, int lhs_stage, int rhs_stage, int local_row, int local_col, int tile_extent, RegisterMatrixAccumTile< T > &accum)
constexpr int triangular_tile_begin(int row_base, int row_extent, int col_base, int col_extent, int contract_extent, TriangularTransform transform)
constexpr bool is_nd_item_3d_launch(const Exec &)
constexpr int subgroup_count(const Item &item)
constexpr int kRegisterMatrixThreadTileCols
constexpr void dispatch_trmm(const Exec &exec, const KernelMatrixView< T, MatrixFormat::Dense > &a, MatrixMatrixOperand< T > operand, T *workspace=nullptr)
constexpr std::size_t trmm_workspace_elements(const DeviceBlasLaunchInfo &launch, int row_extent, int col_extent, bool aliased=false)
constexpr bool views_overlap(const VectorView< T > &lhs, const VectorView< T > &rhs)
constexpr void write_matrix_output(const MatrixMatrixOperand< T > &operand, int row, int col, const T &value)
constexpr int group_local_linear_id(const Group &group)
constexpr T triangular_matrix_entry(const KernelMatrixView< T, MatrixFormat::Dense > &a, int row, int col)
constexpr int group_local_linear_range(const Group &group)
constexpr Workspace * workspace_ptr_cast(T *workspace)
constexpr T reduce_sum_group(const Group &group, const T &value)
constexpr int item_local_linear_id(const Item &item)
constexpr std::size_t workspace_elements_v
constexpr void validate_triangular_operand(const KernelMatrixView< T, MatrixFormat::Dense > &a, const MatrixVectorOperand< T > &operand, TriangularTransform transform)
constexpr bool group_is_leader(const Group &group)
Trivially copyable view of a MatrixView for use inside a SYCL kernel.
auto rows() const
Row count (the capacity on a heterogeneous batch).
auto cols() const
Column count (the capacity on a heterogeneous batch).
Host-side description of a launch, for the *_workspace_elements queries.
Operands of a matrix-matrix operation: .
KernelMatrixView< T, MatrixFormat::Dense > c
output matrix; read (scaled by beta) and overwritten
KernelMatrixView< T, MatrixFormat::Dense > b
second input matrix