batmat 0.0.17
Batched linear algebra routines
Loading...
Searching...
No Matches
syomv.tpp
Go to the documentation of this file.
1#pragma once
2
3#include <batmat/assume.hpp>
6#include <batmat/loop.hpp>
7#include <batmat/lut.hpp>
9
10#define UNROLL_FOR(...) BATMAT_FULLY_UNROLLED_FOR (__VA_ARGS__)
11
13
14template <class T, class Abi, KernelConfig Conf, StorageOrder OA, StorageOrder OB, StorageOrder OD>
15inline const constinit auto syomv_lut =
18 });
19
20/// Symmetric off-diagonal block multiply. Single register block.
21template <class T, class Abi, KernelConfig Conf, index_t RowsReg, StorageOrder OA, StorageOrder OB,
22 StorageOrder OD>
23[[gnu::hot, gnu::flatten]] void
25 const uview<T, Abi, OD> D, const index_t l0, const index_t k) noexcept {
26 static_assert(RowsReg > 0);
27 static_assert(Conf.struc_A == MatrixStructure::LowerTriangular); // TODO
28 using simd = datapar::simd<T, Abi>;
29 BATMAT_ASSUME(k > 0);
30 // Pre-compute the offsets of the columns of A
31 auto A_cached = with_cached_access<0, RowsReg>(A);
32 // Initialize accumulator
33 simd accum[RowsReg]{}; // NOLINT(*-c-arrays)
34 // Column weights for non-transposed block
35 simd Bl[RowsReg];
36 UNROLL_FOR (index_t l = 0; l < RowsReg; ++l)
37 Bl[l] = ops::rotr<1>(B.load(l + l0, 0));
38 // Actual multiplication kernel
39 for (index_t i = 0; i < k; ++i) {
40 simd Bi = B.load(i, 0);
41 simd Di = D.load(i, 0);
42 UNROLL_FOR (index_t l = 0; l < RowsReg; ++l) {
43 // Dot product between first lane of A and second lane of x
44 simd Ail = A_cached.load(i, l);
45 accum[l] += Ail * ops::rotl<1>(Bi);
46 // Linear combination of columns of first lane of A, weighted by
47 // the rows of the first lane of x, added to the second lane of v
48 Ail = ops::rotr<1>(Ail); // TODO: rotr?
49 Conf.negate ? (Di -= Ail * Bl[l]) : (Di += Ail * Bl[l]);
50 }
51 D.store(Di, i, 0);
52 }
53 // Subtract dot products of transposed block
54 UNROLL_FOR (index_t l = 0; l < RowsReg; ++l) {
55 simd vl = D.load(l + l0, 0);
56 Conf.negate ? (vl -= accum[l]) : (vl += accum[l]);
57 D.store(vl, l + l0, 0);
58 }
59}
60
61/// Generalized matrix multiplication D = C ± A⁽ᵀ⁾ B⁽ᵀ⁾. Using register blocking.
62template <class T, class Abi, KernelConfig Conf, StorageOrder OA, StorageOrder OB, StorageOrder OD>
64 const view<T, Abi, OD> D) noexcept {
65 using enum MatrixStructure;
66 constexpr auto Rows = RowsReg<T, Abi>;
67 // Check dimensions
68 const index_t I = D.rows(), J = D.cols(), K = A.cols();
69 BATMAT_ASSUME(A.rows() == I);
70 BATMAT_ASSUME(B.rows() == K);
71 BATMAT_ASSUME(B.cols() == J);
72 BATMAT_ASSUME(I == K);
73 BATMAT_ASSUME(I > 0);
74 BATMAT_ASSUME(J > 0);
75 BATMAT_ASSUME(K > 0);
76 BATMAT_ASSUME(J == 1); // TODO
77 static const auto microkernel = syomv_lut<T, Abi, Conf, OA, OB, OD>;
78 // Sizeless views to partition and pass to the micro-kernels
79 const uview<const T, Abi, OA> A_ = A;
80 const uview<const T, Abi, OB> B_ = B;
81 const uview<T, Abi, OD> D_ = D;
82
83 // Optimization for very small matrices
84 if (I <= Rows)
85 return microkernel[I - 1](A_, B_, D_, 0, K);
86 // Simply loop over all block columns in the matrix.
87 foreach_chunked_merged(0, K, Rows, [&](index_t l, index_t nl) {
88 const auto Al = A_.middle_cols(l);
89 microkernel[nl - 1](Al, B_, D_, l, A.rows());
90 });
91}
92
93} // namespace batmat::linalg::micro_kernels::syomv
#define BATMAT_ASSUME(x)
Invokes undefined behavior if the expression x does not evaluate to true.
Definition assume.hpp:17
#define UNROLL_FOR(...)
Definition gemm-diag.tpp:10
datapar::simd< F, Abi > rotl(datapar::simd< F, Abi > x)
Rotates the elements of x by s positions to the left.
Definition rotate.hpp:226
datapar::simd< F, Abi > rotr(datapar::simd< F, Abi > x)
Rotate the elements of x to the right by S positions.
Definition rotate.hpp:239
consteval auto make_1d_lut(F f)
Returns an array of the form:
Definition lut.hpp:39
void foreach_chunked_merged(index_t i_begin, index_t i_end, auto chunk_size, auto func_chunk, LoopDir dir=LoopDir::Forward)
Iterate over the range [i_begin, i_end) in chunks of size chunk_size, calling func_chunk for each chu...
Definition loop.hpp:43
stdx::simd< Tp, Abi > simd
Definition simd.hpp:99
const constinit auto syomv_lut
Definition syomv.tpp:15
constexpr index_t RowsReg
Register block size of the matrix-matrix multiplication micro-kernels.
Definition avx-512.hpp:13
void syomv_microkernel(uview< const T, Abi, OA > A, uview< const T, Abi, OB > B, uview< T, Abi, OD > D, index_t l0, index_t k) noexcept
Symmetric off-diagonal block multiply. Single register block.
Definition syomv.tpp:24
void syomv_register(view< const T, Abi, OA > A, view< const T, Abi, OB > B, view< T, Abi, OD > D) noexcept
Generalized matrix multiplication D = C ± A⁽ᵀ⁾ B⁽ᵀ⁾. Using register blocking.
Definition syomv.tpp:63
cached_uview< Order==StorageOrder::ColMajor ? Cols :Rows, T, Abi, Order > with_cached_access(const uview< T, Abi, Order > &o) noexcept
Definition uview.hpp:228
simd_view_types< std::remove_const_t< T >, Abi >::template view< T, Order > view
Definition uview.hpp:70
std::integral_constant< index_t, I > index_constant
Definition lut.hpp:10
Self middle_cols(this const Self &self, index_t c) noexcept
Definition uview.hpp:118