blob: 3cf84a614a932f4640181f06e7ba8a563827fdec [file] [log] [blame]
Pablo Telloeb82fd22018-02-23 13:43:50 +00001/*
Michalis Spyrou778b95c2021-04-20 12:15:52 +01002 * Copyright (c) 2017-2021 Arm Limited.
Pablo Telloeb82fd22018-02-23 13:43:50 +00003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "arm_gemm.hpp"
25#include "gemm_common.hpp"
Georgios Pinitas7cd26d42019-01-09 18:35:17 +000026#include "gemm_hybrid.hpp"
Georgios Pinitasc0b6f762020-11-02 01:37:17 +000027#include "gemm_hybrid_indirect.hpp"
David Manselle39334c2018-07-06 17:53:35 +010028#include "gemm_implementation.hpp"
Pablo Telloeb82fd22018-02-23 13:43:50 +000029#include "gemm_interleaved.hpp"
David Mansellce8f6052018-05-17 18:51:26 +010030#include "gemv_batched.hpp"
Pablo Telloeb82fd22018-02-23 13:43:50 +000031#include "gemv_pretransposed.hpp"
32
Anthony Barbier5f707732018-07-03 16:22:02 +010033#include "kernels/a32_sgemm_8x6.hpp"
Georgios Pinitas4ee8b152021-07-16 16:16:43 +010034#include "kernels/a64_hybrid_fp32bf16fp32_mmla_4x24.hpp"
35#include "kernels/a64_hybrid_fp32bf16fp32_mmla_6x16.hpp"
36#include "kernels/a64_hybrid_fp32_mla_4x24.hpp"
Georgios Pinitasc0b6f762020-11-02 01:37:17 +000037#include "kernels/a64_hybrid_fp32_mla_6x16.hpp"
38#include "kernels/a64_hybrid_fp32_mla_8x4.hpp"
Georgios Pinitas4ee8b152021-07-16 16:16:43 +010039#include "kernels/a64_interleaved_bf16fp32_mmla_8x12.hpp"
Georgios Pinitasc0b6f762020-11-02 01:37:17 +000040#include "kernels/a64_sgemm_8x12.hpp"
Michalis Spyrou778b95c2021-04-20 12:15:52 +010041#include "kernels/a64_sgemm_8x6.hpp"
Georgios Pinitasc0b6f762020-11-02 01:37:17 +000042#include "kernels/a64_smallK_hybrid_fp32_mla_6x4.hpp"
43#include "kernels/a64_smallK_hybrid_fp32_mla_8x4.hpp"
Pablo Telloeb82fd22018-02-23 13:43:50 +000044
Georgios Pinitas4ee8b152021-07-16 16:16:43 +010045#include "kernels/sve_hybrid_fp32bf16fp32_mmla_4x6VL.hpp"
46#include "kernels/sve_hybrid_fp32bf16fp32_mmla_6x4VL.hpp"
Georgios Pinitasc0b6f762020-11-02 01:37:17 +000047#include "kernels/sve_hybrid_fp32_mla_6x4VL.hpp"
48#include "kernels/sve_hybrid_fp32_mla_8x1VL.hpp"
Georgios Pinitas4ee8b152021-07-16 16:16:43 +010049#include "kernels/sve_interleaved_bf16fp32_mmla_8x3VL.hpp"
Georgios Pinitasc0b6f762020-11-02 01:37:17 +000050#include "kernels/sve_interleaved_fp32_mla_8x3VL.hpp"
51#include "kernels/sve_interleaved_fp32_mmla_8x3VL.hpp"
52#include "kernels/sve_smallK_hybrid_fp32_mla_8x1VL.hpp"
Georgios Pinitas421405b2018-10-26 19:05:32 +010053
Anthony Barbier5f707732018-07-03 16:22:02 +010054namespace arm_gemm {
55
Georgios Pinitas7cd26d42019-01-09 18:35:17 +000056static const GemmImplementation<float, float> gemm_fp32_methods[] =
57{
Georgios Pinitasc0b6f762020-11-02 01:37:17 +000058// GEMV cases - starting with 'gemv_batched' wrapper to turn batched GEMV into GEMM.
Georgios Pinitas7cd26d42019-01-09 18:35:17 +000059{
60 GemmMethod::GEMV_BATCHED,
61 "gemv_batched",
Georgios Pinitasc0b6f762020-11-02 01:37:17 +000062 [](const GemmArgs &args) { return args._Msize==1 && args._nbatches>1 && !args._indirect_input; },
Georgios Pinitas7cd26d42019-01-09 18:35:17 +000063 nullptr,
Georgios Pinitas48b3ef82019-10-14 19:03:09 +010064 [](const GemmArgs &args) { return new GemvBatched<float, float>(args); }
Georgios Pinitas7cd26d42019-01-09 18:35:17 +000065},
66#ifdef __aarch64__
Georgios Pinitas4ee8b152021-07-16 16:16:43 +010067#ifdef ARM_COMPUTE_ENABLE_BF16
68// "fast mode" (BF16) kernels
69GemmImplementation<float, float>::with_estimate(
70 GemmMethod::GEMM_INTERLEAVED,
71 "a64_interleaved_bf16fp32_mmla_8x12",
72 [](const GemmArgs &args) { return args._fast_mode && args._ci->has_bf16(); },
73 [](const GemmArgs &args) { return GemmInterleaved<cls_a64_interleaved_bf16fp32_mmla_8x12, float, float>::estimate_cycles<float>(args); },
74 [](const GemmArgs &args) { return new GemmInterleaved<cls_a64_interleaved_bf16fp32_mmla_8x12, float, float>(args); }
75),
76GemmImplementation<float, float>::with_estimate(
77 GemmMethod::GEMM_HYBRID,
78 "a64_hybrid_fp32bf16fp32_mmla_6x16",
79 [](const GemmArgs &args) { return args._fast_mode && args._ci->has_bf16(); },
80 [](const GemmArgs &args) { return GemmHybridIndirect<cls_a64_hybrid_fp32bf16fp32_mmla_6x16, float, float>::estimate_cycles<float>(args); },
81 [](const GemmArgs &args) { return new GemmHybridIndirect<cls_a64_hybrid_fp32bf16fp32_mmla_6x16, float, float>(args); }
82),
83GemmImplementation<float, float>::with_estimate(
84 GemmMethod::GEMM_HYBRID,
85 "a64_hybrid_fp32bf16fp32_mmla_4x24",
86 [](const GemmArgs &args) { return args._fast_mode && args._ci->has_bf16(); },
87 [](const GemmArgs &args) { return GemmHybridIndirect<cls_a64_hybrid_fp32bf16fp32_mmla_4x24, float, float>::estimate_cycles<float>(args); },
88 [](const GemmArgs &args) { return new GemmHybridIndirect<cls_a64_hybrid_fp32bf16fp32_mmla_4x24, float, float>(args); }
89),
90#endif // ARM_COMPUTE_ENABLE_BF16
Michalis Spyrou20fca522021-06-07 14:23:57 +010091#ifdef ARM_COMPUTE_ENABLE_SVE
Georgios Pinitas4ee8b152021-07-16 16:16:43 +010092#ifdef ARM_COMPUTE_ENABLE_BF16
93GemmImplementation<float, float>::with_estimate(
94 GemmMethod::GEMM_INTERLEAVED,
95 "sve_interleaved_bf16fp32_mmla_8x3VL",
96 [](const GemmArgs &args) { return args._fast_mode && args._ci->has_svebf16(); },
97 [](const GemmArgs &args) { return GemmInterleaved<cls_sve_interleaved_bf16fp32_mmla_8x3VL, float, float>::estimate_cycles<float>(args); },
98 [](const GemmArgs &args) { return new GemmInterleaved<cls_sve_interleaved_bf16fp32_mmla_8x3VL, float, float>(args); }
99),
100GemmImplementation<float, float>::with_estimate(
Georgios Pinitas5aa1a0b2020-07-02 20:02:20 +0100101 GemmMethod::GEMM_HYBRID,
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100102 "sve_hybrid_fp32bf16fp32_mmla_6x4VL",
103 [](const GemmArgs &args) { return args._fast_mode && args._ci->has_bf16(); },
104 [](const GemmArgs &args) { return GemmHybridIndirect<cls_sve_hybrid_fp32bf16fp32_mmla_6x4VL, float, float>::estimate_cycles<float>(args); },
105 [](const GemmArgs &args) { return new GemmHybridIndirect<cls_sve_hybrid_fp32bf16fp32_mmla_6x4VL, float, float>(args); }
106),
107GemmImplementation<float, float>::with_estimate(
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000108 GemmMethod::GEMM_HYBRID,
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100109 "sve_hybrid_fp32bf16fp32_mmla_4x6VL",
110 [](const GemmArgs &args) { return args._fast_mode && args._ci->has_bf16(); },
111 [](const GemmArgs &args) { return GemmHybridIndirect<cls_sve_hybrid_fp32bf16fp32_mmla_4x6VL, float, float>::estimate_cycles<float>(args); },
112 [](const GemmArgs &args) { return new GemmHybridIndirect<cls_sve_hybrid_fp32bf16fp32_mmla_4x6VL, float, float>(args); }
113),
114#endif // ARM_COMPUTE_ENABLE_BF16
115#ifdef ARM_COMPUTE_ENABLE_SVEF32MM
116// MMLA next due to higher throughput (which is SVE only)
117// Prefer this in all cases, except if fast mode is requested and BF16 is available.
Georgios Pinitas5aa1a0b2020-07-02 20:02:20 +0100118{
119 GemmMethod::GEMM_INTERLEAVED,
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000120 "sve_interleaved_fp32_mmla_8x3VL",
Michalis Spyrou20fca522021-06-07 14:23:57 +0100121 [](const GemmArgs &args) { return args._ci->has_svef32mm() && (args._Ksize>4); },
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100122 [](const GemmArgs &args) { return !(args._fast_mode && args._ci->has_bf16()); },
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000123 [](const GemmArgs &args) { return new GemmInterleaved<cls_sve_interleaved_fp32_mmla_8x3VL, float, float>(args); }
Georgios Pinitas5aa1a0b2020-07-02 20:02:20 +0100124},
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100125#endif // ARM_COMPUTE_ENABLE_SVEF32MM
126// SVE kernels
Georgios Pinitasc7b183a2020-03-06 18:12:09 +0000127{
128 GemmMethod::GEMM_HYBRID,
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000129 "sve_smallK_hybrid_fp32_mla_8x1VL",
Pablo Marquez Telloa50f1932021-03-08 17:27:05 +0000130 [](const GemmArgs &args) { return args._ci->has_sve() && args._Ksize <= 24 && !args._indirect_input; },
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100131 nullptr,
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000132 [](const GemmArgs &args) { return new GemmHybrid<cls_sve_smallK_hybrid_fp32_mla_8x1VL, float, float>(args); }
Georgios Pinitasc7b183a2020-03-06 18:12:09 +0000133},
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000134{
135 GemmMethod::GEMM_HYBRID,
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000136 "sve_hybrid_fp32_mla_8x1VL",
Pablo Marquez Telloa50f1932021-03-08 17:27:05 +0000137 [](const GemmArgs &args) { return args._ci->has_sve(); },
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100138 [](const GemmArgs &args) { return (args._Nsize < 12); },
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000139 [](const GemmArgs &args) { return new GemmHybridIndirect<cls_sve_hybrid_fp32_mla_8x1VL, float, float>(args); }
140},
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100141GemmImplementation<float, float>::with_estimate(
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000142 GemmMethod::GEMM_HYBRID,
143 "sve_hybrid_fp32_mla_6x4VL",
Pablo Marquez Telloa50f1932021-03-08 17:27:05 +0000144 [](const GemmArgs &args) { return args._ci->has_sve(); },
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100145 [](const GemmArgs &args) { return GemmHybridIndirect<cls_sve_hybrid_fp32_mla_6x4VL, float, float>::estimate_cycles<float>(args); },
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000146 [](const GemmArgs &args) { return new GemmHybridIndirect<cls_sve_hybrid_fp32_mla_6x4VL, float, float>(args); }
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100147),
148GemmImplementation<float, float>::with_estimate(
149 GemmMethod::GEMM_INTERLEAVED,
150 "sve_interleaved_fp32_mla_8x3VL",
151 [](const GemmArgs &args) { return args._ci->has_sve(); },
152 [](const GemmArgs &args) { return GemmInterleaved<cls_sve_interleaved_fp32_mla_8x3VL, float, float>::estimate_cycles<float>(args); },
153 [](const GemmArgs &args) { return new GemmInterleaved<cls_sve_interleaved_fp32_mla_8x3VL, float, float>(args); }
154),
Michalis Spyrou20fca522021-06-07 14:23:57 +0100155#endif // ARM_COMPUTE_ENABLE_SVE
Michalis Spyrou778b95c2021-04-20 12:15:52 +0100156// Cortex-A35 specific kernel - use for any problem on A35, and never in any other cases.
157{
158 GemmMethod::GEMM_INTERLEAVED,
159 "a64_sgemm_8x6",
160 nullptr,
161 [](const GemmArgs &args) { return args._ci->get_cpu_model() == CPUModel::A35; },
162 [](const GemmArgs &args) { return new GemmInterleaved<cls_a64_sgemm_8x6, float, float>(args); }
163},
Michele Di Giorgio33f41fa2021-03-09 14:09:08 +0000164// Arm® Neon™ hybrid methods
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000165{
166 GemmMethod::GEMM_HYBRID,
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000167 "a64_smallK_hybrid_fp32_mla_8x4",
168 [](const GemmArgs &args) { return args._Ksize <= 8 && (args._Nsize % 4)==0 && !args._indirect_input; },
Georgios Pinitas48b3ef82019-10-14 19:03:09 +0100169 nullptr,
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000170 [](const GemmArgs &args) { return new GemmHybrid<cls_a64_smallK_hybrid_fp32_mla_8x4, float, float>(args); }
Georgios Pinitas48b3ef82019-10-14 19:03:09 +0100171},
172{
173 GemmMethod::GEMM_HYBRID,
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000174 "a64_smallK_hybrid_fp32_mla_6x4",
175 [](const GemmArgs &args) { return (args._Ksize > 8 && args._Ksize <= 16) && (args._Nsize % 4)==0 && !args._indirect_input; },
Georgios Pinitas48b3ef82019-10-14 19:03:09 +0100176 nullptr,
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000177 [](const GemmArgs &args) { return new GemmHybrid<cls_a64_smallK_hybrid_fp32_mla_6x4, float, float>(args); }
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000178},
179{
Georgios Pinitas14613832019-03-01 19:07:11 +0000180 GemmMethod::GEMM_HYBRID,
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000181 "a64_hybrid_fp32_mla_8x4",
182 nullptr,
Michalis Spyrou71ac9032019-11-14 14:31:44 +0000183 [](const GemmArgs &args) { return (args._Nsize < 12); },
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000184 [](const GemmArgs &args) { return new GemmHybridIndirect<cls_a64_hybrid_fp32_mla_8x4, float, float>(args); }
Michalis Spyrou71ac9032019-11-14 14:31:44 +0000185},
David Mansell318c9f42020-07-08 13:28:45 +0100186GemmImplementation<float, float>::with_estimate(
Michalis Spyrou71ac9032019-11-14 14:31:44 +0000187 GemmMethod::GEMM_HYBRID,
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100188 "a64_hybrid_fp32_mla_4x24",
189 nullptr,
190 [](const GemmArgs &args) { return GemmHybridIndirect<cls_a64_hybrid_fp32_mla_4x24, float, float>::estimate_cycles<float>(args); },
191 [](const GemmArgs &args) { return new GemmHybridIndirect<cls_a64_hybrid_fp32_mla_4x24, float, float>(args); }
192),
193GemmImplementation<float, float>::with_estimate(
194 GemmMethod::GEMM_HYBRID,
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000195 "a64_hybrid_fp32_mla_6x16",
196 nullptr,
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100197 [](const GemmArgs &args) { return GemmHybridIndirect<cls_a64_hybrid_fp32_mla_6x16, float, float>::estimate_cycles<float>(args); },
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000198 [](const GemmArgs &args) { return new GemmHybridIndirect<cls_a64_hybrid_fp32_mla_6x16, float, float>(args); }
David Mansell318c9f42020-07-08 13:28:45 +0100199),
David Mansell318c9f42020-07-08 13:28:45 +0100200GemmImplementation<float, float>::with_estimate(
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000201 GemmMethod::GEMM_INTERLEAVED,
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000202 "a64_sgemm_8x12",
Gian Marco Iodice463f9762020-05-19 14:12:27 +0100203 nullptr,
Georgios Pinitas4ee8b152021-07-16 16:16:43 +0100204 [](const GemmArgs &args) { return GemmInterleaved<cls_a64_sgemm_8x12, float, float>::estimate_cycles<float>(args); },
Georgios Pinitasc0b6f762020-11-02 01:37:17 +0000205 [](const GemmArgs &args) { return new GemmInterleaved<cls_a64_sgemm_8x12, float, float>(args); }
David Mansell318c9f42020-07-08 13:28:45 +0100206),
David Manselle39334c2018-07-06 17:53:35 +0100207#endif // __aarch64__
208
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000209#ifdef __arm__
Georgios Pinitascfa2bba2019-06-27 17:00:52 +0100210{
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000211 GemmMethod::GEMM_INTERLEAVED,
212 "sgemm_8x6",
213 nullptr,
214 nullptr,
Georgios Pinitas48b3ef82019-10-14 19:03:09 +0100215 [](const GemmArgs &args) { return new GemmInterleaved<sgemm_8x6, float, float>(args); }
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000216},
217#endif // __arm__
218{
219 GemmMethod::DEFAULT,
220 "",
221 nullptr,
222 nullptr,
223 nullptr
224}
David Manselle39334c2018-07-06 17:53:35 +0100225};
226
227/* Templated function to return this list. */
228template<>
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000229const GemmImplementation<float, float> *gemm_implementation_list<float, float>() {
230 return gemm_fp32_methods;
Pablo Telloeb82fd22018-02-23 13:43:50 +0000231}
232
David Manselle39334c2018-07-06 17:53:35 +0100233/* Explicitly instantiate the external functions for these types. */
Georgios Pinitas48b3ef82019-10-14 19:03:09 +0100234template UniqueGemmCommon<float, float> gemm<float, float, Nothing>(const GemmArgs &args, const Nothing &);
235template KernelDescription get_gemm_method<float, float, Nothing>(const GemmArgs &args, const Nothing &);
236template std::vector<KernelDescription> get_compatible_kernels<float, float, Nothing> (const GemmArgs &args, const Nothing &);
Pablo Telloeb82fd22018-02-23 13:43:50 +0000237
Georgios Pinitas14613832019-03-01 19:07:11 +0000238} // namespace arm_gemm