batmat 0.0.15
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>
8
9#define UNROLL_FOR(...) BATMAT_FULLY_UNROLLED_FOR (__VA_ARGS__)
10
12
13/// Symmetric off-diagonal block multiply. Single register block.
14template <class T, class Abi, KernelConfig Conf, index_t RowsReg, StorageOrder OA, StorageOrder OB,
15 StorageOrder OD>
16[[gnu::hot, gnu::flatten]] void
18 const uview<T, Abi, OD> D, const index_t l0, const index_t k) noexcept {
19 static_assert(RowsReg > 0);
20 static_assert(Conf.struc_A == MatrixStructure::LowerTriangular); // TODO
21 using simd = datapar::simd<T, Abi>;
22 BATMAT_ASSUME(k > 0);
23 // Pre-compute the offsets of the columns of A
24 auto A_cached = with_cached_access<0, RowsReg>(A);
25 // Initialize accumulator
26 simd accum[RowsReg]{}; // NOLINT(*-c-arrays)
27 // Column weights for non-transposed block
28 simd Bl[RowsReg];
29 UNROLL_FOR (index_t l = 0; l < RowsReg; ++l)
30 Bl[l] = ops::rotr<1>(B.load(l + l0, 0));
31 // Actual multiplication kernel
32 for (index_t i = 0; i < k; ++i) {
33 simd Bi = B.load(i, 0);
34 simd Di = D.load(i, 0);
35 UNROLL_FOR (index_t l = 0; l < RowsReg; ++l) {
36 // Dot product between first lane of A and second lane of x
37 simd Ail = A_cached.load(i, l);
38 accum[l] += Ail * ops::rotl<1>(Bi);
39 // Linear combination of columns of first lane of A, weighted by
40 // the rows of the first lane of x, added to the second lane of v
41 Ail = ops::rotr<1>(Ail); // TODO: rotr?
42 Conf.negate ? (Di -= Ail * Bl[l]) : (Di += Ail * Bl[l]);
43 }
44 D.store(Di, i, 0);
45 }
46 // Subtract dot products of transposed block
47 UNROLL_FOR (index_t l = 0; l < RowsReg; ++l) {
48 simd vl = D.load(l + l0, 0);
49 Conf.negate ? (vl -= accum[l]) : (vl += accum[l]);
50 D.store(vl, l + l0, 0);
51 }
52}
53
54/// Generalized matrix multiplication D = C ± A⁽ᵀ⁾ B⁽ᵀ⁾. Using register blocking.
55template <class T, class Abi, KernelConfig Conf, StorageOrder OA, StorageOrder OB, StorageOrder OD>
57 const view<T, Abi, OD> D) noexcept {
58 using enum MatrixStructure;
59 constexpr auto Rows = RowsReg<T, Abi>;
60 // Check dimensions
61 const index_t I = D.rows(), J = D.cols(), K = A.cols();
62 BATMAT_ASSUME(A.rows() == I);
63 BATMAT_ASSUME(B.rows() == K);
64 BATMAT_ASSUME(B.cols() == J);
65 BATMAT_ASSUME(I == K);
66 BATMAT_ASSUME(I > 0);
67 BATMAT_ASSUME(J > 0);
68 BATMAT_ASSUME(K > 0);
69 BATMAT_ASSUME(J == 1); // TODO
70 static const auto microkernel = syomv_lut<T, Abi, Conf, OA, OB, OD>;
71 // Sizeless views to partition and pass to the micro-kernels
72 const uview<const T, Abi, OA> A_ = A;
73 const uview<const T, Abi, OB> B_ = B;
74 const uview<T, Abi, OD> D_ = D;
75
76 // Optimization for very small matrices
77 if (I <= Rows)
78 return microkernel[I - 1](A_, B_, D_, 0, K);
79 // Simply loop over all block columns in the matrix.
80 foreach_chunked_merged(0, K, Rows, [&](index_t l, index_t nl) {
81 const auto Al = A_.middle_cols(l);
82 microkernel[nl - 1](Al, B_, D_, l, A.rows());
83 });
84}
85
86} // 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:9
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
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.hpp:28
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:17
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:56
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
Self middle_cols(this const Self &self, index_t c) noexcept
Definition uview.hpp:118