tract_linalg/frame/mmm/
kernel.rs1use crate::frame::pack::PackedFormat;
2
3use super::*;
4use std::borrow::Cow;
5use std::fmt::Debug;
6
7use crate::LADatum;
8
9pub trait MatMatMulKer: Clone + Debug + Send + Sync + 'static {
10 type Acc: LADatum;
11 fn name(&self) -> &str;
12 fn kernel(&self, op: &[FusedKerSpec<Self::Acc>]) -> isize;
13 fn mr(&self) -> usize;
14 fn nr(&self) -> usize;
15
16 fn arch(&self) -> Option<crate::isa::Arch> {
20 None
21 }
22
23 fn emulated(&self) -> bool {
26 false
27 }
28
29 fn boost(&self) -> isize;
32
33 fn preference(&self) -> isize {
36 self.boost() + self.isa().level() as isize * crate::isa::LEVEL_BOOST
37 }
38
39 #[allow(clippy::type_complexity)]
40 fn packings(&self) -> &[(Box<dyn MMMInputFormat>, Box<dyn MMMInputFormat>)];
41 fn stores(&self) -> Cow<'_, [DatumType]>;
42
43 #[allow(unused_variables)]
44 fn can_fuse(&self, spec: &FusedSpec) -> bool {
45 true
46 }
47
48 fn runnable_on(&self, isa: &crate::isa::IsaSet) -> bool {
53 self.arch().is_none_or(|a| Some(a) == isa.arch()) && self.isa().satisfied_by(*isa)
54 }
55
56 fn runnable(&self) -> bool {
57 self.built() && self.runnable_on(&crate::isa::native())
58 }
59
60 fn built(&self) -> bool {
62 true
63 }
64
65 fn isa(&self) -> crate::isa::IsaReq {
67 crate::isa::IsaReq::ANY
68 }
69
70 fn stores_row_major_tile(&self) -> bool {
74 false
75 }
76}
77
78type Kernel<Acc> = unsafe fn(&[FusedKerSpec<Acc>]) -> isize;
79
80#[derive(Clone)]
81pub struct DynKernel<const MR: usize, const NR: usize, Acc: LADatum> {
82 pub name: String,
83 pub kernel: Kernel<Acc>,
84 pub arch: Option<crate::isa::Arch>,
86 pub emulated: fn() -> bool,
90 pub packings: Vec<(Box<dyn MMMInputFormat>, Box<dyn MMMInputFormat>)>,
91 pub stores: Vec<DatumType>,
92 pub built: bool,
96 pub isa: crate::isa::IsaReq,
98 pub boost: fn() -> isize,
99 pub can_fuse: fn(&FusedSpec) -> bool,
100 pub row_major_store: bool,
101}
102
103impl<const MR: usize, const NR: usize, Acc: LADatum> DynKernel<MR, NR, Acc> {
104 pub fn new(
105 name: &str,
106 kernel: Kernel<Acc>,
107 packing_a: PackedFormat,
108 packing_b: PackedFormat,
109 ) -> Self {
110 let kernel = DynKernel {
111 name: name.to_string(),
112 kernel,
113 arch: None,
114 emulated: || false,
115 packings: vec![],
116 stores: vec![Acc::datum_type()],
117 built: true,
118 isa: crate::isa::IsaReq::ANY,
119 boost: || 0,
120 can_fuse: |_| true,
121 row_major_store: false,
122 };
123 kernel.with_packing(packing_a, packing_b)
124 }
125
126 pub fn with_isa(mut self, isa: crate::isa::IsaReq) -> Self {
130 self.isa = isa;
131 self
132 }
133
134 pub fn with_boost(mut self, f: fn() -> isize) -> Self {
137 self.boost = f;
138 self
139 }
140
141 pub fn with_packing(mut self, a: impl MMMInputFormat, b: impl MMMInputFormat) -> Self {
142 self.packings.push((Box::new(a), Box::new(b)));
143 self
144 }
145
146 pub fn with_packing_a(self, a: impl MMMInputFormat) -> Self {
147 let b = self.regular_pack_b();
148 self.with_packing(a, b)
149 }
150
151 pub fn regular_pack_a(&self) -> PackedFormat {
152 *self.packings[0].0.clone().downcast::<PackedFormat>().unwrap()
153 }
154
155 pub fn regular_pack_b(&self) -> PackedFormat {
156 *self.packings[0].1.clone().downcast::<PackedFormat>().unwrap()
157 }
158
159 pub fn with_can_fuse(self, can_fuse: fn(&FusedSpec) -> bool) -> Self {
160 Self { can_fuse, ..self }
161 }
162
163 pub fn with_store<D: LADatum>(mut self) -> Self {
164 self.stores.push(D::datum_type());
165 self
166 }
167
168 pub fn mmm(&self) -> Box<dyn MatMatMul> {
169 Box::new(self.clone())
170 }
171}
172
173impl<const MR: usize, const NR: usize, Acc: LADatum> Debug for DynKernel<MR, NR, Acc> {
174 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175 write!(f, "{}", self.name)
176 }
177}
178
179impl<const MR: usize, const NR: usize, Acc: LADatum> MatMatMulKer for DynKernel<MR, NR, Acc> {
180 type Acc = Acc;
181 fn name(&self) -> &str {
182 &self.name
183 }
184
185 fn mr(&self) -> usize {
186 MR
187 }
188
189 fn nr(&self) -> usize {
190 NR
191 }
192
193 fn arch(&self) -> Option<crate::isa::Arch> {
194 self.arch
195 }
196
197 fn emulated(&self) -> bool {
198 (self.emulated)()
199 }
200
201 fn built(&self) -> bool {
202 self.built
203 }
204
205 fn isa(&self) -> crate::isa::IsaReq {
206 self.isa
207 }
208
209 fn can_fuse(&self, spec: &FusedSpec) -> bool {
210 (self.can_fuse)(spec)
211 }
212
213 fn kernel(&self, op: &[FusedKerSpec<Self::Acc>]) -> isize {
214 unsafe { (self.kernel)(op) }
215 }
216
217 #[allow(clippy::type_complexity)]
218 fn packings(&self) -> &[(Box<dyn MMMInputFormat>, Box<dyn MMMInputFormat>)] {
219 &self.packings
220 }
221
222 fn stores(&self) -> Cow<'_, [DatumType]> {
223 Cow::Borrowed(&self.stores)
224 }
225
226 fn boost(&self) -> isize {
227 (self.boost)()
228 }
229
230 fn stores_row_major_tile(&self) -> bool {
231 self.row_major_store
232 }
233}