10template <
typename Tag,
typename Group,
typename T>
11inline constexpr void symm(
const Group& group,
16 const int row_extent = operand.
c.
rows();
17 const int col_extent = operand.
c.
cols();
20 for (
int col = 0; col < col_extent; ++col) {
21 for (
int row = 0; row < row_extent; ++row) {
23 for (
int k = local_id; k < contract_extent; k += local_size) {
42template <
typename Item,
typename T>
43inline constexpr void symm(
const Item& item,
47 const auto sg = item.get_sub_group();
52 const int row_extent = operand.
c.
rows();
53 const int col_extent = operand.
c.
cols();
57 const int col_tiles = (col_extent + sg_size - 1) / sg_size;
58 const int row_tiles = (row_extent + rows_per_sg - 1) / rows_per_sg;
60 for (
int linear_tile = sg_id; linear_tile < row_tiles * col_tiles; linear_tile += total_sg) {
61 const int tile_row = linear_tile / col_tiles;
62 const int tile_col = linear_tile % col_tiles;
63 const int base_row = tile_row * rows_per_sg;
64 const int base_col = tile_col * sg_size;
65 const int col = base_col + lane;
66 std::array<T, detail::subgroup::kMaxMatrixRowsPerSubgroup> partials{};
68 for (
int k_base = 0; k_base < contract_extent; k_base += tile_k) {
69 const int tile_extent = std::min(tile_k, contract_extent - k_base);
72 for (
int tile_offset = 0; tile_offset < tile_extent; ++tile_offset) {
73 const int k = k_base + tile_offset;
74 const T b_value = col < col_extent ? operand.
b(k, col) : T(0);
75 for (
int row_offset = 0; row_offset < rows_per_sg; ++row_offset) {
76 const int row = base_row + row_offset;
77 if (row >= row_extent || col >= col_extent) {
82 partials[
static_cast<std::size_t
>(row_offset)] += a_value * b_value;
86 for (
int tile_offset = 0; tile_offset < tile_extent; ++tile_offset) {
87 const int k = k_base + tile_offset;
89 for (
int row_offset = 0; row_offset < rows_per_sg; ++row_offset) {
90 const int row = base_row + row_offset;
91 const T b_lane = row < row_extent && lane == row_offset ? operand.
b(row, k) : T(0);
93 if (row >= row_extent || col >= col_extent) {
96 partials[
static_cast<std::size_t
>(row_offset)] += b_value * a_value;
102 if (col < col_extent) {
103 for (
int row_offset = 0; row_offset < rows_per_sg; ++row_offset) {
104 const int row = base_row + row_offset;
105 if (row >= row_extent) {
114template <
typename Item,
typename T>
124 const int row_extent = operand.
c.
rows();
125 const int col_extent = operand.
c.
cols();
133 for (
int tile_row = tile_row_start; tile_row < row_tiles; tile_row += tile_row_stride) {
134 for (
int tile_col = tile_col_start; tile_col < col_tiles; tile_col += tile_col_stride) {
140 if (tile_count > 0) {
141 auto lhs_loader = [&](
int tile_r,
int global_k) {
143 if (global_row >= row_extent) {
148 operand.
b(global_row, global_k);
150 auto rhs_loader = [&](
int tile_c,
int global_k) {
152 if (global_col >= col_extent) {
156 operand.
b(global_k, global_col) :
172 sycl::group_barrier(item.get_group());
174 for (
int tile_idx = 0; tile_idx < tile_count; ++tile_idx) {
176 const int current_tile_extent = std::min(
kRegisterMatrixTileK, contract_extent - current_k_base);
177 const int next_tile_idx = tile_idx + 1;
181 if (next_tile_idx < tile_count) {
210 if (next_tile_idx < tile_count) {
214 sycl::group_barrier(item.get_group());
216 sycl::group_barrier(item.get_sub_group());
230 sycl::group_barrier(item.get_group());
244template <
typename Tag, DeviceBlasPolicy Policy,
typename T>
248 assert(row_extent >= 0 && col_extent >= 0 &&
"device::symm workspace query expects non-negative matrix extents");
253 const int contract_extent = Tag::side ==
Side::Left ? row_extent : col_extent;
260template <
typename Tag, DeviceBlasPolicy Policy,
typename Exec,
typename T>
264 T* workspace =
nullptr) {
265 const SymmetricTransform transform{.side = Tag::side, .uplo = Tag::uplo, .hermitian = Tag::hermitian};
269 const int row_extent = operand.
c.
rows();
270 const int col_extent = operand.
c.
cols();
273 if (register_workspace !=
nullptr &&
275 std::same_as<std::remove_cvref_t<Exec>, sycl::nd_item<3>>) {
306template <S
ide S
ideV = S
ide::Left, Uplo UploV = Uplo::Upper,
typename Group,
typename T>
307inline constexpr void symm(
const Group& group,
310 T* workspace =
nullptr) {
320inline constexpr void symm(
const Group& group,
323 T* workspace =
nullptr) {
333template <
typename T, S
ide S
ideV = S
ide::Left, Uplo UploV = Uplo::Upper>
346template <
typename T, DeviceBlasPolicy Policy, S
ide S
ideV = S
ide::Left, Uplo UploV = Uplo::Upper>
354template <S
ide S
ideV = S
ide::Left, Uplo UploV = Uplo::Upper,
typename Group,
typename T>
355inline constexpr void symm(
const Group& group,
361 T* workspace =
nullptr) {
371inline constexpr void symm(
const Group& group,
377 T* workspace =
nullptr) {
Policy
Synchronous or asynchronous execution policy.
constexpr std::size_t symm_workspace_elements(const DeviceBlasLaunchInfo &launch, int row_extent, int col_extent)
Local memory, in elements of T, that symm() can use; 0 means pass nullptr.
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 symm(const Group &group, const KernelMatrixView< T, MatrixFormat::Dense > &a, MatrixMatrixOperand< T > operand, T *workspace=nullptr)
Symmetric matrix-matrix product (Left) or (Right), reading only the UploV triangle of A.
@ Auto
any eligible path; the sub-group fast paths accept sub-group size 16 or 32
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).
@ Upper
The upper triangle (i <= j).
@ 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 symm(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 int kRegisterMatrixTileN
constexpr int subgroup_group_id(const Item &item)
constexpr int kRegisterMatrixTileK
constexpr int matrix_tile_group_row(const Item &)
constexpr int kRegisterMatrixLocalCols
constexpr void symm(const Item &item, const KernelMatrixView< T, MatrixFormat::Dense > &a, MatrixMatrixOperand< T > operand, SymmetricTransform transform)
constexpr int subgroup_size(const Item &item)
constexpr int kRegisterMatrixRhsStages
constexpr void symm_register_tiled(const Item &item, const KernelMatrixView< T, MatrixFormat::Dense > &a, MatrixMatrixOperand< T > operand, SymmetricTransform transform, RegisterMatrixWorkspace< T > *workspace)
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 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 bool is_nd_item_3d_launch(const Exec &)
constexpr int subgroup_count(const Item &item)
constexpr int kRegisterMatrixThreadTileCols
constexpr void write_matrix_output(const MatrixMatrixOperand< T > &operand, int row, int col, const T &value)
constexpr void dispatch_symm(const Exec &exec, const KernelMatrixView< T, MatrixFormat::Dense > &a, MatrixMatrixOperand< T > operand, T *workspace=nullptr)
constexpr int group_local_linear_id(const Group &group)
constexpr void validate_symmetric_operand(const KernelMatrixView< T, MatrixFormat::Dense > &a, const MatrixVectorOperand< T > &operand, SymmetricTransform transform)
constexpr int group_local_linear_range(const Group &group)
constexpr Workspace * workspace_ptr_cast(T *workspace)
constexpr T symmetric_matrix_entry(const KernelMatrixView< T, MatrixFormat::Dense > &a, int row, int col)
constexpr T reduce_sum_group(const Group &group, const T &value)
constexpr int item_local_linear_id(const Item &item)
constexpr std::size_t symm_workspace_elements(const DeviceBlasLaunchInfo &launch, int row_extent, int col_extent)
constexpr std::size_t workspace_elements_v
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