11#include <batchlas/device_limits.hh>
17#include <sycl/sycl.hpp>
121template <Transpose TransV>
133template <Transpose TransAV, Transpose TransBV>
161template <
bool ConjugateXV,
bool ConjugateYV>
237template <
typename Item>
240 item.get_sub_group();
241 item.get_local_linear_id();
242 item.get_local_range().size();
245template <NdItemLike Item>
247 return static_cast<int>(item.get_local_linear_id());
250template <NdItemLike Item>
252 return static_cast<int>(item.get_local_range().size());
255template <
typename T,
typename Workspace>
258template <
typename Workspace,
typename T>
260 static_assert(
sizeof(Workspace) %
sizeof(T) == 0);
261 return reinterpret_cast<Workspace*
>(workspace);
264template <
typename Group,
typename T>
267 using Real =
typename T::value_type;
276template <NdItemLike Item,
typename T>
282inline constexpr T
conj(
const T& value) {
284 return std::conj(value);
290template <
typename Group>
292 return static_cast<int>(group.get_local_linear_id());
295template <NdItemLike Item>
300template <
typename Group>
302 return static_cast<int>(group.get_local_range().size());
305template <NdItemLike Item>
314template <
typename Group>
319template <
typename T,
typename Op>
322template <
typename T,
typename Op>
325template <
typename T,
typename Op>
330 return conjugate ?
conj(value) : value;
336 if (lhs.
size() <= 0 || rhs.
size() <= 0) {
341 auto* lhs_end = lhs_begin + (lhs.
size() - 1) * lhs.
inc();
342 if (lhs_end < lhs_begin) {
343 std::swap(lhs_begin, lhs_end);
347 auto* rhs_end = rhs_begin + (rhs.
size() - 1) * rhs.
inc();
348 if (rhs_end < rhs_begin) {
349 std::swap(rhs_begin, rhs_end);
352 return !(lhs_end < rhs_begin || rhs_end < lhs_begin);
358 if (lhs.
rows() <= 0 || lhs.
cols() <= 0 || rhs.
rows() <= 0 || rhs.
cols() <= 0) {
362 auto* lhs_begin = lhs.
data();
363 auto* lhs_end = lhs_begin + (lhs.
cols() - 1) * lhs.
ld() + (lhs.
rows() - 1);
364 if (lhs_end < lhs_begin) {
365 std::swap(lhs_begin, lhs_end);
368 auto* rhs_begin = rhs.
data();
369 auto* rhs_end = rhs_begin + (rhs.
cols() - 1) * rhs.
ld() + (rhs.
rows() - 1);
370 if (rhs_end < rhs_begin) {
371 std::swap(rhs_begin, rhs_end);
374 return !(lhs_end < rhs_begin || rhs_end < lhs_begin);
388 return conj(a(col, row));
391template <Transpose TransV,
typename T>
400 return conj(a(col, row));
413template <Transpose TransV,
typename T>
431template <Transpose TransV,
typename T>
444 assert(a.
batch_size() == 1 &&
"device BLAS expects a single logical matrix; pass batch_item() for batched data");
452 assert(operand.
x.batch_size() == 1 &&
"device::gemv expects a single logical input vector; pass batch_item() for batched data");
453 assert(operand.
y.batch_size() == 1 &&
"device::gemv expects a single logical output vector; pass batch_item() for batched data");
454 assert(operand.
x.size() >=
input_size(a, trans) &&
"device::gemv input vector is too small for the requested transpose mode");
455 assert(operand.
y.size() >=
output_size(a, trans) &&
"device::gemv output vector is too small for the requested transpose mode");
463 assert(operand.
b.
batch_size() == 1 &&
"device::gemm expects a single logical input matrix; pass batch_item() for batched data");
464 assert(operand.
c.
batch_size() == 1 &&
"device::gemm expects a single logical output matrix; pass batch_item() for batched data");
471 assert(b_rows == k &&
"device::gemm operand contract dimension mismatch");
472 assert(operand.
c.
rows() == m &&
"device::gemm output matrix row count does not match op(A)");
473 assert(operand.
c.
cols() == n &&
"device::gemm output matrix column count does not match op(B)");
481 assert(transform.
side ==
Side::Left &&
"device::trmv currently supports only Side::Left");
482 assert(a.
rows() == a.
cols() &&
"device::trmv expects a square triangular matrix");
483 assert(operand.
x.batch_size() == 1 &&
"device::trmv expects a single logical input vector; pass batch_item() for batched data");
484 assert(operand.
y.batch_size() == 1 &&
"device::trmv expects a single logical output vector; pass batch_item() for batched data");
485 assert(operand.
x.size() >= a.
rows() &&
"device::trmv input vector is too small for the triangular matrix");
486 assert(operand.
y.size() >= a.
rows() &&
"device::trmv output vector is too small for the triangular matrix");
494 assert(transform.
side ==
Side::Left &&
"device::symv currently supports only Side::Left");
495 assert(a.
rows() == a.
cols() &&
"device::symv expects a square symmetric matrix");
496 assert(operand.
x.batch_size() == 1 &&
"device::symv expects a single logical input vector; pass batch_item() for batched data");
497 assert(operand.
y.batch_size() == 1 &&
"device::symv expects a single logical output vector; pass batch_item() for batched data");
498 assert(operand.
x.size() >= a.
rows() &&
"device::symv input vector is too small for the symmetric matrix");
499 assert(operand.
y.size() >= a.
rows() &&
"device::symv output vector is too small for the symmetric matrix");
507 assert(operand.
b.
batch_size() == 1 &&
"device::trmm expects a single logical input matrix; pass batch_item() for batched data");
508 assert(operand.
c.
batch_size() == 1 &&
"device::trmm expects a single logical output matrix; pass batch_item() for batched data");
509 assert(operand.
b.
rows() == operand.
c.
rows() &&
"device::trmm input and output matrices must have matching row counts");
510 assert(operand.
b.
cols() == operand.
c.
cols() &&
"device::trmm input and output matrices must have matching column counts");
511 assert(a.
rows() == a.
cols() &&
"device::trmm expects a square triangular matrix");
513 assert(a.
rows() == operand.
b.
rows() &&
"device::trmm left-side triangular matrix must match input rows");
515 assert(a.
rows() == operand.
b.
cols() &&
"device::trmm right-side triangular matrix must match input columns");
524 assert(a.
rows() == a.
cols() &&
"device::symm expects a square symmetric matrix");
525 assert(operand.
b.
batch_size() == 1 &&
"device::symm expects a single logical input matrix; pass batch_item() for batched data");
526 assert(operand.
c.
batch_size() == 1 &&
"device::symm expects a single logical output matrix; pass batch_item() for batched data");
527 assert(operand.
b.
rows() == operand.
c.
rows() &&
"device::symm input and output matrices must have matching row counts");
528 assert(operand.
b.
cols() == operand.
c.
cols() &&
"device::symm input and output matrices must have matching column counts");
530 assert(a.
rows() == operand.
b.
rows() &&
"device::symm left-side symmetric matrix must match input rows");
532 assert(a.
rows() == operand.
b.
cols() &&
"device::symm right-side symmetric matrix must match input columns");
539 assert(x.
batch_size() == 1 &&
"device::ger expects a single logical input vector; pass batch_item() for batched data");
540 assert(operand.
y.batch_size() == 1 &&
"device::ger expects a single logical input vector; pass batch_item() for batched data");
542 assert(operand.
a.
rows() == x.
size() &&
"device::ger matrix row count must match x size");
543 assert(operand.
a.
cols() == operand.
y.size() &&
"device::ger matrix column count must match y size");
551 assert(operand.
b.
batch_size() == 1 &&
"device::syr2k expects a single logical input matrix; pass batch_item() for batched data");
552 assert(operand.
c.
batch_size() == 1 &&
"device::syr2k expects a single logical output matrix; pass batch_item() for batched data");
553 assert(a.
rows() == operand.
b.
rows() &&
"device::syr2k input matrices must have matching row counts");
554 assert(a.
cols() == operand.
b.
cols() &&
"device::syr2k input matrices must have matching column counts");
556 assert(operand.
c.
rows() == extent &&
"device::syr2k output matrix row count does not match op(A)");
557 assert(operand.
c.
cols() == extent &&
"device::syr2k output matrix column count does not match op(A)");
565 assert(operand.
c.
batch_size() == 1 &&
"device::syrk expects a single logical output matrix; pass batch_item() for batched data");
567 assert(operand.
c.
rows() == extent &&
"device::syrk output matrix row count does not match op(A)");
568 assert(operand.
c.
cols() == extent &&
"device::syrk output matrix column count does not match op(A)");
575 assert(x.
batch_size() == 1 &&
"device vector BLAS expects a single logical vector; pass batch_item() for batched data");
584 assert(x.
size() == y.
size() &&
"device vector BLAS operands must have matching sizes");
594 assert(x.
size() == z.
size() &&
"device vector BLAS operands must have matching sizes");
597template <
typename T,
typename... Views>
598 requires(
sizeof...(Views) > 0 && (VectorOperandFor<T, Views> && ...))
601 const Views&... inputs) {
604 assert(inputs.size() == z.size() &&
"device hadamard operands must have matching sizes")),
608template <S
ide S
ideV, Uplo UploV, Transpose TransposeV, Diag DiagV>
616template <S
ide S
ideV, Uplo UploV,
bool HermitianV>
623template <Uplo UploV, Transpose TransposeV,
bool HermitianV>
630template <
typename Tag>
639 return uplo ==
Uplo::Lower ? row >= col : row <= col;
642template <
typename Tag,
typename T>
653 if (src_row == src_col) {
661 T value = a(src_row, src_col);
686 T value = a(src_row, src_col);
693template <
typename Tag,
typename T>
701 const T value = a(col, row);
702 if constexpr (Tag::hermitian) {
710 const T value = a(col, row);
711 if constexpr (Tag::hermitian) {
726 const T value = a(col, row);
732 const T value = a(col, row);
741 operand.
c(row, col) = operand.
alpha * value + operand.
beta * operand.
c(row, col);
749 operand.
a(row, col) += operand.
alpha * value;
752template <
typename Tag>
767template <
typename Tag>
782template <
typename Tag,
typename T>
784 if constexpr (Tag::hermitian) {
792 return hermitian ?
conj(alpha) : alpha;
798 .side = transform.
side,
799 .uplo = transform.
uplo,
807 .uplo = transform.
uplo,
808 .trans = transform.
trans,
816 .uplo = transform.
uplo,
817 .trans = transform.
trans,
Non-owning view of a batch of strided vectors: the vector argument type of the entry points.
int size() const
Entries per item.
T * data_ptr() const
Pointer to entry 0 of item 0.
int batch_size() const
Number of batch items.
int inc() const
Element distance between entries.
A std::complex scalar (std::complex<float>, std::complex<double>).
Enumerations, scalar traits and scalar concepts shared by every public header.
batchlas::portable:: group broadcast, shuffles and sums for any trivially copyable or complex T.
constexpr Rank1UpdateOperand< T > make_rank1_update_operand(const VectorView< T > &y, const KernelMatrixView< T, MatrixFormat::Dense > &a, T alpha=T(1))
Builds a Rank1UpdateOperand.
constexpr DeviceBlasLaunchInfo make_group_launch_info(int local_size)
Launch description for a call that receives a sycl::group.
constexpr MatrixVectorOperand< T > make_matvec_operand(const VectorView< T > &x, const VectorView< T > &y, T alpha=T(1), T beta=T(0))
Builds a MatrixVectorOperand.
constexpr DeviceBlasLaunchInfo make_nd_item_1d_launch_info(int local_size, int subgroup_size)
Launch description for a call that receives a sycl::nd_item<1>.
constexpr DeviceBlasLaunchInfo make_nd_item_3d_launch_info(int local_size, int subgroup_size)
Launch description for a call that receives a sycl::nd_item<3> (tiled output).
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.
constexpr RankKOperand< T > make_rankk_operand(const KernelMatrixView< T, MatrixFormat::Dense > &c, T alpha=T(1), T beta=T(0))
Builds a RankKOperand.
DeviceBlasPolicy
Which implementation family a device BLAS call may use.
DeviceBlasLaunchKind
Kind of launch a DeviceBlasLaunchInfo describes.
@ Subgroup16
fast paths only when the actual sub-group size is 16
@ Auto
any eligible path; the sub-group fast paths accept sub-group size 16 or 32
@ Subgroup32
fast paths only when the actual sub-group size is 32
@ Generic
the portable group-reduction path only; never stages through local memory
@ Group
the call receives a sycl::group (or sycl::sub_group)
@ NdItem1D
the call receives a sycl::nd_item<1>
@ NdItem3D
the call receives a sycl::nd_item<3> whose dimensions 1 and 2 index output tiles
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).
@ ConjTrans
op(A) = A^H (the same as Trans for real scalars).
@ Unit
The diagonal is taken as 1 and not read.
@ NonUnit
The stored diagonal is used.
@ Upper
The upper triangle (i <= j).
@ Lower
The lower triangle (i >= j).
@ Left
The special operand is on the left.
T reduce_over_group(Group g, T x, Op op)
sycl::reduce_over_group, also for a std::complex sum; a work-group floating result is exact (see deta...
The batched containers: Matrix (owning), MatrixView (non-owning), KernelMatrixView (device-side),...
constexpr bool views_overlap(const VectorView< T > &lhs, const VectorView< T > &rhs)
constexpr void validate_rank1_operand(const VectorView< T > &x, const Rank1UpdateOperand< T > &operand)
constexpr int output_size(const KernelMatrixView< T, MatrixFormat::Dense > &a, Transpose trans)
constexpr void write_matrix_output(const MatrixMatrixOperand< T > &operand, int row, int col, const T &value)
constexpr Transpose rank2k_rhs_transform()
constexpr void validate_single_problem(const KernelMatrixView< T, MatrixFormat::Dense > &a, Transpose trans)
constexpr int group_local_linear_id(const Group &group)
constexpr SymmetricTransform canonical_hermitian_transform(SymmetricTransform transform)
constexpr void validate_operand(const KernelMatrixView< T, MatrixFormat::Dense > &a, const MatrixVectorOperand< T > &operand, Transpose trans)
constexpr void validate_vector_operands(const VectorView< T > &x, const VectorView< T > &y, const char *op_name)
constexpr int input_size(const KernelMatrixView< T, MatrixFormat::Dense > &a, Transpose trans)
constexpr T triangular_matrix_entry(const KernelMatrixView< T, MatrixFormat::Dense > &a, int row, int col)
constexpr void validate_gemm_operand(const KernelMatrixView< T, MatrixFormat::Dense > &a, const MatrixMatrixOperand< T > &operand, GeneralMatrixTransform transform)
constexpr void accumulate_rank1_output(const Rank1UpdateOperand< T > &operand, int row, int col, const T &value)
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 maybe_conjugate(const T &value, bool conjugate)
constexpr Transpose rankk_rhs_transform()
constexpr T symmetric_matrix_entry(const KernelMatrixView< T, MatrixFormat::Dense > &a, int row, int col)
constexpr void validate_rank2k_operand(const KernelMatrixView< T, MatrixFormat::Dense > &a, const MatrixMatrixOperand< T > &operand, SymmetricRank2kTransform transform)
constexpr T matrix_entry(const KernelMatrixView< T, MatrixFormat::Dense > &a, int row, int col, Transpose trans)
constexpr T reduce_sum_group(const Group &group, const T &value)
constexpr T conj(const T &value)
constexpr int item_local_linear_id(const Item &item)
constexpr void validate_vector_operand(const VectorView< T > &x, const char *op_name)
constexpr std::size_t workspace_elements_v
constexpr void validate_rankk_operand(const KernelMatrixView< T, MatrixFormat::Dense > &a, const RankKOperand< T > &operand, SymmetricRankKTransform transform)
constexpr void validate_hadamard_operands(const VectorView< T > &z, const char *op_name, const Views &... inputs)
constexpr void validate_triangular_operand(const KernelMatrixView< T, MatrixFormat::Dense > &a, const MatrixVectorOperand< T > &operand, TriangularTransform transform)
constexpr bool triangular_storage_contains(int row, int col)
constexpr bool group_is_leader(const Group &group)
constexpr int item_local_linear_range(const Item &item)
constexpr T secondary_rank2k_alpha(const T &alpha)
constexpr std::string_view op_name(Op o)
Trivially copyable view of a MatrixView for use inside a SYCL kernel.
auto data() const
Base pointer of item 0.
auto batch_size() const
Number of batch items.
auto rows() const
Row count (the capacity on a heterogeneous batch).
auto ld() const
Dense leading dimension, in elements.
auto cols() const
Column count (the capacity on a heterogeneous batch).
Host-side description of a launch, for the *_workspace_elements queries.
DeviceBlasLaunchKind kind
executor the call receives
int subgroup_size
sub-group size of the kernel; 1 for DeviceBlasLaunchKind::Group
int local_size
work-items per work-group (per sub-group for a sub-group executor)
Operands of a matrix-matrix operation: .
KernelMatrixView< T, MatrixFormat::Dense > c
output matrix; read (scaled by beta) and overwritten
T alpha
scale of the product
T beta
scale of the input C; 0 still reads C
KernelMatrixView< T, MatrixFormat::Dense > b
second input matrix
Operands of a matrix-vector operation: .
VectorView< T > x
input vector
T beta
scale of the input y; 0 still reads y
T alpha
scale of the product
VectorView< T > y
output vector; read (scaled by beta) and overwritten
Operands of a rank-1 update: (conjugations per call).
KernelMatrixView< T, MatrixFormat::Dense > a
matrix updated in place
T alpha
scale of the outer product
VectorView< T > y
right vector, length a.cols()
Operands of a rank-k update: .
T alpha
scale of the product
KernelMatrixView< T, MatrixFormat::Dense > c
square output; only the uplo triangle is touched
T beta
scale of the input C; 0 still reads C