symmetric_product_fold.hh
Go to the documentation of this file.
1#pragma once
2
3// Fold a full GEMM product into the uplo triangle of C only:
4// C(i, j) := product(i, j) + beta * C(i, j) for (i, j) in the uplo triangle
5// The other half is the caller's and must come out unchanged; beta == 0 means C
6// is not read, so a poisoned C cannot produce NaN.
7// evidence: docs/perf/level3.md#level-3-generic-syrk-and-syr2k-fallbacks-fold-one-triangle
8
11
12#include <src/queue.hh>
13
14#include <sycl/sycl.hpp>
15
16namespace batchlas {
17namespace detail {
18
19template <typename T>
23 T beta,
24 Uplo uplo) {
25 const size_t n = static_cast<size_t>(C.rows());
26 const size_t batch_size = static_cast<size_t>(C.batch_size());
27 const size_t total_elements = batch_size * n * n;
28 if (total_elements == 0) {
29 return ctx.get_event();
30 }
31
32 T* c_ptr = C.data_ptr();
33 const T* p_ptr = product.data_ptr();
34 const size_t c_ld = static_cast<size_t>(C.ld());
35 const size_t c_stride = static_cast<size_t>(C.stride());
36 const size_t p_ld = static_cast<size_t>(product.ld());
37 const size_t p_stride = static_cast<size_t>(product.stride());
38 const bool upper = uplo == Uplo::Upper;
39 const bool ignore_c = beta == T(0);
40
41 auto [global_size, local_size] = compute_nd_range_sizes(
42 total_elements, ctx.device(), KernelType::ELEMENTWISE);
43
44 ctx->parallel_for(sycl::nd_range<1>(global_size, local_size), [=](sycl::nd_item<1> item) {
45 const size_t flat_idx = item.get_global_id(0);
46 if (flat_idx >= total_elements) return;
47
48 const size_t b = flat_idx / (n * n);
49 const size_t remainder = flat_idx % (n * n);
50 const size_t i = remainder / n; // row
51 const size_t j = remainder % n; // column
52
53 const bool in_triangle = upper ? (i <= j) : (i >= j);
54 if (!in_triangle) return;
55
56 const size_t c_idx = b * c_stride + j * c_ld + i;
57 const size_t p_idx = b * p_stride + j * p_ld + i;
58 c_ptr[c_idx] = ignore_c ? p_ptr[p_idx] : p_ptr[p_idx] + beta * c_ptr[c_idx];
59 });
60
61 return ctx.get_event();
62}
63
64} // namespace detail
65} // namespace batchlas
Non-owning view of a batch of matrices: the argument type of every entry point.
Definition matrix.hh:485
T * data_ptr() const
Base pointer of item 0.
Definition matrix.hh:600
int rows() const
Rows per item (the capacity on a heterogeneous batch).
Definition matrix.hh:605
int ld() const
Leading dimension: element distance between columns.
Definition matrix.hh:818
int stride() const
Batch stride: element distance between items.
Definition matrix.hh:823
int batch_size() const
Number of batch items.
Definition matrix.hh:603
Uplo
Which triangle of a symmetric, Hermitian or triangular operand is referenced.
Definition enums.hh:287
@ Upper
The upper triangle (i <= j).
Definition enums.hh:288
std::pair< size_t, size_t > compute_nd_range_sizes(size_t total_work, const Device &device, KernelType kernel_type, size_t preferred_wg_size=0)
Compute optimal global and local work sizes for nd_range kernels with overflow protection.
@ ELEMENTWISE
Element-wise operations (fill, copy, etc.).
Launch-size heuristics used by the library's own kernels.
The batched containers: Matrix (owning), MatrixView (non-owning), KernelMatrixView (device-side),...
Event fold_symmetric_product_into_triangle(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &C, const MatrixView< T, MatrixFormat::Dense > &product, T beta, Uplo uplo)
Completion handle of enqueued work, returned by every entry point.
Where BatchLAS work runs: a device, a backend, an ordered SYCL queue and a workspace arena.
Event get_event() const
An Event that completes after everything enqueued on this Queue so far.
Device device() const
The device this Queue runs on.