char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
b91020089
char/aliceai-t5-moe
1// Copyright 2024 Mozilla Foundation 2// 3// Permission is hereby granted, free of charge, to any person obtaining 4// a copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to 8// permit persons to whom the Software is furnished to do so, subject to 9// the following conditions: 10// 11// The above copyright notice and this permission notice shall be 12// included in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 18// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21// SOFTWARE. 22 23// 24// _ _ ___ _ _ ___ 25// | |_(_)_ _ _ _| _ ) | /_\ / __| 26// | _| | ' \ || | _ \ |__ / _ \\__ \. 27// \__|_|_||_\_, |___/____/_/ \_\___/ 28// |__/ 29// 30// BASIC LINEAR ALGEBRA SUBPROGRAMS 31// 32// 33// This file implements multithreaded CPU matrix multiplication for the 34// common contiguous use case C = Aᵀ * B. These kernels are designed to 35// have excellent performance[1] for matrices that fit in the CPU cache 36// without imposing any overhead such as cache filling or malloc calls. 37// 38// This implementation does not guarantee any upper bound with rounding 39// errors, which grow along with k. Our goal's to maximally exploit the 40// hardware for performance, and then use whatever resources remain for 41// improving numerical accuracy. 42// 43// [1] J. Tunney, ‘LLaMA Now Goes Faster on CPUs’, Mar. 2024. [Online]. 44// Available: https://justine.lol/matmul/. [Accessed: 29-Mar-2024]. 45 46#if defined(__GNUC__ ) 47#pragma GCC diagnostic ignored "-Wpedantic" 48#pragma GCC diagnostic ignored "-Wignored-attributes" 49#endif 50 51#include "sgemm.h" 52#include "ggml-impl.h" 53#include "ggml-cpu-impl.h" 54#include "ggml-quants.h" 55#include "simd-mappings.h" 56 57#include <array> 58#include <type_traits> 59 60#ifdef _MSC_VER 61#define NOINLINE __declspec(noinline) 62#else 63#define NOINLINE __attribute__((__noinline__)) 64#endif 65 66#if defined(__ARM_NEON )|| defined(__AVX512F__ )|| defined(__VXE__ )|| defined(__VXE2__ ) 67#define VECTOR_REGISTERS 32 68#else 69#define VECTOR_REGISTERS 16 70#endif 71 72#if defined(__riscv_v_intrinsic ) 73#define LMUL 4 74#endif 75 76#define MM256_SET_M128I (a ,b ) _mm256_insertf128_si256(_mm256_castsi128_si256(b), (a), 1) 77 78namespace { 79 80inline float unhalf (ggml_fp16_t d ) { 81return GGML_CPU_FP16_TO_FP32 (d ); 82} 83 84//////////////////////////////////////////////////////////////////////////////////////////////////// 85// VECTORIZED ARITHMETIC OPERATIONS 86 87#if defined(__SSE__ )|| defined(__AVX__ )|| defined(__AVX2__ )|| defined(__AVX512F__ ) 88inline __m128 add (__m128 x ,__m128 y ) {return _mm_add_ps (x ,y ); } 89inline __m128 sub (__m128 x ,__m128 y ) {return _mm_sub_ps (x ,y ); } 90inline __m128 mul (__m128 x ,__m128 y ) {return _mm_mul_ps (x ,y ); } 91#endif // __SSE__ 92 93#if defined(__AVX__ )|| defined(__AVX2__ )|| defined(__AVX512F__ ) 94inline __m256 add (__m256 x ,__m256 y ) {return _mm256_add_ps (x ,y ); } 95inline __m256 sub (__m256 x ,__m256 y ) {return _mm256_sub_ps (x ,y ); } 96inline __m256 mul (__m256 x ,__m256 y ) {return _mm256_mul_ps (x ,y ); } 97#endif // __AVX__ 98 99#if defined(__AVX512F__ ) 100inline __m512 add (__m512 x ,__m512 y ) {return _mm512_add_ps (x ,y ); } 101inline __m512 sub (__m512 x ,__m512 y ) {return _mm512_sub_ps (x ,y ); } 102inline __m512 mul (__m512 x ,__m512 y ) {return _mm512_mul_ps (x ,y ); } 103#endif // __AVX512F__ 104 105#if defined(__ARM_NEON ) 106inline float32x4_t add (float32x4_t x ,float32x4_t y ) {return vaddq_f32 (x ,y ); } 107inline float32x4_t sub (float32x4_t x ,float32x4_t y ) {return vsubq_f32 (x ,y ); } 108inline float32x4_t mul (float32x4_t x ,float32x4_t y ) {return vmulq_f32 (x ,y ); } 109#endif // __ARM_NEON 110 111#if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC ) 112inline float16x8_t add (float16x8_t x ,float16x8_t y ) {return vaddq_f16 (x ,y ); } 113inline float16x8_t sub (float16x8_t x ,float16x8_t y ) {return vsubq_f16 (x ,y ); } 114inline float16x8_t mul (float16x8_t x ,float16x8_t y ) {return vmulq_f16 (x ,y ); } 115#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 116 117#if defined(__VXE__ )|| defined(__VXE2__ ) 118inline float32x4_t add (float32x4_t x ,float32x4_t y ) {return vec_add (x ,y ); } 119inline float32x4_t sub (float32x4_t x ,float32x4_t y ) {return vec_sub (x ,y ); } 120inline float32x4_t mul (float32x4_t x ,float32x4_t y ) {return vec_mul (x ,y ); } 121#endif 122 123#if defined(__MMA__ ) 124typedef vector unsigned char vec_t ; 125typedef __vector_quad acc_t ; 126#endif 127//////////////////////////////////////////////////////////////////////////////////////////////////// 128// VECTORIZED FUSED MULTIPLY ADD 129 130/** 131* Computes a * b + c. 132*/ 133template < typename T ,typename U > 134inline U madd (T a ,T b ,U c ) { 135return add (mul (a ,b ),c ); 136} 137 138#if defined(__FMA__ ) 139#if defined(__AVX__ )|| defined(__AVX2__ )|| defined(__AVX512F__ ) 140template <> 141inline __m256 madd (__m256 a ,__m256 b ,__m256 c ) { 142return _mm256_fmadd_ps (a ,b ,c ); 143} 144#endif 145#if defined(__AVX512F__ ) 146template <> 147inline __m512 madd (__m512 a ,__m512 b ,__m512 c ) { 148return _mm512_fmadd_ps (a ,b ,c ); 149} 150#endif 151#if defined(__AVX512BF16__ ) 152template <> 153inline __m512 madd (__m512bh a ,__m512bh b ,__m512 c ) { 154return _mm512_dpbf16_ps (c ,a ,b ); 155} 156template <> 157inline __m256 madd (__m256bh a ,__m256bh b ,__m256 c ) { 158return _mm256_dpbf16_ps (c ,a ,b ); 159} 160#endif 161#endif 162 163#if defined(__ARM_FEATURE_FMA ) 164template <> 165inline float32x4_t madd (float32x4_t a ,float32x4_t b ,float32x4_t c ) { 166return vfmaq_f32 (c ,b ,a ); 167} 168#if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC )&& !defined(_MSC_VER ) 169template <> 170inline float16x8_t madd (float16x8_t a ,float16x8_t b ,float16x8_t c ) { 171return vfmaq_f16 (c ,b ,a ); 172} 173#endif 174#endif 175 176#if defined(__VXE__ )|| defined(__VXE2__ ) 177template <> 178inline float32x4_t madd (float32x4_t a ,float32x4_t b ,float32x4_t c ) { 179return vec_madd (a ,b ,c ); 180} 181#endif 182 183#if defined(__riscv_v_intrinsic ) 184template <> inline vfloat32m1_t madd (vfloat32m1_t a ,vfloat32m1_t b ,vfloat32m1_t c ) { 185return __riscv_vfmacc_vv_f32m1 (c ,a ,b ,__riscv_vsetvlmax_e32m1 ()); 186} 187template <> inline vfloat32m2_t madd (vfloat32m2_t a ,vfloat32m2_t b ,vfloat32m2_t c ) { 188return __riscv_vfmacc_vv_f32m2 (c ,a ,b ,__riscv_vsetvlmax_e32m2 ()); 189} 190template <> inline vfloat32m4_t madd (vfloat32m4_t a ,vfloat32m4_t b ,vfloat32m4_t c ) { 191return __riscv_vfmacc_vv_f32m4 (c ,a ,b ,__riscv_vsetvlmax_e32m4 ()); 192} 193template <> inline vfloat32m8_t madd (vfloat32m8_t a ,vfloat32m8_t b ,vfloat32m8_t c ) { 194return __riscv_vfmacc_vv_f32m8 (c ,a ,b ,__riscv_vsetvlmax_e32m8 ()); 195} 196#endif 197 198#if defined(__riscv_zvfh ) 199template <> inline vfloat32m1_t madd (vfloat16mf2_t a ,vfloat16mf2_t b ,vfloat32m1_t c ) { 200return __riscv_vfwmacc_vv_f32m1 (c ,a ,b ,__riscv_vsetvlmax_e32m1 ()); 201} 202template <> inline vfloat32m2_t madd (vfloat16m1_t a ,vfloat16m1_t b ,vfloat32m2_t c ) { 203return __riscv_vfwmacc_vv_f32m2 (c ,a ,b ,__riscv_vsetvlmax_e32m2 ()); 204} 205template <> inline vfloat32m4_t madd (vfloat16m2_t a ,vfloat16m2_t b ,vfloat32m4_t c ) { 206return __riscv_vfwmacc_vv_f32m4 (c ,a ,b ,__riscv_vsetvlmax_e32m4 ()); 207} 208template <> inline vfloat32m8_t madd (vfloat16m4_t a ,vfloat16m4_t b ,vfloat32m8_t c ) { 209return __riscv_vfwmacc_vv_f32m8 (c ,a ,b ,__riscv_vsetvlmax_e32m8 ()); 210} 211#endif 212 213#if defined(__riscv_zvfbfwma ) 214template <> inline vfloat32m1_t madd (vbfloat16mf2_t a ,vbfloat16mf2_t b ,vfloat32m1_t c ) { 215return __riscv_vfwmaccbf16_vv_f32m1 (c ,a ,b ,__riscv_vsetvlmax_e32m1 ()); 216} 217template <> inline vfloat32m2_t madd (vbfloat16m1_t a ,vbfloat16m1_t b ,vfloat32m2_t c ) { 218return __riscv_vfwmaccbf16_vv_f32m2 (c ,a ,b ,__riscv_vsetvlmax_e32m2 ()); 219} 220template <> inline vfloat32m4_t madd (vbfloat16m2_t a ,vbfloat16m2_t b ,vfloat32m4_t c ) { 221return __riscv_vfwmaccbf16_vv_f32m4 (c ,a ,b ,__riscv_vsetvlmax_e32m4 ()); 222} 223template <> inline vfloat32m8_t madd (vbfloat16m4_t a ,vbfloat16m4_t b ,vfloat32m8_t c ) { 224return __riscv_vfwmaccbf16_vv_f32m8 (c ,a ,b ,__riscv_vsetvlmax_e32m8 ()); 225} 226#endif 227 228//////////////////////////////////////////////////////////////////////////////////////////////////// 229// VECTORIZED HORIZONTAL SUM 230 231#if defined(__ARM_NEON ) 232inline float hsum (float32x4_t x ) { 233return vaddvq_f32 (x ); 234} 235#endif // __ARM_NEON 236 237#if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC )&& !defined(_MSC_VER ) 238inline float hsum (float16x8_t x ) { 239return vaddvq_f32 (vaddq_f32 (vcvt_f32_f16 (vget_low_f16 (x )), 240vcvt_f32_f16 (vget_high_f16 (x )))); 241} 242#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 243 244#if defined(__VXE__ )|| defined(__VXE2__ ) 245inline float hsum (float32x4_t x ) { 246float32x4_t tmp = x + vec_reve (x ); 247return tmp [0 ]+ tmp [1 ]; 248} 249#endif 250 251#if defined(__SSE__ )|| defined(__AVX__ )|| defined(__AVX2__ )|| defined(__AVX512F__ ) 252inline float hsum (__m128 x ) { 253#if defined(__AVX__ )|| defined(__AVX2__ )|| defined(__AVX512F__ ) 254x = _mm_add_ps (x ,_mm_movehl_ps (x ,x )); 255x = _mm_add_ss (x ,_mm_movehdup_ps (x )); 256#else 257__m128 t ; 258t = _mm_shuffle_ps (x ,x ,_MM_SHUFFLE (2 ,3 ,0 ,1 )); 259x = _mm_add_ps (x ,t ); 260t = _mm_movehl_ps (t ,x ); 261x = _mm_add_ss (x ,t ); 262#endif 263return _mm_cvtss_f32 (x ); 264} 265#endif 266 267#if defined(__AVX__ )|| defined(__AVX2__ )|| defined(__AVX512F__ ) 268inline float hsum (__m256 x ) { 269return hsum (_mm_add_ps (_mm256_extractf128_ps (x ,1 ), 270_mm256_castps256_ps128 (x ))); 271} 272#endif // __AVX__ 273 274#if defined(__AVX512F__ ) 275inline float hsum (__m512 x ) { 276return _mm512_reduce_add_ps (x ); 277} 278#endif // __AVX512F__ 279 280#if defined(__riscv_v_intrinsic ) 281inline float hsum (vfloat32m1_t x ) { 282return __riscv_vfmv_f_s_f32m1_f32 ( 283__riscv_vfredusum_vs_f32m1_f32m1 (x ,__riscv_vfmv_v_f_f32m1 (0 ,1 ),__riscv_vsetvlmax_e32m1 ())); 284} 285inline float hsum (vfloat32m2_t x ) { 286return __riscv_vfmv_f_s_f32m1_f32 ( 287__riscv_vfredusum_vs_f32m2_f32m1 (x ,__riscv_vfmv_v_f_f32m1 (0 ,1 ),__riscv_vsetvlmax_e32m2 ())); 288} 289inline float hsum (vfloat32m4_t x ) { 290return __riscv_vfmv_f_s_f32m1_f32 ( 291__riscv_vfredusum_vs_f32m4_f32m1 (x ,__riscv_vfmv_v_f_f32m1 (0 ,1 ),__riscv_vsetvlmax_e32m4 ())); 292} 293inline float hsum (vfloat32m8_t x ) { 294return __riscv_vfmv_f_s_f32m1_f32 ( 295__riscv_vfredusum_vs_f32m8_f32m1 (x ,__riscv_vfmv_v_f_f32m1 (0 ,1 ),__riscv_vsetvlmax_e32m8 ())); 296} 297#endif 298 299//////////////////////////////////////////////////////////////////////////////////////////////////// 300// VECTORIZED MEMORY LOADING 301 302template < typename T ,typename U > T load (const U * ); 303 304#if defined(__ARM_NEON ) 305template <> inline float32x4_t load (const float * p ) { 306return vld1q_f32 (p ); 307} 308#if !defined(_MSC_VER ) 309// FIXME: this should check for __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 310template <> inline float16x8_t load (const ggml_fp16_t * p ) { 311return vld1q_f16 ((const float16_t * )p ); 312} 313template <> inline float32x4_t load (const ggml_fp16_t * p ) { 314return vcvt_f32_f16 (vld1_f16 ((const float16_t * )p )); 315} 316#endif // _MSC_VER 317#endif // __ARM_NEON 318 319#if defined(__VXE__ )|| defined(__VXE2__ ) 320template <> inline float32x4_t load (const ggml_fp16_t * p ) { 321float tmp [4 ]; 322 323for (int i = 0 ;i < 4 ;i ++ ) { 324tmp [i ]= GGML_CPU_FP16_TO_FP32 (p [i ]); 325 } 326 327return vec_xl (0 , (const float * )(tmp )); 328} 329template <> inline float32x4_t load (const float * p ) { 330return vec_xl (0 ,p ); 331} 332#endif 333 334#if defined(__SSE__ )|| defined(__AVX__ )|| defined(__AVX2__ )|| defined(__AVX512F__ ) 335template <> inline __m128 load (const float * p ) { 336return _mm_loadu_ps (p ); 337} 338#endif // __SSE__ 339 340#if defined(__AVX__ )|| defined(__AVX2__ )|| defined(__AVX512F__ ) 341template <> inline __m256 load (const float * p ) { 342return _mm256_loadu_ps (p ); 343} 344#endif // __AVX__ 345 346#if defined(__AVX2__ )|| defined(__AVX512F__ ) 347template <> inline __m256 load (const ggml_bf16_t * p ) { 348return _mm256_castsi256_ps ( 349_mm256_slli_epi32 (_mm256_cvtepu16_epi32 (_mm_loadu_si128 ((const __m128i * )p )),16 )); 350} 351#endif // __AVX2__ 352 353#if defined(__F16C__ ) 354template <> inline __m256 load (const ggml_fp16_t * p ) { 355return _mm256_cvtph_ps (_mm_loadu_si128 ((const __m128i * )p )); 356} 357#endif // __F16C__ 358 359#if defined(__AVX512F__ ) 360template <> inline __m512 load (const float * p ) { 361return _mm512_loadu_ps (p ); 362} 363template <> inline __m512 load (const ggml_fp16_t * p ) { 364return _mm512_cvtph_ps (_mm256_loadu_si256 ((const __m256i * )p )); 365} 366template <> inline __m512 load (const ggml_bf16_t * p ) { 367return _mm512_castsi512_ps ( 368_mm512_slli_epi32 (_mm512_cvtepu16_epi32 (_mm256_loadu_si256 ((const __m256i * )p )),16 )); 369} 370#endif // __AVX512F__ 371 372#if defined(__AVX512BF16__ ) 373template <> inline __m512bh load (const ggml_bf16_t * p ) { 374return (__m512bh )_mm512_loadu_ps ((const float * )p ); 375} 376template <> inline __m256bh load (const ggml_bf16_t * p ) { 377return (__m256bh )_mm256_loadu_ps ((const float * )p ); 378} 379template <> inline __m512bh load (const float * p ) { 380return _mm512_cvtne2ps_pbh (_mm512_loadu_ps (p + 16 ),_mm512_loadu_ps (p )); 381} 382template <> inline __m256bh load (const float * p ) { 383return _mm512_cvtneps_pbh (_mm512_loadu_ps (p )); 384} 385#endif 386 387#if defined(__riscv_v_intrinsic ) 388template <> inline vfloat32m1_t load (const float * p ) { 389return __riscv_vle32_v_f32m1 (p ,__riscv_vsetvlmax_e32m1 ()); 390} 391template <> inline vfloat32m2_t load (const float * p ) { 392return __riscv_vle32_v_f32m2 (p ,__riscv_vsetvlmax_e32m2 ()); 393} 394template <> inline vfloat32m4_t load (const float * p ) { 395return __riscv_vle32_v_f32m4 (p ,__riscv_vsetvlmax_e32m4 ()); 396} 397template <> inline vfloat32m8_t load (const float * p ) { 398return __riscv_vle32_v_f32m8 (p ,__riscv_vsetvlmax_e32m8 ()); 399} 400#endif 401 402#if defined(__riscv_zvfh ) 403template <> inline vfloat16mf2_t load (const ggml_fp16_t * p ) { 404return __riscv_vle16_v_f16mf2 (reinterpret_cast < const _Float16 *> (p ),__riscv_vsetvlmax_e16mf2 ()); 405} 406template <> inline vfloat16m1_t load (const ggml_fp16_t * p ) { 407return __riscv_vle16_v_f16m1 (reinterpret_cast < const _Float16 *> (p ),__riscv_vsetvlmax_e16m1 ()); 408} 409template <> inline vfloat16m2_t load (const ggml_fp16_t * p ) { 410return __riscv_vle16_v_f16m2 (reinterpret_cast < const _Float16 *> (p ),__riscv_vsetvlmax_e16m2 ()); 411} 412template <> inline vfloat16m4_t load (const ggml_fp16_t * p ) { 413return __riscv_vle16_v_f16m4 (reinterpret_cast < const _Float16 *> (p ),__riscv_vsetvlmax_e16m4 ()); 414} 415#endif 416 417#if defined(__riscv_zvfbfwma ) 418template <> inline vbfloat16mf2_t load (const ggml_bf16_t * p ) { 419return __riscv_vle16_v_bf16mf2 (reinterpret_cast < const __bf16 *> (p ),__riscv_vsetvlmax_e16mf2 ()); 420} 421template <> inline vbfloat16m1_t load (const ggml_bf16_t * p ) { 422return __riscv_vle16_v_bf16m1 (reinterpret_cast < const __bf16 *> (p ),__riscv_vsetvlmax_e16m1 ()); 423} 424template <> inline vbfloat16m2_t load (const ggml_bf16_t * p ) { 425return __riscv_vle16_v_bf16m2 (reinterpret_cast < const __bf16 *> (p ),__riscv_vsetvlmax_e16m2 ()); 426} 427template <> inline vbfloat16m4_t load (const ggml_bf16_t * p ) { 428return __riscv_vle16_v_bf16m4 (reinterpret_cast < const __bf16 *> (p ),__riscv_vsetvlmax_e16m4 ()); 429} 430#endif 431 432#if defined(__riscv_v_intrinsic ) 433template < typename T > T set_zero (); 434 435template <> inline vfloat32m1_t set_zero () { 436return __riscv_vfmv_v_f_f32m1 (0.0f ,__riscv_vsetvlmax_e32m1 ()); 437} 438template <> inline vfloat32m2_t set_zero () { 439return __riscv_vfmv_v_f_f32m2 (0 ,__riscv_vsetvlmax_e32m2 ()); 440} 441template <> inline vfloat32m4_t set_zero () { 442return __riscv_vfmv_v_f_f32m4 (0 ,__riscv_vsetvlmax_e32m4 ()); 443} 444template <> inline vfloat32m8_t set_zero () { 445return __riscv_vfmv_v_f_f32m8 (0 ,__riscv_vsetvlmax_e32m8 ()); 446} 447#endif 448 449#if defined(__riscv_v_intrinsic ) 450template < typename T > size_t vlmax () { 451if constexpr (std::is_same_v < T ,vfloat32m1_t > ) {return __riscv_vsetvlmax_e32m1 (); } 452else if constexpr (std::is_same_v < T ,vfloat32m2_t > ) {return __riscv_vsetvlmax_e32m2 (); } 453else if constexpr (std::is_same_v < T ,vfloat32m4_t > ) {return __riscv_vsetvlmax_e32m4 (); } 454else if constexpr (std::is_same_v < T ,vfloat32m8_t > ) {return __riscv_vsetvlmax_e32m8 (); } 455#if defined (__riscv_zvfh ) 456else if constexpr (std::is_same_v < T ,vfloat16mf2_t > ) {return __riscv_vsetvlmax_e16mf2 (); } 457else if constexpr (std::is_same_v < T ,vfloat16m1_t > ) {return __riscv_vsetvlmax_e16m1 (); } 458else if constexpr (std::is_same_v < T ,vfloat16m2_t > ) {return __riscv_vsetvlmax_e16m2 (); } 459else if constexpr (std::is_same_v < T ,vfloat16m4_t > ) {return __riscv_vsetvlmax_e16m4 (); } 460#endif 461#if defined (__riscv_zvfbfwma ) 462else if constexpr (std::is_same_v < T ,vbfloat16mf2_t > ) {return __riscv_vsetvlmax_e16mf2 (); } 463else if constexpr (std::is_same_v < T ,vbfloat16m1_t > ) {return __riscv_vsetvlmax_e16m1 (); } 464else if constexpr (std::is_same_v < T ,vbfloat16m2_t > ) {return __riscv_vsetvlmax_e16m2 (); } 465else if constexpr (std::is_same_v < T ,vbfloat16m4_t > ) {return __riscv_vsetvlmax_e16m4 (); } 466#endif 467return 0 ; 468} 469#endif 470 471//////////////////////////////////////////////////////////////////////////////////////////////////// 472// FLOATING POINT MATRIX MULTIPLICATION 473 474template < int M > 475static inline int64_t BLOCK_SIZE (size_t m ) { 476const int64_t NB_BLOC_M = (m + M - 1 ) /M ; 477return (m %NB_BLOC_M == 0 ) ?m /NB_BLOC_M : (m /NB_BLOC_M )+ 1 ; 478} 479 480static constexpr inline int64_t BLOC_POS (int64_t ib ,int64_t ibN ,int64_t bloc_size ) { 481return ib < ibN ?ib * bloc_size :ibN * bloc_size + (ib - ibN )* (bloc_size - 1 ); 482} 483 484template < int KN ,typename D ,typename V ,typename TA ,typename TB ,typename TC > 485class tinyBLAS { 486public : 487tinyBLAS (const ggml_compute_params * params ,int64_t k , 488const TA * A ,int64_t lda , 489const TB * B ,int64_t ldb , 490TC * C ,int64_t ldc ) 491 :params (params ),A (A ),B (B ),C (C ),k (k ),lda (lda ),ldb (ldb ),ldc (ldc ) { 492 } 493 494bool matmul (int64_t m ,int64_t n ) { 495if (k %KN != 0 ) 496return false; 497// compute RM for only need tile with size RM&RM-1 498#if VECTOR_REGISTERS == 32 499if (m %16 == 0 && (m /16 >=params -> nth )) { 500const int64_t SIZE_N = BLOCK_SIZE < 6 > (n ); 501mnpack < 4 ,6 ,4 > (m ,n ,SIZE_N ,12 ); 502return true; 503 } 504if (m %8 == 0 ) { 505const int64_t SIZE_N = BLOCK_SIZE < 6 > (n ); 506mnpack < 4 ,6 ,2 > (m ,n ,SIZE_N ,12 ); 507return true; 508 } 509if (m %4 == 0 ) { 510const int64_t SIZE_N = BLOCK_SIZE < 6 > (n ); 511mnpack < 4 ,6 ,1 > (m ,n ,SIZE_N ,12 ); 512return true; 513 } 514#else // VECTOR_REGISTERS == 16 515if (m %16 == 0 && (m /16 >=params -> nth )) { 516const int64_t SIZE_N = BLOCK_SIZE < 3 > (n ); 517mnpack < 4 ,3 ,4 > (m ,n ,SIZE_N ,24 ); 518return true; 519 } 520if (m %8 == 0 ) { 521const int64_t SIZE_N = BLOCK_SIZE < 3 > (n ); 522mnpack < 4 ,3 ,2 > (m ,n ,SIZE_N ,24 ); 523return true; 524 } 525if (m %4 == 0 ) { 526const int64_t SIZE_N = BLOCK_SIZE < 3 > (n ); 527mnpack < 4 ,3 ,1 > (m ,n ,SIZE_N ,24 ); 528return true; 529 } 530#endif 531return false; 532 } 533 534private : 535template < int RM ,int RN ,int BM > 536inline void mnpack (int64_t m ,int64_t n ,int64_t SIZE_N ,int64_t BN ) { 537if (SIZE_N == RN ) { 538return gemm < RM ,RN ,BM > (m ,n ,BN ); 539 } 540if constexpr (RN > 1 ) { 541return mnpack < RM ,RN - 1 ,BM > (m ,n ,SIZE_N ,BN ); 542 }else { 543GGML_LOG_ERROR ("mnpack<%d, %d> block size not supported\n" ,RM , (int )SIZE_N ); 544GGML_ASSERT (false);// we have miss something. 545 } 546 } 547 548template < int RM ,int RN > 549inline void gemm_bloc (int64_t ii ,int64_t jj ) { 550D Cv [RN ][RM ]= {}; 551for (int64_t l = 0 ;l < k ;l += KN ) { 552// help compiler for op order. 553if constexpr (RM <=RN ) { 554V Av [RM ]; 555for (int64_t i = 0 ;i < RM ;++ i ) { 556Av [i ]= load < V > (A + lda * (ii + i )+ l ); 557 } 558for (int64_t j = 0 ;j < RN ;++ j ) { 559V Bv = load < V > (B + ldb * (jj + j )+ l ); 560for (int64_t i = 0 ;i < RM ;++ i ) { 561Cv [j ][i ]= madd (Av [i ],Bv ,Cv [j ][i ]); 562 } 563 } 564 }else { 565V Bv [RN ]; 566for (int64_t j = 0 ;j < RN ;++ j ) { 567Bv [j ]= load < V > (B + ldb * (jj + j )+ l ); 568 } 569for (int64_t i = 0 ;i < RM ;++ i ) { 570V Av = load < V > (A + lda * (ii + i )+ l ); 571for (int64_t j = 0 ;j < RN ;++ j ) { 572Cv [j ][i ]= madd (Av ,Bv [j ],Cv [j ][i ]); 573 } 574 } 575 } 576 } 577for (int64_t j = 0 ;j < RN ;++ j ) 578for (int64_t i = 0 ;i < RM ;++ i ) 579C [ldc * (jj + j )+ (ii + i )]= hsum (Cv [j ][i ]); 580 } 581 582template < int RM ,int RN ,int BM > 583NOINLINE void gemm (int64_t m ,int64_t n ,int64_t BN ) { 584GGML_ASSERT (m % (RM * BM )== 0 ); 585const int64_t ytiles = m / (RM * BM ); 586const int64_t xtiles = (n + RN - 1 ) /RN ; 587const int64_t jj_RN = (xtiles - (xtiles * RN - n )); 588 589// "round" bloc_size to "nearest" BN 590const int64_t NB_BN = xtiles < BN ?1 : (xtiles + BN /2 ) /BN ; 591const int64_t SIZE_BN = xtiles %NB_BN == 0 ?xtiles /NB_BN :xtiles /NB_BN + 1 ; 592const int64_t jj_BN = (NB_BN - (NB_BN * SIZE_BN - xtiles )); 593const int64_t nb_job = ytiles * NB_BN ; 594 595if (params -> ith == 0 ) { 596GGML_ASSERT (jj_BN * SIZE_BN + (NB_BN - jj_BN )* (SIZE_BN - 1 )== xtiles ); 597// Every thread starts at ith, so the first unprocessed chunk is nth. This save a bit of coordination right at the start. 598ggml_threadpool_chunk_set (params -> threadpool ,params -> nth ); 599 } 600 601ggml_barrier (params -> threadpool ); 602 603int64_t job = params -> ith ; 604while (job < nb_job ) { 605const int64_t ii = (job %ytiles )* RM * BM ; 606const int64_t jb = job /ytiles ; 607const int64_t jr0 = BLOC_POS (jb ,jj_BN ,SIZE_BN ); 608const int64_t jrN = BLOC_POS (jb + 1 ,jj_BN ,SIZE_BN ); 609 610const int64_t jj0 = BLOC_POS (jr0 ,jj_RN ,RN ); 611const int64_t jj2 = BLOC_POS (jrN ,jj_RN ,RN ); 612const int64_t jj1 = jj2 < jj_RN * RN ?jj2 :jj_RN * RN ; 613 614for (int64_t bi = 0 ;bi < BM * RM ;bi += RM ) { 615int64_t jj = jj0 ; 616for (;jj < jj1 ;jj += RN ) { 617gemm_bloc < RM ,RN > (ii + bi ,jj ); 618 } 619if constexpr (RN > 1 ) { 620for (;jj < jj2 ;jj += RN - 1 ) { 621gemm_bloc < RM ,RN - 1 > (ii + bi ,jj ); 622 } 623 } 624GGML_ASSERT (jj == jj2 ); 625 } 626 627job = ggml_threadpool_chunk_add (params -> threadpool ,1 ); 628 } 629 630ggml_barrier (params -> threadpool ); 631return ; 632 } 633 634const ggml_compute_params * params ; 635const TA * const A ; 636const TB * const B ; 637TC * const C ; 638const int64_t k ; 639const int64_t lda ; 640const int64_t ldb ; 641const int64_t ldc ; 642}; 643 644#if defined(__riscv_v_intrinsic ) 645template < typename D ,typename V ,typename TA ,typename TB ,typename TC > 646class tinyBLAS_RVV { 647public : 648tinyBLAS_RVV (const ggml_compute_params * params ,int64_t k , 649const TA * A ,int64_t lda , 650const TB * B ,int64_t ldb , 651TC * C ,int64_t ldc ) 652 :params (params ),A (A ),B (B ),C (C ),k (k ),lda (lda ),ldb (ldb ),ldc (ldc ) { 653 } 654 655bool matmul (int64_t m ,int64_t n ) { 656if (k %vlmax < V > ()!= 0 ) { 657return false; 658 } 659 660#if LMUL == 1 661if (m %16 == 0 && (m /16 >=params -> nth )) { 662const int64_t SIZE_N = BLOCK_SIZE < 6 > (n ); 663mnpack < 4 ,6 ,4 > (m ,n ,SIZE_N ,12 ); 664return true; 665 } 666if (m %8 == 0 ) { 667const int64_t SIZE_N = BLOCK_SIZE < 6 > (n ); 668mnpack < 4 ,6 ,2 > (m ,n ,SIZE_N ,12 ); 669return true; 670 } 671if (m %4 == 0 ) { 672const int64_t SIZE_N = BLOCK_SIZE < 6 > (n ); 673mnpack < 4 ,6 ,1 > (m ,n ,SIZE_N ,12 ); 674return true; 675 } 676#elif LMUL == 2 677if (m %16 == 0 && (m /16 >=params -> nth )) { 678const int64_t SIZE_N = BLOCK_SIZE < 3 > (n ); 679mnpack < 4 ,3 ,4 > (m ,n ,SIZE_N ,24 ); 680return true; 681 } 682if (m %8 == 0 ) { 683const int64_t SIZE_N = BLOCK_SIZE < 3 > (n ); 684mnpack < 4 ,3 ,2 > (m ,n ,SIZE_N ,24 ); 685return true; 686 } 687if (m %4 == 0 ) { 688const int64_t SIZE_N = BLOCK_SIZE < 3 > (n ); 689mnpack < 4 ,3 ,1 > (m ,n ,SIZE_N ,24 ); 690return true; 691 } 692#else // LMUL = 4 693if (m %16 == 0 && (m /16 >=params -> nth )) { 694const int64_t SIZE_N = BLOCK_SIZE < 2 > (n ); 695mnpack < 2 ,2 ,8 > (m ,n ,SIZE_N ,36 ); 696return true; 697 } 698if (m %8 == 0 ) { 699const int64_t SIZE_N = BLOCK_SIZE < 2 > (n ); 700mnpack < 2 ,2 ,4 > (m ,n ,SIZE_N ,36 ); 701return true; 702 } 703if (m %4 == 0 ) { 704const int64_t SIZE_N = BLOCK_SIZE < 2 > (n ); 705mnpack < 2 ,2 ,2 > (m ,n ,SIZE_N ,36 ); 706return true; 707 } 708#endif 709return false; 710 } 711 712private : 713template < int RM ,int RN ,int BM > 714inline void mnpack (int64_t m ,int64_t n ,int64_t SIZE_N ,int64_t BN ) { 715if (SIZE_N == RN ) { 716return gemm < RM ,RN ,BM > (m ,n ,BN ); 717 } 718if constexpr (RN > 1 ) { 719return mnpack < RM ,RN - 1 ,BM > (m ,n ,SIZE_N ,BN ); 720 }else { 721GGML_LOG_ERROR ("mnpack<%d, %d> block size not supported\n" ,RM , (int )SIZE_N ); 722GGML_ASSERT (false);// we have miss something. 723 } 724 } 725 726inline void gemm_bloc_4x6 (int64_t ii ,int64_t jj ) { 727size_t vl = vlmax < V > (); 728D Cv00 = set_zero < D > (); 729D Cv01 = set_zero < D > (); 730D Cv02 = set_zero < D > (); 731D Cv03 = set_zero < D > (); 732D Cv10 = set_zero < D > (); 733D Cv11 = set_zero < D > (); 734D Cv12 = set_zero < D > (); 735D Cv13 = set_zero < D > (); 736D Cv20 = set_zero < D > (); 737D Cv21 = set_zero < D > (); 738D Cv22 = set_zero < D > (); 739D Cv23 = set_zero < D > (); 740D Cv30 = set_zero < D > (); 741D Cv31 = set_zero < D > (); 742D Cv32 = set_zero < D > (); 743D Cv33 = set_zero < D > (); 744D Cv40 = set_zero < D > (); 745D Cv41 = set_zero < D > (); 746D Cv42 = set_zero < D > (); 747D Cv43 = set_zero < D > (); 748D Cv50 = set_zero < D > (); 749D Cv51 = set_zero < D > (); 750D Cv52 = set_zero < D > (); 751D Cv53 = set_zero < D > (); 752 753for (int64_t l = 0 ;l < k ;l += vl ) { 754V Bv0 = load < V > (B + ldb * (jj + 0 )+ l ); 755V Bv1 = load < V > (B + ldb * (jj + 1 )+ l ); 756V Bv2 = load < V > (B + ldb * (jj + 2 )+ l ); 757V Bv3 = load < V > (B + ldb * (jj + 3 )+ l ); 758V Bv4 = load < V > (B + ldb * (jj + 4 )+ l ); 759V Bv5 = load < V > (B + ldb * (jj + 5 )+ l ); 760 761V Av0 = load < V > (A + lda * (ii + 0 )+ l ); 762Cv00 = madd (Av0 ,Bv0 ,Cv00 ); 763Cv10 = madd (Av0 ,Bv1 ,Cv10 ); 764Cv20 = madd (Av0 ,Bv2 ,Cv20 ); 765Cv30 = madd (Av0 ,Bv3 ,Cv30 ); 766Cv40 = madd (Av0 ,Bv4 ,Cv40 ); 767Cv50 = madd (Av0 ,Bv5 ,Cv50 ); 768 769V Av1 = load < V > (A + lda * (ii + 1 )+ l ); 770Cv01 = madd (Av1 ,Bv0 ,Cv01 ); 771Cv11 = madd (Av1 ,Bv1 ,Cv11 ); 772Cv21 = madd (Av1 ,Bv2 ,Cv21 ); 773Cv31 = madd (Av1 ,Bv3 ,Cv31 ); 774Cv41 = madd (Av1 ,Bv4 ,Cv41 ); 775Cv51 = madd (Av1 ,Bv5 ,Cv51 ); 776 777V Av2 = load < V > (A + lda * (ii + 2 )+ l ); 778Cv02 = madd (Av2 ,Bv0 ,Cv02 ); 779Cv12 = madd (Av2 ,Bv1 ,Cv12 ); 780Cv22 = madd (Av2 ,Bv2 ,Cv22 ); 781Cv32 = madd (Av2 ,Bv3 ,Cv32 ); 782Cv42 = madd (Av2 ,Bv4 ,Cv42 ); 783Cv52 = madd (Av2 ,Bv5 ,Cv52 ); 784 785V Av3 = load < V > (A + lda * (ii + 3 )+ l ); 786Cv03 = madd (Av3 ,Bv0 ,Cv03 ); 787Cv13 = madd (Av3 ,Bv1 ,Cv13 ); 788Cv23 = madd (Av3 ,Bv2 ,Cv23 ); 789Cv33 = madd (Av3 ,Bv3 ,Cv33 ); 790Cv43 = madd (Av3 ,Bv4 ,Cv43 ); 791Cv53 = madd (Av3 ,Bv5 ,Cv53 ); 792 } 793 794C [ldc * (jj + 0 )+ (ii + 0 )]= hsum (Cv00 ); 795C [ldc * (jj + 0 )+ (ii + 1 )]= hsum (Cv01 ); 796C [ldc * (jj + 0 )+ (ii + 2 )]= hsum (Cv02 ); 797C [ldc * (jj + 0 )+ (ii + 3 )]= hsum (Cv03 ); 798C [ldc * (jj + 1 )+ (ii + 0 )]= hsum (Cv10 ); 799C [ldc * (jj + 1 )+ (ii + 1 )]= hsum (Cv11 ); 800C [ldc * (jj + 1 )+ (ii + 2 )]= hsum (Cv12 ); 801C [ldc * (jj + 1 )+ (ii + 3 )]= hsum (Cv13 ); 802C [ldc * (jj + 2 )+ (ii + 0 )]= hsum (Cv20 ); 803C [ldc * (jj + 2 )+ (ii + 1 )]= hsum (Cv21 ); 804C [ldc * (jj + 2 )+ (ii + 2 )]= hsum (Cv22 ); 805C [ldc * (jj + 2 )+ (ii + 3 )]= hsum (Cv23 ); 806C [ldc * (jj + 3 )+ (ii + 0 )]= hsum (Cv30 ); 807C [ldc * (jj + 3 )+ (ii + 1 )]= hsum (Cv31 ); 808C [ldc * (jj + 3 )+ (ii + 2 )]= hsum (Cv32 ); 809C [ldc * (jj + 3 )+ (ii + 3 )]= hsum (Cv33 ); 810C [ldc * (jj + 4 )+ (ii + 0 )]= hsum (Cv40 ); 811C [ldc * (jj + 4 )+ (ii + 1 )]= hsum (Cv41 ); 812C [ldc * (jj + 4 )+ (ii + 2 )]= hsum (Cv42 ); 813C [ldc * (jj + 4 )+ (ii + 3 )]= hsum (Cv43 ); 814C [ldc * (jj + 5 )+ (ii + 0 )]= hsum (Cv50 ); 815C [ldc * (jj + 5 )+ (ii + 1 )]= hsum (Cv51 ); 816C [ldc * (jj + 5 )+ (ii + 2 )]= hsum (Cv52 ); 817C [ldc * (jj + 5 )+ (ii + 3 )]= hsum (Cv53 ); 818 } 819 820inline void gemm_bloc_4x5 (int64_t ii ,int64_t jj ) { 821size_t vl = vlmax < V > (); 822D Cv00 = set_zero < D > (); 823D Cv01 = set_zero < D > (); 824D Cv02 = set_zero < D > (); 825D Cv03 = set_zero < D > (); 826D Cv10 = set_zero < D > (); 827D Cv11 = set_zero < D > (); 828D Cv12 = set_zero < D > (); 829D Cv13 = set_zero < D > (); 830D Cv20 = set_zero < D > (); 831D Cv21 = set_zero < D > (); 832D Cv22 = set_zero < D > (); 833D Cv23 = set_zero < D > (); 834D Cv30 = set_zero < D > (); 835D Cv31 = set_zero < D > (); 836D Cv32 = set_zero < D > (); 837D Cv33 = set_zero < D > (); 838D Cv40 = set_zero < D > (); 839D Cv41 = set_zero < D > (); 840D Cv42 = set_zero < D > (); 841D Cv43 = set_zero < D > (); 842 843for (int64_t l = 0 ;l < k ;l += vl ) { 844V Bv0 = load < V > (B + ldb * (jj + 0 )+ l ); 845V Bv1 = load < V > (B + ldb * (jj + 1 )+ l ); 846V Bv2 = load < V > (B + ldb * (jj + 2 )+ l ); 847V Bv3 = load < V > (B + ldb * (jj + 3 )+ l ); 848V Bv4 = load < V > (B + ldb * (jj + 4 )+ l ); 849 850V Av0 = load < V > (A + lda * (ii + 0 )+ l ); 851Cv00 = madd (Av0 ,Bv0 ,Cv00 ); 852Cv10 = madd (Av0 ,Bv1 ,Cv10 ); 853Cv20 = madd (Av0 ,Bv2 ,Cv20 ); 854Cv30 = madd (Av0 ,Bv3 ,Cv30 ); 855Cv40 = madd (Av0 ,Bv4 ,Cv40 ); 856 857V Av1 = load < V > (A + lda * (ii + 1 )+ l ); 858Cv01 = madd (Av1 ,Bv0 ,Cv01 ); 859Cv11 = madd (Av1 ,Bv1 ,Cv11 ); 860Cv21 = madd (Av1 ,Bv2 ,Cv21 ); 861Cv31 = madd (Av1 ,Bv3 ,Cv31 ); 862Cv41 = madd (Av1 ,Bv4 ,Cv41 ); 863 864V Av2 = load < V > (A + lda * (ii + 2 )+ l ); 865Cv02 = madd (Av2 ,Bv0 ,Cv02 ); 866Cv12 = madd (Av2 ,Bv1 ,Cv12 ); 867Cv22 = madd (Av2 ,Bv2 ,Cv22 ); 868Cv32 = madd (Av2 ,Bv3 ,Cv32 ); 869Cv42 = madd (Av2 ,Bv4 ,Cv42 ); 870 871V Av3 = load < V > (A + lda * (ii + 3 )+ l ); 872Cv03 = madd (Av3 ,Bv0 ,Cv03 ); 873Cv13 = madd (Av3 ,Bv1 ,Cv13 ); 874Cv23 = madd (Av3 ,Bv2 ,Cv23 ); 875Cv33 = madd (Av3 ,Bv3 ,Cv33 ); 876Cv43 = madd (Av3 ,Bv4 ,Cv43 ); 877 } 878 879C [ldc * (jj + 0 )+ (ii + 0 )]= hsum (Cv00 ); 880C [ldc * (jj + 0 )+ (ii + 1 )]= hsum (Cv01 ); 881C [ldc * (jj + 0 )+ (ii + 2 )]= hsum (Cv02 ); 882C [ldc * (jj + 0 )+ (ii + 3 )]= hsum (Cv03 ); 883C [ldc * (jj + 1 )+ (ii + 0 )]= hsum (Cv10 ); 884C [ldc * (jj + 1 )+ (ii + 1 )]= hsum (Cv11 ); 885C [ldc * (jj + 1 )+ (ii + 2 )]= hsum (Cv12 ); 886C [ldc * (jj + 1 )+ (ii + 3 )]= hsum (Cv13 ); 887C [ldc * (jj + 2 )+ (ii + 0 )]= hsum (Cv20 ); 888C [ldc * (jj + 2 )+ (ii + 1 )]= hsum (Cv21 ); 889C [ldc * (jj + 2 )+ (ii + 2 )]= hsum (Cv22 ); 890C [ldc * (jj + 2 )+ (ii + 3 )]= hsum (Cv23 ); 891C [ldc * (jj + 3 )+ (ii + 0 )]= hsum (Cv30 ); 892C [ldc * (jj + 3 )+ (ii + 1 )]= hsum (Cv31 ); 893C [ldc * (jj + 3 )+ (ii + 2 )]= hsum (Cv32 ); 894C [ldc * (jj + 3 )+ (ii + 3 )]= hsum (Cv33 ); 895C [ldc * (jj + 4 )+ (ii + 0 )]= hsum (Cv40 ); 896C [ldc * (jj + 4 )+ (ii + 1 )]= hsum (Cv41 ); 897C [ldc * (jj + 4 )+ (ii + 2 )]= hsum (Cv42 ); 898C [ldc * (jj + 4 )+ (ii + 3 )]= hsum (Cv43 ); 899 } 900 901inline void gemm_bloc_4x4 (int64_t ii ,int64_t jj ) { 902size_t vl = vlmax < V > (); 903D Cv00 = set_zero < D > (); 904D Cv01 = set_zero < D > (); 905D Cv02 = set_zero < D > (); 906D Cv03 = set_zero < D > (); 907D Cv10 = set_zero < D > (); 908D Cv11 = set_zero < D > (); 909D Cv12 = set_zero < D > (); 910D Cv13 = set_zero < D > (); 911D Cv20 = set_zero < D > (); 912D Cv21 = set_zero < D > (); 913D Cv22 = set_zero < D > (); 914D Cv23 = set_zero < D > (); 915D Cv30 = set_zero < D > (); 916D Cv31 = set_zero < D > (); 917D Cv32 = set_zero < D > (); 918D Cv33 = set_zero < D > (); 919 920for (int64_t l = 0 ;l < k ;l += vl ) { 921V Av0 = load < V > (A + lda * (ii + 0 )+ l ); 922V Av1 = load < V > (A + lda * (ii + 1 )+ l ); 923V Av2 = load < V > (A + lda * (ii + 2 )+ l ); 924V Av3 = load < V > (A + lda * (ii + 3 )+ l ); 925 926V Bv0 = load < V > (B + ldb * (jj + 0 )+ l ); 927Cv00 = madd (Av0 ,Bv0 ,Cv00 ); 928Cv01 = madd (Av1 ,Bv0 ,Cv01 ); 929Cv02 = madd (Av2 ,Bv0 ,Cv02 ); 930Cv03 = madd (Av3 ,Bv0 ,Cv03 ); 931 932V Bv1 = load < V > (B + ldb * (jj + 1 )+ l ); 933Cv10 = madd (Av0 ,Bv1 ,Cv10 ); 934Cv11 = madd (Av1 ,Bv1 ,Cv11 ); 935Cv12 = madd (Av2 ,Bv1 ,Cv12 ); 936Cv13 = madd (Av3 ,Bv1 ,Cv13 ); 937 938V Bv2 = load < V > (B + ldb * (jj + 2 )+ l ); 939Cv20 = madd (Av0 ,Bv2 ,Cv20 ); 940Cv21 = madd (Av1 ,Bv2 ,Cv21 ); 941Cv22 = madd (Av2 ,Bv2 ,Cv22 ); 942Cv23 = madd (Av3 ,Bv2 ,Cv23 ); 943 944V Bv3 = load < V > (B + ldb * (jj + 3 )+ l ); 945Cv30 = madd (Av0 ,Bv3 ,Cv30 ); 946Cv31 = madd (Av1 ,Bv3 ,Cv31 ); 947Cv32 = madd (Av2 ,Bv3 ,Cv32 ); 948Cv33 = madd (Av3 ,Bv3 ,Cv33 ); 949 } 950 951C [ldc * (jj + 0 )+ (ii + 0 )]= hsum (Cv00 ); 952C [ldc * (jj + 0 )+ (ii + 1 )]= hsum (Cv01 ); 953C [ldc * (jj + 0 )+ (ii + 2 )]= hsum (Cv02 ); 954C [ldc * (jj + 0 )+ (ii + 3 )]= hsum (Cv03 ); 955C [ldc * (jj + 1 )+ (ii + 0 )]= hsum (Cv10 ); 956C [ldc * (jj + 1 )+ (ii + 1 )]= hsum (Cv11 ); 957C [ldc * (jj + 1 )+ (ii + 2 )]= hsum (Cv12 ); 958C [ldc * (jj + 1 )+ (ii + 3 )]= hsum (Cv13 ); 959C [ldc * (jj + 2 )+ (ii + 0 )]= hsum (Cv20 ); 960C [ldc * (jj + 2 )+ (ii + 1 )]= hsum (Cv21 ); 961C [ldc * (jj + 2 )+ (ii + 2 )]= hsum (Cv22 ); 962C [ldc * (jj + 2 )+ (ii + 3 )]= hsum (Cv23 ); 963C [ldc * (jj + 3 )+ (ii + 0 )]= hsum (Cv30 ); 964C [ldc * (jj + 3 )+ (ii + 1 )]= hsum (Cv31 ); 965C [ldc * (jj + 3 )+ (ii + 2 )]= hsum (Cv32 ); 966C [ldc * (jj + 3 )+ (ii + 3 )]= hsum (Cv33 ); 967 } 968 969inline void gemm_bloc_4x3 (int64_t ii ,int64_t jj ) { 970size_t vl = vlmax < V > (); 971D Cv00 = set_zero < D > (); 972D Cv01 = set_zero < D > (); 973D Cv02 = set_zero < D > (); 974D Cv03 = set_zero < D > (); 975D Cv10 = set_zero < D > (); 976D Cv11 = set_zero < D > (); 977D Cv12 = set_zero < D > (); 978D Cv13 = set_zero < D > (); 979D Cv20 = set_zero < D > (); 980D Cv21 = set_zero < D > (); 981D Cv22 = set_zero < D > (); 982D Cv23 = set_zero < D > (); 983 984for (int64_t l = 0 ;l < k ;l += vl ) { 985V Av0 = load < V > (A + lda * (ii + 0 )+ l ); 986V Av1 = load < V > (A + lda * (ii + 1 )+ l ); 987V Av2 = load < V > (A + lda * (ii + 2 )+ l ); 988V Av3 = load < V > (A + lda * (ii + 3 )+ l ); 989 990V Bv0 = load < V > (B + ldb * (jj + 0 )+ l ); 991Cv00 = madd (Av0 ,Bv0 ,Cv00 ); 992Cv01 = madd (Av1 ,Bv0 ,Cv01 ); 993Cv02 = madd (Av2 ,Bv0 ,Cv02 ); 994Cv03 = madd (Av3 ,Bv0 ,Cv03 ); 995 996V Bv1 = load < V > (B + ldb * (jj + 1 )+ l ); 997Cv10 = madd (Av0 ,Bv1 ,Cv10 ); 998Cv11 = madd (Av1 ,Bv1 ,Cv11 ); 999Cv12 = madd (Av2 ,Bv1 ,Cv12 ); 1000Cv13 = madd (Av3 ,Bv1 ,Cv13 ); 1001 1002V Bv2 = load < V > (B + ldb * (jj + 2 )+ l ); 1003Cv20 = madd (Av0 ,Bv2 ,Cv20 ); 1004Cv21 = madd (Av1 ,Bv2 ,Cv21 ); 1005Cv22 = madd (Av2 ,Bv2 ,Cv22 ); 1006Cv23 = madd (Av3 ,Bv2 ,Cv23 ); 1007 } 1008 1009C [ldc * (jj + 0 )+ (ii + 0 )]= hsum (Cv00 ); 1010C [ldc * (jj + 0 )+ (ii + 1 )]= hsum (Cv01 ); 1011C [ldc * (jj + 0 )+ (ii + 2 )]= hsum (Cv02 ); 1012C [ldc * (jj + 0 )+ (ii + 3 )]= hsum (Cv03 ); 1013C [ldc * (jj + 1 )+ (ii + 0 )]= hsum (Cv10 ); 1014C [ldc * (jj + 1 )+ (ii + 1 )]= hsum (Cv11 ); 1015C [ldc * (jj + 1 )+ (ii + 2 )]= hsum (Cv12 ); 1016C [ldc * (jj + 1 )+ (ii + 3 )]= hsum (Cv13 ); 1017C [ldc * (jj + 2 )+ (ii + 0 )]= hsum (Cv20 ); 1018C [ldc * (jj + 2 )+ (ii + 1 )]= hsum (Cv21 ); 1019C [ldc * (jj + 2 )+ (ii + 2 )]= hsum (Cv22 ); 1020C [ldc * (jj + 2 )+ (ii + 3 )]= hsum (Cv23 ); 1021 } 1022 1023inline void gemm_bloc_4x2 (int64_t ii ,int64_t jj ) { 1024size_t vl = vlmax < V > (); 1025D Cv00 = set_zero < D > (); 1026D Cv01 = set_zero < D > (); 1027D Cv02 = set_zero < D > (); 1028D Cv03 = set_zero < D > (); 1029D Cv10 = set_zero < D > (); 1030D Cv11 = set_zero < D > (); 1031D Cv12 = set_zero < D > (); 1032D Cv13 = set_zero < D > (); 1033 1034for (int64_t l = 0 ;l < k ;l += vl ) { 1035V Av0 = load < V > (A + lda * (ii + 0 )+ l ); 1036V Av1 = load < V > (A + lda * (ii + 1 )+ l ); 1037V Av2 = load < V > (A + lda * (ii + 2 )+ l ); 1038V Av3 = load < V > (A + lda * (ii + 3 )+ l ); 1039 1040V Bv0 = load < V > (B + ldb * (jj + 0 )+ l ); 1041Cv00 = madd (Av0 ,Bv0 ,Cv00 ); 1042Cv01 = madd (Av1 ,Bv0 ,Cv01 ); 1043Cv02 = madd (Av2 ,Bv0 ,Cv02 ); 1044Cv03 = madd (Av3 ,Bv0 ,Cv03 ); 1045 1046V Bv1 = load < V > (B + ldb * (jj + 1 )+ l ); 1047Cv10 = madd (Av0 ,Bv1 ,Cv10 ); 1048Cv11 = madd (Av1 ,Bv1 ,Cv11 ); 1049Cv12 = madd (Av2 ,Bv1 ,Cv12 ); 1050Cv13 = madd (Av3 ,Bv1 ,Cv13 ); 1051 } 1052 1053C [ldc * (jj + 0 )+ (ii + 0 )]= hsum (Cv00 ); 1054C [ldc * (jj + 0 )+ (ii + 1 )]= hsum (Cv01 ); 1055C [ldc * (jj + 0 )+ (ii + 2 )]= hsum (Cv02 ); 1056C [ldc * (jj + 0 )+ (ii + 3 )]= hsum (Cv03 ); 1057C [ldc * (jj + 1 )+ (ii + 0 )]= hsum (Cv10 ); 1058C [ldc * (jj + 1 )+ (ii + 1 )]= hsum (Cv11 ); 1059C [ldc * (jj + 1 )+ (ii + 2 )]= hsum (Cv12 ); 1060C [ldc * (jj + 1 )+ (ii + 3 )]= hsum (Cv13 ); 1061 } 1062 1063inline void gemm_bloc_4x1 (int64_t ii ,int64_t jj ) { 1064size_t vl = vlmax < V > (); 1065D Cv00 = set_zero < D > (); 1066D Cv01 = set_zero < D > (); 1067D Cv02 = set_zero < D > (); 1068D Cv03 = set_zero < D > (); 1069 1070for (int64_t l = 0 ;l < k ;l += vl ) { 1071V Av0 = load < V > (A + lda * (ii + 0 )+ l ); 1072V Av1 = load < V > (A + lda * (ii + 1 )+ l ); 1073V Av2 = load < V > (A + lda * (ii + 2 )+ l ); 1074V Av3 = load < V > (A + lda * (ii + 3 )+ l ); 1075 1076V Bv0 = load < V > (B + ldb * (jj + 0 )+ l ); 1077Cv00 = madd (Av0 ,Bv0 ,Cv00 ); 1078Cv01 = madd (Av1 ,Bv0 ,Cv01 ); 1079Cv02 = madd (Av2 ,Bv0 ,Cv02 ); 1080Cv03 = madd (Av3 ,Bv0 ,Cv03 ); 1081 } 1082 1083C [ldc * (jj + 0 )+ (ii + 0 )]= hsum (Cv00 ); 1084C [ldc * (jj + 0 )+ (ii + 1 )]= hsum (Cv01 ); 1085C [ldc * (jj + 0 )+ (ii + 2 )]= hsum (Cv02 ); 1086C [ldc * (jj + 0 )+ (ii + 3 )]= hsum (Cv03 ); 1087 } 1088 1089inline void gemm_bloc_2x2 (int64_t ii ,int64_t jj ) { 1090size_t vl = vlmax < V > (); 1091D Cv00 = set_zero < D > (); 1092D Cv01 = set_zero < D > (); 1093D Cv10 = set_zero < D > (); 1094D Cv11 = set_zero < D > (); 1095 1096for (int64_t l = 0 ;l < k ;l += vl ) { 1097V Av0 = load < V > (A + lda * (ii + 0 )+ l ); 1098V Av1 = load < V > (A + lda * (ii + 1 )+ l ); 1099 1100V Bv0 = load < V > (B + ldb * (jj + 0 )+ l ); 1101Cv00 = madd (Av0 ,Bv0 ,Cv00 ); 1102Cv01 = madd (Av1 ,Bv0 ,Cv01 ); 1103 1104V Bv1 = load < V > (B + ldb * (jj + 1 )+ l ); 1105Cv10 = madd (Av0 ,Bv1 ,Cv10 ); 1106Cv11 = madd (Av1 ,Bv1 ,Cv11 ); 1107 } 1108 1109C [ldc * (jj + 0 )+ (ii + 0 )]= hsum (Cv00 ); 1110C [ldc * (jj + 0 )+ (ii + 1 )]= hsum (Cv01 ); 1111C [ldc * (jj + 1 )+ (ii + 0 )]= hsum (Cv10 ); 1112C [ldc * (jj + 1 )+ (ii + 1 )]= hsum (Cv11 ); 1113 } 1114 1115inline void gemm_bloc_2x1 (int64_t ii ,int64_t jj ) { 1116size_t vl = vlmax < V > (); 1117D Cv00 = set_zero < D > (); 1118D Cv01 = set_zero < D > (); 1119 1120for (int64_t l = 0 ;l < k ;l += vl ) { 1121V Av0 = load < V > (A + lda * (ii + 0 )+ l ); 1122V Av1 = load < V > (A + lda * (ii + 1 )+ l ); 1123 1124V Bv0 = load < V > (B + ldb * (jj + 0 )+ l ); 1125Cv00 = madd (Av0 ,Bv0 ,Cv00 ); 1126Cv01 = madd (Av1 ,Bv0 ,Cv01 ); 1127 } 1128 1129C [ldc * (jj + 0 )+ (ii + 0 )]= hsum (Cv00 ); 1130C [ldc * (jj + 0 )+ (ii + 1 )]= hsum (Cv01 ); 1131 } 1132 1133template < int RM ,int RN > 1134inline void gemm_bloc (int64_t ii ,int64_t jj ) { 1135if constexpr (RM == 4 ) { 1136if constexpr (RN == 6 ) {return gemm_bloc_4x6 (ii ,jj ); } 1137if constexpr (RN == 5 ) {return gemm_bloc_4x5 (ii ,jj ); } 1138if constexpr (RN == 4 ) {return gemm_bloc_4x4 (ii ,jj ); } 1139if constexpr (RN == 3 ) {return gemm_bloc_4x3 (ii ,jj ); } 1140if constexpr (RN == 2 ) {return gemm_bloc_4x2 (ii ,jj ); } 1141if constexpr (RN == 1 ) {return gemm_bloc_4x1 (ii ,jj ); } 1142 }else if constexpr (RM == 2 ) { 1143if constexpr (RN == 2 ) {return gemm_bloc_2x2 (ii ,jj ); } 1144if constexpr (RN == 1 ) {return gemm_bloc_2x1 (ii ,jj ); } 1145 } 1146 } 1147 1148template < int RM ,int RN ,int BM > 1149NOINLINE void gemm (int64_t m ,int64_t n ,int64_t BN ) { 1150GGML_ASSERT (m % (RM * BM )== 0 ); 1151const int64_t ytiles = m / (RM * BM ); 1152const int64_t xtiles = (n + RN - 1 ) /RN ; 1153const int64_t jj_RN = (xtiles - (xtiles * RN - n )); 1154 1155// "round" bloc_size to "nearest" BN 1156const int64_t NB_BN = xtiles < BN ?1 : (xtiles + BN /2 ) /BN ; 1157const int64_t SIZE_BN = xtiles %NB_BN == 0 ?xtiles /NB_BN :xtiles /NB_BN + 1 ; 1158const int64_t jj_BN = (NB_BN - (NB_BN * SIZE_BN - xtiles )); 1159const int64_t nb_job = ytiles * NB_BN ; 1160 1161if (params -> ith == 0 ) { 1162GGML_ASSERT (jj_BN * SIZE_BN + (NB_BN - jj_BN )* (SIZE_BN - 1 )== xtiles ); 1163// Every thread starts at ith, so the first unprocessed chunk is nth. This save a bit of coordination right at the start. 1164ggml_threadpool_chunk_set (params -> threadpool ,params -> nth ); 1165 } 1166 1167ggml_barrier (params -> threadpool ); 1168 1169int64_t job = params -> ith ; 1170while (job < nb_job ) { 1171const int64_t ii = (job %ytiles )* RM * BM ; 1172const int64_t jb = job /ytiles ; 1173const int64_t jr0 = BLOC_POS (jb ,jj_BN ,SIZE_BN ); 1174const int64_t jrN = BLOC_POS (jb + 1 ,jj_BN ,SIZE_BN ); 1175 1176const int64_t jj0 = BLOC_POS (jr0 ,jj_RN ,RN ); 1177const int64_t jj2 = BLOC_POS (jrN ,jj_RN ,RN ); 1178const int64_t jj1 = jj2 < jj_RN * RN ?jj2 :jj_RN * RN ; 1179 1180for (int64_t bi = 0 ;bi < BM * RM ;bi += RM ) { 1181int64_t jj = jj0 ; 1182for (;jj < jj1 ;jj += RN ) { 1183gemm_bloc < RM ,RN > (ii + bi ,jj ); 1184 } 1185if constexpr (RN > 1 ) { 1186for (;jj < jj2 ;jj += RN - 1 ) { 1187gemm_bloc < RM ,RN - 1 > (ii + bi ,jj ); 1188 } 1189 } 1190GGML_ASSERT (jj == jj2 ); 1191 } 1192 1193job = ggml_threadpool_chunk_add (params -> threadpool ,1 ); 1194 } 1195 1196ggml_barrier (params -> threadpool ); 1197return ; 1198 } 1199 1200const ggml_compute_params * params ; 1201const TA * const A ; 1202const TB * const B ; 1203TC * const C ; 1204const int64_t k ; 1205const int64_t lda ; 1206const int64_t ldb ; 1207const int64_t ldc ; 1208}; 1209#endif 1210 1211////////////////////////////////////////////////////////////////////////////////////////// 1212// QUANT ZERO MATRIX MULTIPLICATION 1213 1214#if defined(__ARM_FEATURE_DOTPROD ) 1215template < typename TA > 1216class tinyBLAS_Q0_ARM { 1217public : 1218tinyBLAS_Q0_ARM (int64_t k , 1219const TA * A ,int64_t lda , 1220const block_q8_0 * B ,int64_t ldb , 1221float * C ,int64_t ldc , 1222int ith ,int nth ) 1223 :A (A ),B (B ),C (C ),k (k ),lda (lda ),ldb (ldb ),ldc (ldc ),ith (ith ),nth (nth ) { 1224 } 1225 1226void matmul (int64_t m ,int64_t n ) { 1227mnpack (0 ,m ,0 ,n ); 1228 } 1229 1230private : 1231NOINLINE void mnpack (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 1232int64_t mc ,nc ,mp ,np ; 1233switch ((MIN (m - m0 ,3 ) <<4 ) |MIN (n - n0 ,3ll )) { 1234case 0x33 : 1235mc = 3 ; 1236nc = 3 ; 1237gemm < 3 ,3 > (m0 ,m ,n0 ,n ); 1238break ; 1239case 0x32 : 1240mc = 3 ; 1241nc = 2 ; 1242gemm < 3 ,2 > (m0 ,m ,n0 ,n ); 1243break ; 1244case 0x23 : 1245mc = 2 ; 1246nc = 3 ; 1247gemm < 2 ,3 > (m0 ,m ,n0 ,n ); 1248break ; 1249case 0x22 : 1250mc = 2 ; 1251nc = 2 ; 1252gemm < 2 ,2 > (m0 ,m ,n0 ,n ); 1253break ; 1254case 0x31 : 1255mc = 3 ; 1256nc = 1 ; 1257gemm < 3 ,1 > (m0 ,m ,n0 ,n ); 1258break ; 1259case 0x13 : 1260mc = 1 ; 1261nc = 3 ; 1262gemm < 1 ,3 > (m0 ,m ,n0 ,n ); 1263break ; 1264case 0x21 : 1265mc = 2 ; 1266nc = 1 ; 1267gemm < 2 ,1 > (m0 ,m ,n0 ,n ); 1268break ; 1269case 0x12 : 1270mc = 1 ; 1271nc = 2 ; 1272gemm < 1 ,2 > (m0 ,m ,n0 ,n ); 1273break ; 1274case 0x11 : 1275mc = 1 ; 1276nc = 1 ; 1277gemm < 1 ,1 > (m0 ,m ,n0 ,n ); 1278break ; 1279default : 1280return ; 1281 } 1282mp = m0 + (m - m0 ) /mc * mc ; 1283np = n0 + (n - n0 ) /nc * nc ; 1284mnpack (mp ,m ,n0 ,np ); 1285mnpack (m0 ,m ,np ,n ); 1286 } 1287 1288template < int RM ,int RN > 1289NOINLINE void gemm (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 1290int64_t ytiles = (m - m0 ) /RM ; 1291int64_t xtiles = (n - n0 ) /RN ; 1292int64_t tiles = xtiles * ytiles ; 1293int64_t duty = (tiles + nth - 1 ) /nth ; 1294int64_t start = duty * ith ; 1295int64_t end = start + duty ; 1296if (end > tiles ) 1297end = tiles ; 1298for (int64_t job = start ;job < end ;++ job ) { 1299int64_t ii = m0 + job /xtiles * RM ; 1300int64_t jj = n0 + job %xtiles * RN ; 1301float32x4_t Cv [RN ][RM ]= {}; 1302for (int64_t l = 0 ;l < k ;++ l ) 1303for (int64_t j = 0 ;j < RN ;++ j ) 1304for (int64_t i = 0 ;i < RM ;++ i ) 1305Cv [j ][i ]= vmlaq_n_f32 (Cv [j ][i ], 1306vcvtq_f32_s32 (vdotq_s32 ( 1307vdotq_s32 (vdupq_n_s32 (0 ), 1308load_lo (A + lda * (ii + i )+ l ), 1309load_lo (B + ldb * (jj + j )+ l )), 1310load_hi (A + lda * (ii + i )+ l ), 1311load_hi (B + ldb * (jj + j )+ l ))), 1312unhalf (A [lda * (ii + i )+ l ].d )* 1313unhalf (B [ldb * (jj + j )+ l ].d )); 1314for (int64_t j = 0 ;j < RN ;++ j ) 1315for (int64_t i = 0 ;i < RM ;++ i ) 1316C [ldc * (jj + j )+ (ii + i )]= hsum (Cv [j ][i ]); 1317 } 1318 } 1319 1320inline int8x16_t load_lo (const block_q8_0 * b ) { 1321return vld1q_s8 (b -> qs ); 1322 } 1323 1324inline int8x16_t load_hi (const block_q8_0 * b ) { 1325return vld1q_s8 (b -> qs + 16 ); 1326 } 1327 1328inline int8x16_t load_lo (const block_q4_0 * b ) { 1329return vsubq_s8 (vreinterpretq_s8_u8 (vandq_u8 (vld1q_u8 (b -> qs ), 1330vdupq_n_u8 (0x0f ))), 1331vdupq_n_s8 (0x8 )); 1332 } 1333 1334inline int8x16_t load_hi (const block_q4_0 * b ) { 1335return vsubq_s8 (vreinterpretq_s8_u8 (vshrq_n_u8 (vld1q_u8 (b -> qs ),4 )), 1336vdupq_n_s8 (0x8 )); 1337 } 1338 1339const TA * const A ; 1340const block_q8_0 * const B ; 1341float * const C ; 1342const int64_t k ; 1343const int64_t lda ; 1344const int64_t ldb ; 1345const int64_t ldc ; 1346const int ith ; 1347const int nth ; 1348}; 1349#endif // __ARM_FEATURE_DOTPROD 1350 1351#if defined(__AVX2__ )|| defined(__AVX512F__ )|| defined(__AVX__ ) 1352template < typename TA ,typename TB ,typename TC > 1353class tinyBLAS_Q0_AVX { 1354public : 1355tinyBLAS_Q0_AVX (int64_t k , 1356const TA * A ,int64_t lda , 1357const TB * B ,int64_t ldb , 1358TC * C ,int64_t ldc , 1359int ith ,int nth ) 1360 :A (A ),B (B ),C (C ),k (k ),lda (lda ),ldb (ldb ),ldc (ldc ),ith (ith ),nth (nth ) { 1361const int8_t kvalues_iq4nl [16 ]= { 1362-127 ,-104 ,-83 ,-65 , 1363-49 ,-35 ,-22 ,-10 , 13641 ,13 ,25 ,38 , 136553 ,69 ,89 ,113 1366 }; 1367 1368iq4nlt = _mm_loadu_si128 ((const __m128i * )kvalues_iq4nl ); 1369 } 1370 1371void matmul (int64_t m ,int64_t n ) { 1372mnpack (0 ,m ,0 ,n ); 1373 } 1374 1375private : 1376void mnpack (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 1377int64_t mc ,nc ,mp ,np ; 1378switch ((MIN (m - m0 ,4 ) <<4 ) |MIN (n - n0 ,4 )) { 1379#if VECTOR_REGISTERS == 32 1380case 0x44 : 1381mc = 4 ; 1382nc = 4 ; 1383#if defined(__AVX2__ )&& defined(__F16C__ ) 1384gemm4xN < 4 > (m0 ,m ,n0 ,n ); 1385#else 1386gemm < 4 ,4 > (m0 ,m ,n0 ,n ); 1387#endif 1388break ; 1389case 0x43 : 1390mc = 4 ; 1391nc = 3 ; 1392#if defined(__AVX2__ )&& defined(__F16C__ ) 1393gemm4xN < 3 > (m0 ,m ,n0 ,n ); 1394#else 1395gemm < 4 ,3 > (m0 ,m ,n0 ,n ); 1396#endif 1397break ; 1398case 0x34 : 1399mc = 3 ; 1400nc = 4 ; 1401#if defined(__AVX2__ )&& defined(__F16C__ ) 1402gemmMx4 < 3 > (m0 ,m ,n0 ,n ); 1403#else 1404gemm < 3 ,4 > (m0 ,m ,n0 ,n ); 1405#endif 1406break ; 1407case 0x33 : 1408mc = 3 ; 1409nc = 3 ; 1410gemm < 3 ,3 > (m0 ,m ,n0 ,n ); 1411break ; 1412case 0x42 : 1413mc = 4 ; 1414nc = 2 ; 1415#if defined(__AVX2__ )&& defined(__F16C__ ) 1416gemm4xN < 2 > (m0 ,m ,n0 ,n ); 1417#else 1418gemm < 4 ,2 > (m0 ,m ,n0 ,n ); 1419#endif 1420break ; 1421case 0x24 : 1422mc = 2 ; 1423nc = 4 ; 1424#if defined(__AVX2__ )&& defined(__F16C__ ) 1425gemmMx4 < 2 > (m0 ,m ,n0 ,n ); 1426#else 1427gemm < 2 ,4 > (m0 ,m ,n0 ,n ); 1428#endif 1429break ; 1430#else 1431case 0x44 : 1432case 0x43 : 1433case 0x42 : 1434mc = 4 ; 1435nc = 2 ; 1436#if defined(__AVX2__ )&& defined(__F16C__ ) 1437gemm4xN < 2 > (m0 ,m ,n0 ,n ); 1438#else 1439gemm < 4 ,2 > (m0 ,m ,n0 ,n ); 1440#endif 1441break ; 1442case 0x34 : 1443case 0x24 : 1444mc = 2 ; 1445nc = 4 ; 1446#if defined(__AVX2__ )&& defined(__F16C__ ) 1447gemmMx4 < 2 > (m0 ,m ,n0 ,n ); 1448#else 1449gemm < 2 ,4 > (m0 ,m ,n0 ,n ); 1450#endif 1451break ; 1452case 0x33 : 1453#endif 1454case 0x32 : 1455mc = 3 ; 1456nc = 2 ; 1457gemm < 3 ,2 > (m0 ,m ,n0 ,n ); 1458break ; 1459case 0x23 : 1460mc = 2 ; 1461nc = 3 ; 1462gemm < 2 ,3 > (m0 ,m ,n0 ,n ); 1463break ; 1464case 0x41 : 1465mc = 4 ; 1466nc = 1 ; 1467#if defined(__AVX2__ )&& defined(__F16C__ ) 1468gemm4xN < 1 > (m0 ,m ,n0 ,n ); 1469#else 1470gemm < 4 ,1 > (m0 ,m ,n0 ,n ); 1471#endif 1472break ; 1473case 0x22 : 1474mc = 2 ; 1475nc = 2 ; 1476gemm < 2 ,2 > (m0 ,m ,n0 ,n ); 1477break ; 1478case 0x14 : 1479mc = 1 ; 1480nc = 4 ; 1481#if defined(__AVX2__ )&& defined(__F16C__ ) 1482gemmMx4 < 1 > (m0 ,m ,n0 ,n ); 1483#else 1484gemm < 1 ,4 > (m0 ,m ,n0 ,n ); 1485#endif 1486break ; 1487case 0x31 : 1488mc = 3 ; 1489nc = 1 ; 1490gemm < 3 ,1 > (m0 ,m ,n0 ,n ); 1491break ; 1492case 0x13 : 1493mc = 1 ; 1494nc = 3 ; 1495gemm < 1 ,3 > (m0 ,m ,n0 ,n ); 1496break ; 1497case 0x21 : 1498mc = 2 ; 1499nc = 1 ; 1500gemm < 2 ,1 > (m0 ,m ,n0 ,n ); 1501break ; 1502case 0x12 : 1503mc = 1 ; 1504nc = 2 ; 1505gemm < 1 ,2 > (m0 ,m ,n0 ,n ); 1506break ; 1507case 0x11 : 1508mc = 1 ; 1509nc = 1 ; 1510gemm < 1 ,1 > (m0 ,m ,n0 ,n ); 1511break ; 1512default : 1513return ; 1514 } 1515mp = m0 + (m - m0 ) /mc * mc ; 1516np = n0 + (n - n0 ) /nc * nc ; 1517mnpack (mp ,m ,n0 ,np ); 1518mnpack (m0 ,m ,np ,n ); 1519 } 1520 1521#if defined(__AVX2__ )&& defined(__F16C__ ) 1522// Templated functions for gemm of dimensions 4xN 1523template < int RN > 1524NOINLINE void gemm4xN (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 1525int64_t ytiles = (m - m0 ) /4 ; 1526int64_t xtiles = (n - n0 ) /RN ; 1527int64_t tiles = xtiles * ytiles ; 1528int64_t duty = (tiles + nth - 1 ) /nth ; 1529int64_t start = duty * ith ; 1530int64_t end = start + duty ; 1531if (end > tiles ) 1532end = tiles ; 1533for (int64_t job = start ;job < end ;++ job ) { 1534int64_t ii = m0 + job /xtiles * 4 ; 1535int64_t jj = n0 + job %xtiles * RN ; 1536__m256 Cv [RN ][4 ]= {}; 1537for (int64_t l = 0 ;l < k ;++ l ) { 1538uint64_t a_delta = ((uint64_t )A [lda * (ii + 3 )+ l ].d <<48 ) | ((uint64_t )A [lda * (ii + 2 )+ l ].d <<32 ) | ((uint64_t )A [lda * (ii + 1 )+ l ].d <<16 ) | (A [lda * (ii + 0 )+ l ].d ); 1539// Convert delta values for four blocks to float values 1540__m128 da = _mm_cvtph_ps (_mm_set_epi64x (0 ,a_delta )); 1541__m256i avec0 = load (A + lda * (ii + 0 )+ l ); 1542__m256i avec1 = load (A + lda * (ii + 1 )+ l ); 1543__m256i avec2 = load (A + lda * (ii + 2 )+ l ); 1544__m256i avec3 = load (A + lda * (ii + 3 )+ l ); 1545for (int64_t j = 0 ;j < RN ;++ j ) { 1546__m128 db = _mm_set1_ps (unhalf (B [ldb * (jj + j )+ l ].d )); 1547// Computation of product of delta values for four blocks and replicate it across 256 bit lane 1548__m256 dvec = _mm256_castps128_ps256 (_mm_mul_ps (da ,db )); 1549dvec = _mm256_permute2f128_ps (dvec ,dvec ,0 ); 1550// Computation of dot product and multiplication with appropriate delta value products 1551Cv [j ][0 ]= madd (_mm256_shuffle_ps (dvec ,dvec ,0 ), 1552updot (_mm256_sign_epi8 (avec0 ,avec0 ), 1553_mm256_sign_epi8 (load (B + ldb * (jj + j )+ l ),avec0 )), 1554Cv [j ][0 ]); 1555Cv [j ][1 ]= madd (_mm256_shuffle_ps (dvec ,dvec ,85 ), 1556updot (_mm256_sign_epi8 (avec1 ,avec1 ), 1557_mm256_sign_epi8 (load (B + ldb * (jj + j )+ l ),avec1 )), 1558Cv [j ][1 ]); 1559Cv [j ][2 ]= madd (_mm256_shuffle_ps (dvec ,dvec ,170 ), 1560updot (_mm256_sign_epi8 (avec2 ,avec2 ), 1561_mm256_sign_epi8 (load (B + ldb * (jj + j )+ l ),avec2 )), 1562Cv [j ][2 ]); 1563Cv [j ][3 ]= madd (_mm256_shuffle_ps (dvec ,dvec ,255 ), 1564updot (_mm256_sign_epi8 (avec3 ,avec3 ), 1565_mm256_sign_epi8 (load (B + ldb * (jj + j )+ l ),avec3 )), 1566Cv [j ][3 ]); 1567 } 1568 } 1569 1570for (int64_t j = 0 ;j < RN ;++ j ) 1571for (int64_t i = 0 ;i < 4 ;++ i ) 1572C [ldc * (jj + j )+ (ii + i )]= hsum (Cv [j ][i ]); 1573 } 1574 } 1575 1576// Templated functions for gemm of dimensions Mx4 1577template < int RM > 1578NOINLINE void gemmMx4 (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 1579int64_t ytiles = (m - m0 ) /RM ; 1580int64_t xtiles = (n - n0 ) /4 ; 1581int64_t tiles = xtiles * ytiles ; 1582int64_t duty = (tiles + nth - 1 ) /nth ; 1583int64_t start = duty * ith ; 1584int64_t end = start + duty ; 1585if (end > tiles ) 1586end = tiles ; 1587for (int64_t job = start ;job < end ;++ job ) { 1588int64_t ii = m0 + job /xtiles * RM ; 1589int64_t jj = n0 + job %xtiles * 4 ; 1590__m256 Cv [4 ][RM ]= {}; 1591for (int64_t l = 0 ;l < k ;++ l ) { 1592uint64_t b_delta = ((uint64_t )B [ldb * (jj + 3 )+ l ].d <<48 ) | ((uint64_t )B [ldb * (jj + 2 )+ l ].d <<32 ) | ((uint64_t )B [ldb * (jj + 1 )+ l ].d <<16 ) | (B [ldb * (jj + 0 )+ l ].d ); 1593// Convert delta values for four blocks to float values 1594__m128 db = _mm_cvtph_ps (_mm_set_epi64x (0 ,b_delta )); 1595__m256i bvec0 = load (B + ldb * (jj + 0 )+ l ); 1596__m256i bvec1 = load (B + ldb * (jj + 1 )+ l ); 1597__m256i bvec2 = load (B + ldb * (jj + 2 )+ l ); 1598__m256i bvec3 = load (B + ldb * (jj + 3 )+ l ); 1599for (int64_t i = 0 ;i < RM ;++ i ) { 1600__m128 da = _mm_set1_ps (unhalf ((A [lda * (ii + i )+ l ].d ))); 1601// Computation of product of delta values for four blocks and replicate it across 256 bit lane 1602__m256 dvec = _mm256_castps128_ps256 (_mm_mul_ps (da ,db )); 1603dvec = _mm256_permute2f128_ps (dvec ,dvec ,0 ); 1604// Computation of dot product and multiplication with appropriate delta value products 1605Cv [0 ][i ]= madd (_mm256_shuffle_ps (dvec ,dvec ,0 ), 1606updot (_mm256_sign_epi8 (load (A + lda * (ii + i )+ l ), 1607load (A + lda * (ii + i )+ l )), 1608_mm256_sign_epi8 (bvec0 ,load (A + lda * (ii + i )+ l ))), 1609Cv [0 ][i ]); 1610Cv [1 ][i ]= madd (_mm256_shuffle_ps (dvec ,dvec ,85 ), 1611updot (_mm256_sign_epi8 (load (A + lda * (ii + i )+ l ), 1612load (A + lda * (ii + i )+ l )), 1613_mm256_sign_epi8 (bvec1 ,load (A + lda * (ii + i )+ l ))), 1614Cv [1 ][i ]); 1615Cv [2 ][i ]= madd (_mm256_shuffle_ps (dvec ,dvec ,170 ), 1616updot (_mm256_sign_epi8 (load (A + lda * (ii + i )+ l ), 1617load (A + lda * (ii + i )+ l )), 1618_mm256_sign_epi8 (bvec2 ,load (A + lda * (ii + i )+ l ))), 1619Cv [2 ][i ]); 1620Cv [3 ][i ]= madd (_mm256_shuffle_ps (dvec ,dvec ,255 ), 1621updot (_mm256_sign_epi8 (load (A + lda * (ii + i )+ l ), 1622load (A + lda * (ii + i )+ l )), 1623_mm256_sign_epi8 (bvec3 ,load (A + lda * (ii + i )+ l ))), 1624Cv [3 ][i ]); 1625 } 1626 } 1627for (int64_t j = 0 ;j < 4 ;++ j ) 1628for (int64_t i = 0 ;i < RM ;++ i ) 1629C [ldc * (jj + j )+ (ii + i )]= hsum (Cv [j ][i ]); 1630 } 1631 } 1632#endif 1633 1634template < int RM ,int RN > 1635NOINLINE void gemm (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 1636int64_t ytiles = (m - m0 ) /RM ; 1637int64_t xtiles = (n - n0 ) /RN ; 1638int64_t tiles = xtiles * ytiles ; 1639int64_t duty = (tiles + nth - 1 ) /nth ; 1640int64_t start = duty * ith ; 1641int64_t end = start + duty ; 1642if (end > tiles ) 1643end = tiles ; 1644for (int64_t job = start ;job < end ;++ job ) { 1645int64_t ii = m0 + job /xtiles * RM ; 1646int64_t jj = n0 + job %xtiles * RN ; 1647__m256 Cv [RN ][RM ]= {}; 1648for (int64_t l = 0 ;l < k ;++ l ) 1649for (int64_t j = 0 ;j < RN ;++ j ) 1650for (int64_t i = 0 ;i < RM ;++ i ) { 1651#if defined(__AVX2__ ) 1652__m256 udTmp = updot (_mm256_sign_epi8 (load (A + lda * (ii + i )+ l ), 1653load (A + lda * (ii + i )+ l )), 1654_mm256_sign_epi8 (load (B + ldb * (jj + j )+ l ), 1655load (A + lda * (ii + i )+ l ))); 1656#else 1657__m128i ali0 = load0 (A + lda * (ii + i )+ l ); 1658__m128i ali1 = load1 (A + lda * (ii + i )+ l ); 1659__m128i blj0 = load0 (B + ldb * (jj + j )+ l ); 1660__m128i blj1 = load1 (B + ldb * (jj + j )+ l ); 1661 1662__m128i sepAA0 = _mm_sign_epi8 (ali0 ,ali0 ); 1663__m128i sepAA1 = _mm_sign_epi8 (ali1 ,ali1 ); 1664__m128i sepBA0 = _mm_sign_epi8 (blj0 ,ali0 ); 1665__m128i sepBA1 = _mm_sign_epi8 (blj1 ,ali1 ); 1666 1667// updot 1668const __m128i oneFill = _mm_set1_epi16 (1 ); 1669__m128i mad0 = _mm_maddubs_epi16 (sepAA0 ,sepBA0 ); 1670__m128i mad1 = _mm_maddubs_epi16 (sepAA1 ,sepBA1 ); 1671__m256 udTmp = _mm256_cvtepi32_ps (MM256_SET_M128I (_mm_madd_epi16 (oneFill ,mad1 ),_mm_madd_epi16 (oneFill ,mad0 ))); 1672#endif 1673Cv [j ][i ]= madd (_mm256_set1_ps (unhalf (A [lda * (ii + i )+ l ].d )* 1674unhalf (B [ldb * (jj + j )+ l ].d )), 1675udTmp , 1676Cv [j ][i ]); 1677 } 1678for (int64_t j = 0 ;j < RN ;++ j ) 1679for (int64_t i = 0 ;i < RM ;++ i ) 1680C [ldc * (jj + j )+ (ii + i )]= hsum (Cv [j ][i ]); 1681 } 1682 } 1683 1684inline __m256i load (const block_q8_0 * b ) { 1685return _mm256_loadu_si256 ((const __m256i * )b -> qs ); 1686 } 1687 1688inline __m128i load0 (const block_q8_0 * b ) { 1689return _mm_loadu_si128 ((const __m128i * )b -> qs ); 1690 } 1691 1692inline __m128i load1 (const block_q8_0 * b ) { 1693return _mm_loadu_si128 (((const __m128i * )b -> qs )+ 1 ); 1694 } 1695 1696inline __m256i load (const block_q4_0 * b ) { 1697return _mm256_sub_epi8 (denibble (b -> qs ),_mm256_set1_epi8 (8 )); 1698 } 1699 1700inline __m128i load0 (const block_q4_0 * b ) { 1701const __m128i x = _mm_loadu_si128 ((const __m128i * )(b -> qs )); 1702return _mm_sub_epi8 (_mm_and_si128 (_mm_set1_epi8 (15 ),x ),_mm_set1_epi8 (8 )); 1703 } 1704 1705inline __m128i load1 (const block_q4_0 * b ) { 1706const __m128i x = _mm_loadu_si128 ((const __m128i * )(b -> qs )); 1707return _mm_sub_epi8 (_mm_and_si128 (_mm_set1_epi8 (15 ),_mm_srli_epi16 (x ,4 )),_mm_set1_epi8 (8 )); 1708 } 1709 1710inline __m256i load (const block_q5_0 * b ) { 1711return _mm256_or_si256 (denibble (b -> qs ),bittobyte (b -> qh )); 1712 } 1713 1714inline __m128i load0 (const block_q5_0 * b ) { 1715const __m128i x = _mm_loadu_si128 ((const __m128i * )(b -> qs )); 1716uint32_t x32 ; 1717memcpy (& x32 ,b -> qh ,sizeof (uint32_t )); 1718__m128i qxl = _mm_and_si128 (_mm_set1_epi8 (15 ),x ); 1719__m128i bytesl = _mm_cmpeq_epi8 (_mm_set1_epi64x (-1 ), 1720_mm_or_si128 (_mm_set1_epi64x (0x7fbfdfeff7fbfdfe ), 1721_mm_shuffle_epi8 (_mm_set1_epi32 (x32 ), 1722_mm_set_epi64x (0x0101010101010101 ,0x0000000000000000 )))); 1723bytesl = _mm_andnot_si128 (bytesl ,_mm_set1_epi8 ((char )0xF0 )); 1724return _mm_or_si128 (qxl ,bytesl ); 1725 } 1726 1727inline __m128i load1 (const block_q5_0 * b ) { 1728const __m128i x = _mm_loadu_si128 ((const __m128i * )(b -> qs )); 1729uint32_t x32 ; 1730memcpy (& x32 ,b -> qh ,sizeof (uint32_t )); 1731__m128i qxh = _mm_and_si128 (_mm_set1_epi8 (15 ),_mm_srli_epi16 (x ,4 )); 1732__m128i bytesh = _mm_cmpeq_epi8 (_mm_set1_epi64x (-1 ), 1733_mm_or_si128 (_mm_set1_epi64x (0x7fbfdfeff7fbfdfe ), 1734_mm_shuffle_epi8 (_mm_set1_epi32 (x32 ), 1735_mm_set_epi64x (0x0303030303030303 ,0x0202020202020202 )))); 1736bytesh = _mm_andnot_si128 (bytesh ,_mm_set1_epi8 ((char )0xF0 )); 1737return _mm_or_si128 (qxh ,bytesh ); 1738 } 1739 1740inline __m256i load (const block_iq4_nl * b ) { 1741return MM256_SET_M128I (load1 (b ),load0 (b )); 1742 } 1743 1744inline __m128i load0 (const block_iq4_nl * b ) { 1745const __m128i x = _mm_loadu_si128 ((const __m128i * )(b -> qs )); 1746return _mm_shuffle_epi8 (iq4nlt ,_mm_and_si128 (_mm_set1_epi8 (15 ),x )); 1747 } 1748 1749inline __m128i load1 (const block_iq4_nl * b ) { 1750const __m128i x = _mm_loadu_si128 ((const __m128i * )(b -> qs )); 1751return _mm_shuffle_epi8 (iq4nlt ,_mm_and_si128 (_mm_set1_epi8 (15 ),_mm_srli_epi16 (x ,4 ))); 1752 } 1753 1754inline __m256 updot (__m256i u ,__m256i s ) { 1755__m256i res ; 1756#if defined(__AVX512VNNI__ )&& defined(__AVX512VL__ ) 1757res = _mm256_dpbusd_epi32 (_mm256_setzero_si256 (),u ,s ); 1758#elif defined(__AVXVNNI__ ) 1759res = _mm256_dpbusd_avx_epi32 (_mm256_setzero_si256 (),u ,s ); 1760#else 1761res = _mm256_madd_epi16 (_mm256_set1_epi16 (1 ),_mm256_maddubs_epi16 (u ,s )); 1762#endif 1763return _mm256_cvtepi32_ps (res ); 1764 } 1765 1766static inline __m256i denibble (const uint8_t * p ) { 1767__m128i x = _mm_loadu_si128 ((const __m128i * )p ); 1768return _mm256_and_si256 (_mm256_set1_epi8 (15 ), 1769_mm256_insertf128_si256 (_mm256_castsi128_si256 (x ), 1770_mm_srli_epi16 (x ,4 ),1 )); 1771 } 1772 1773static inline __m256i bittobyte (const uint8_t * p ) { 1774uint32_t x32 ; 1775memcpy (& x32 ,p ,sizeof (uint32_t )); 1776__m256i bytes = _mm256_cmpeq_epi8 (_mm256_set1_epi64x (-1 ), 1777_mm256_or_si256 (_mm256_set1_epi64x (0x7fbfdfeff7fbfdfe ), 1778_mm256_shuffle_epi8 (_mm256_set1_epi32 (x32 ), 1779_mm256_set_epi64x (0x0303030303030303 ,0x0202020202020202 , 17800x0101010101010101 ,0x0000000000000000 )))); 1781return _mm256_andnot_si256 (bytes ,_mm256_set1_epi8 ((char )0xF0 )); 1782 } 1783 1784const TA * const A ; 1785const TB * const B ; 1786TC * const C ; 1787const int64_t k ; 1788const int64_t lda ; 1789const int64_t ldb ; 1790const int64_t ldc ; 1791const int ith ; 1792const int nth ; 1793__m128i iq4nlt ; 1794}; 1795#endif // __AVX__ 1796 1797//PPC Implementation 1798#if defined(__MMA__ ) 1799 1800template < typename T > 1801struct mma_instr ; 1802 1803template <> 1804struct mma_instr < ggml_bf16_t > { 1805static inline void outer_product (acc_t * acc ,vec_t a ,vec_t b ) { 1806__builtin_mma_xvbf16ger2pp (acc ,a ,b ); 1807 } 1808}; 1809 1810template <> 1811struct mma_instr < ggml_fp16_t > { 1812static inline void outer_product (acc_t * acc ,vec_t a ,vec_t b ) { 1813__builtin_mma_xvf16ger2pp (acc ,a ,b ); 1814 } 1815}; 1816 1817template < typename TA ,typename TB ,typename TC > 1818class tinyBLAS_HP16_PPC { 1819public : 1820tinyBLAS_HP16_PPC (int64_t k , 1821const TA * A ,int64_t lda , 1822const TB * B ,int64_t ldb , 1823TC * C ,int64_t ldc , 1824int ith ,int nth ) 1825 :A (A ),B (B ),C (C ),k (k ),lda (lda ),ldb (ldb ),ldc (ldc ),ith (ith ),nth (nth ) { 1826 } 1827 1828void matmul (int64_t m ,int64_t n ) { 1829int64_t mc = 256 ; 1830int64_t nc = 256 ; 1831int64_t kc = 256 ; 1832#if defined(_AIX )|| defined(__BIG_ENDIAN__ ) 1833mc = 128 ; 1834nc = 128 ; 1835kc = 128 ; 1836#endif 1837if (k < kc ) { 1838kc = k ; 1839 } 1840bool can_use_tiled = (m %mc == 0 )&& (n %nc == 0 )&& (k %kc == 0 ); 1841if (can_use_tiled ) { 1842matmul_tiled (m ,n ,mc ,nc ,kc ); 1843 }else { 1844mnpack (0 ,m ,0 ,n ); 1845 } 1846 } 1847 1848private : 1849 __attribute__((always_inline )) 1850inline void save_acc (acc_t * ACC ,int64_t ii ,int64_t jj ) { 1851vec_t vec_C [4 ]; 1852__builtin_mma_disassemble_acc (vec_C ,ACC ); 1853for (int I = 0 ;I < 4 ;I ++ ) { 1854for (int J = 0 ;J < 4 ;J ++ ) { 1855* ((float * )(C + ii + ((jj + J )* ldc )+ I ))= * ((float * )& vec_C [I ]+ J ); 1856 } 1857 } 1858 } 1859 1860 __attribute__((always_inline )) 1861inline void add_save_acc (acc_t * ACC ,int64_t ii ,int64_t jj ) { 1862vec_t vec_C [4 ]; 1863__builtin_mma_disassemble_acc (vec_C ,ACC ); 1864for (int I = 0 ;I < 4 ;I ++ ) { 1865for (int J = 0 ;J < 4 ;J ++ ) { 1866float * c_ptr = (float * )(C + ii + ((jj + J )* ldc )+ I ); 1867* c_ptr += * ((float * )& vec_C [I ]+ J ); 1868 } 1869 } 1870 } 1871 1872void vector_permute_store (vec_t * c ,int numVec ,unsigned char * vecOffset ) { 1873vec_t t [8 ],s [8 ]; 1874vec_t swiz1 = {0 ,1 ,2 ,3 ,16 ,17 ,18 ,19 ,4 ,5 ,6 ,7 ,20 ,21 ,22 ,23 }; 1875vec_t swiz2 = {8 ,9 ,10 ,11 ,24 ,25 ,26 ,27 ,12 ,13 ,14 ,15 ,28 ,29 ,30 ,31 }; 1876vec_t swiz3 = {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,16 ,17 ,18 ,19 ,20 ,21 ,22 ,23 }; 1877vec_t swiz4 = {8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 }; 1878 1879if (numVec == 2 ) { 1880t [0 ]= vec_perm (c [0 ],c [1 ],swiz1 ); 1881t [1 ]= vec_perm (c [2 ],c [3 ],swiz1 ); 1882s [0 ]= vec_perm (t [0 ],t [1 ],swiz3 ); 1883s [1 ]= vec_perm (t [0 ],t [1 ],swiz4 ); 1884vec_xst (s [0 ],0 , (vec_t * )vecOffset ); 1885vec_xst (s [1 ],0 , (vec_t * )(vecOffset + 16 )); 1886 }else if (numVec == 4 ) { 1887t [0 ]= vec_perm (c [0 ],c [1 ],swiz1 ); 1888t [1 ]= vec_perm (c [0 ],c [1 ],swiz2 ); 1889t [2 ]= vec_perm (c [2 ],c [3 ],swiz1 ); 1890t [3 ]= vec_perm (c [2 ],c [3 ],swiz2 ); 1891s [0 ]= vec_perm (t [0 ],t [2 ],swiz3 ); 1892s [1 ]= vec_perm (t [0 ],t [2 ],swiz4 ); 1893s [2 ]= vec_perm (t [1 ],t [3 ],swiz3 ); 1894s [3 ]= vec_perm (t [1 ],t [3 ],swiz4 ); 1895for (int i = 0 ;i < 4 ;++ i ) 1896vec_xst (s [i ],0 , (vec_t * )(vecOffset + i * 16 )); 1897 }else if (numVec == 8 ) { 1898for (int i = 0 ;i < 4 ;i += 2 ) { 1899t [i + 0 ]= vec_perm (c [i + 0 ],c [i + 1 ],swiz1 ); 1900t [i + 1 ]= vec_perm (c [i + 0 ],c [i + 1 ],swiz2 ); 1901 } 1902for (int i = 4 ;i < 8 ;i += 2 ) { 1903t [i + 0 ]= vec_perm (c [i + 0 ],c [i + 1 ],swiz1 ); 1904t [i + 1 ]= vec_perm (c [i + 0 ],c [i + 1 ],swiz2 ); 1905 } 1906s [0 ]= vec_perm (t [0 ],t [2 ],swiz3 ); 1907s [1 ]= vec_perm (t [0 ],t [2 ],swiz4 ); 1908s [2 ]= vec_perm (t [1 ],t [3 ],swiz3 ); 1909s [3 ]= vec_perm (t [1 ],t [3 ],swiz4 ); 1910s [4 ]= vec_perm (t [4 ],t [6 ],swiz3 ); 1911s [5 ]= vec_perm (t [4 ],t [6 ],swiz4 ); 1912s [6 ]= vec_perm (t [5 ],t [7 ],swiz3 ); 1913s [7 ]= vec_perm (t [5 ],t [7 ],swiz4 ); 1914for (int i = 0 ;i < 8 ;++ i ) 1915vec_xst (s [i ],0 , (vec_t * )(vecOffset + i * 16 )); 1916 } 1917 } 1918 1919void packNormal (const TA * a ,int64_t lda ,int rows ,int cols ,unsigned char * vec ) { 1920int64_t i ,j ; 1921TA * aoffset = NULL ; 1922unsigned char * vecOffset = NULL ; 1923TA * aoffsets [8 ]; 1924vector unsigned char c_arr [8 ]; 1925aoffset = const_cast < TA *> (a ); 1926vecOffset = vec ; 1927j = (rows >>3 ); 1928if (j > 0 ) { 1929do { 1930aoffsets [0 ]= aoffset ; 1931if (cols == 4 ) { 1932aoffsets [0 ]= aoffset ; 1933for (int it = 1 ;it < 4 ;++ it ) 1934aoffsets [it ]= aoffsets [it - 1 ]+ lda ; 1935aoffset += 4 * lda ; 1936for (int i = 0 ;i < 4 ;++ i ) 1937c_arr [i ]= vec_xl (0 , (vector unsigned char * )aoffsets [i ]); 1938vector_permute_store (c_arr ,4 ,vecOffset ); 1939for (int i = 0 ;i < 4 ;i ++ ) 1940aoffsets [i ]= aoffsets [i ]+ lda ; 1941vecOffset += 64 ; 1942 } 1943i = (cols >>3 ); 1944if (i > 0 ) { 1945for (int it = 1 ;it < 8 ;++ it ) { 1946aoffsets [it ]= aoffsets [it - 1 ]+ lda ; 1947 } 1948aoffset += 8 * lda ; 1949 1950do { 1951for (int it = 0 ;it < 8 ;++ it ) 1952c_arr [it ]= vec_xl (0 , (vector unsigned char * )aoffsets [it ]); 1953vector_permute_store (c_arr ,8 ,vecOffset ); 1954for (int it = 0 ;it < 8 ;++ it ) 1955aoffsets [it ]= aoffsets [it ]+ 8 ; 1956vecOffset += 128 ; 1957i -- ; 1958 }while (i > 0 ); 1959 } 1960j -- ; 1961 }while (j > 0 ); 1962 } 1963if (rows & 4 ) { 1964aoffsets [0 ]= aoffset ; 1965for (int it = 1 ;it < 4 ;++ it ) 1966aoffsets [it ]= aoffsets [it - 1 ]+ lda ; 1967aoffset += 4 * lda ; 1968if (cols == 4 ) { 1969for (int it = 0 ;it < 4 ;++ it ) 1970c_arr [it ]= vec_xl (0 , (vector unsigned char * )aoffsets [it ]); 1971vector_permute_store (c_arr ,2 ,vecOffset ); 1972for (int it = 0 ;it < 4 ;it ++ ) 1973aoffsets [it ]= aoffsets [it ]+ lda ; 1974vecOffset += 32 ; 1975 } 1976i = (cols >>3 ); 1977if (i > 0 ) { 1978do { 1979for (int it = 0 ;it < 4 ;++ it ) 1980c_arr [it ]= vec_xl (0 , (vector unsigned char * )aoffsets [it ]); 1981vector_permute_store (c_arr ,4 ,vecOffset ); 1982for (int it = 0 ;it < 4 ;it ++ ) 1983aoffsets [it ]= aoffsets [it ]+ 8 * lda ; 1984vecOffset += 64 ; 1985i -- ; 1986 }while (i > 0 ); 1987 } 1988 } 1989if (rows & 3 ) { 1990aoffsets [0 ]= aoffset ; 1991for (int it = 1 ;it < 4 ;++ it ) 1992aoffsets [it ]= aoffsets [it - 1 ]+ lda ; 1993if (cols == 4 ) { 1994switch (rows ) { 1995case 3 :c_arr [2 ]= vec_xl (0 , (vector unsigned char * )aoffsets [2 ]); 1996case 2 :c_arr [1 ]= vec_xl (0 , (vector unsigned char * )aoffsets [1 ]); 1997case 1 :c_arr [0 ]= vec_xl (0 , (vector unsigned char * )aoffsets [0 ]); 1998break ; 1999 } 2000vector_permute_store (c_arr ,2 ,vecOffset ); 2001for (int it = 0 ;it < 4 ;it ++ ) 2002aoffsets [it ]= aoffsets [it ]+ lda ; 2003vecOffset += 32 ; 2004 } 2005i = (cols >>3 ); 2006if (i > 0 ) { 2007do { 2008switch (rows ) { 2009case 3 :c_arr [2 ]= vec_xl (0 , (vector unsigned char * )aoffsets [2 ]); 2010case 2 :c_arr [1 ]= vec_xl (0 , (vector unsigned char * )aoffsets [1 ]); 2011case 1 :c_arr [0 ]= vec_xl (0 , (vector unsigned char * )aoffsets [0 ]); 2012break ; 2013 } 2014vector_permute_store (c_arr ,4 ,vecOffset ); 2015for (int it = 0 ;it < 4 ;it ++ ) 2016aoffsets [it ]= aoffsets [it ]+ 8 * lda ; 2017vecOffset += 64 ; 2018i -- ; 2019 }while (i > 0 ); 2020 } 2021 } 2022 } 2023 2024void mnpack (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 2025int64_t mc ,nc ,mp ,np ; 2026int m_rem = MIN (m - m0 ,8 ); 2027int n_rem = MIN (n - n0 ,8 ); 2028 2029if (m_rem >=8 && n_rem >=8 ) { 2030mc = 8 ; 2031nc = 8 ; 2032gemm < 8 ,8 > (m0 ,m ,n0 ,n ); 2033 }else if (m_rem >=4 && n_rem >=8 ) { 2034mc = 4 ; 2035nc = 8 ; 2036gemm < 4 ,8 > (m0 ,m ,n0 ,n ); 2037 }else if (m_rem >=8 && n_rem >=4 ){ 2038mc = 8 ; 2039nc = 4 ; 2040gemm < 8 ,4 > (m0 ,m ,n0 ,n ); 2041 }else if ((m_rem < 4 )&& (n_rem >=8 )) { 2042nc = 8 ; 2043switch (m_rem ) { 2044case 1 : 2045mc = 1 ; 2046gemm_Mx8 < 1 > (m0 ,m ,n0 ,n ); 2047break ; 2048case 2 : 2049mc = 2 ; 2050gemm_Mx8 < 2 > (m0 ,m ,n0 ,n ); 2051break ; 2052case 3 : 2053mc = 3 ; 2054gemm_Mx8 < 3 > (m0 ,m ,n0 ,n ); 2055break ; 2056default : 2057return ; 2058 } 2059 }else if (m_rem >=4 && n_rem >=4 ) { 2060mc = 4 ; 2061nc = 4 ; 2062gemm_small < 4 ,4 > (m0 ,m ,n0 ,n ); 2063 }else if ((m_rem > 4 )&& (n_rem < 4 )) { 2064mc = 4 ; 2065switch (n_rem ) { 2066case 1 : 2067nc = 1 ; 2068gemm_small < 4 ,1 > (m0 ,m ,n0 ,n ); 2069break ; 2070case 2 : 2071nc = 2 ; 2072gemm_small < 4 ,2 > (m0 ,m ,n0 ,n ); 2073break ; 2074case 3 : 2075nc = 3 ; 2076gemm_small < 4 ,3 > (m0 ,m ,n0 ,n ); 2077break ; 2078 2079default : 2080return ; 2081 } 2082 }else { 2083switch ((m_rem <<4 ) |n_rem ) { 2084case 0x43 : 2085mc = 4 ; 2086nc = 3 ; 2087gemm_small < 4 ,3 > (m0 ,m ,n0 ,n ); 2088break ; 2089case 0x42 : 2090mc = 4 ; 2091nc = 2 ; 2092gemm_small < 4 ,2 > (m0 ,m ,n0 ,n ); 2093break ; 2094case 0x41 : 2095mc = 4 ; 2096nc = 1 ; 2097gemm_small < 4 ,1 > (m0 ,m ,n0 ,n ); 2098break ; 2099case 0x34 : 2100mc = 3 ; 2101nc = 4 ; 2102gemm_small < 3 ,4 > (m0 ,m ,n0 ,n ); 2103break ; 2104case 0x33 : 2105mc = 3 ; 2106nc = 3 ; 2107gemm_small < 3 ,3 > (m0 ,m ,n0 ,n ); 2108break ; 2109case 0x32 : 2110mc = 3 ; 2111nc = 2 ; 2112gemm_small < 3 ,2 > (m0 ,m ,n0 ,n ); 2113break ; 2114case 0x31 : 2115mc = 3 ; 2116nc = 1 ; 2117gemm_small < 3 ,1 > (m0 ,m ,n0 ,n ); 2118break ; 2119case 0x24 : 2120mc = 2 ; 2121nc = 4 ; 2122gemm_small < 2 ,4 > (m0 ,m ,n0 ,n ); 2123break ; 2124case 0x23 : 2125mc = 2 ; 2126nc = 3 ; 2127gemm_small < 2 ,3 > (m0 ,m ,n0 ,n ); 2128break ; 2129case 0x22 : 2130mc = 2 ; 2131nc = 2 ; 2132gemm_small < 2 ,2 > (m0 ,m ,n0 ,n ); 2133break ; 2134case 0x21 : 2135mc = 2 ; 2136nc = 1 ; 2137gemm_small < 2 ,1 > (m0 ,m ,n0 ,n ); 2138break ; 2139case 0x14 : 2140mc = 1 ; 2141nc = 4 ; 2142gemm_small < 1 ,4 > (m0 ,m ,n0 ,n ); 2143break ; 2144case 0x13 : 2145mc = 1 ; 2146nc = 3 ; 2147gemm_small < 1 ,3 > (m0 ,m ,n0 ,n ); 2148break ; 2149case 0x12 : 2150mc = 1 ; 2151nc = 2 ; 2152gemm_small < 1 ,2 > (m0 ,m ,n0 ,n ); 2153break ; 2154case 0x11 : 2155mc = 1 ; 2156nc = 1 ; 2157gemm_small < 1 ,1 > (m0 ,m ,n0 ,n ); 2158break ; 2159default : 2160return ; 2161 } 2162 } 2163mp = m0 + (m - m0 ) /mc * mc ; 2164np = n0 + (n - n0 ) /nc * nc ; 2165mnpack (mp ,m ,n0 ,np ); 2166mnpack (m0 ,m ,np ,n ); 2167 } 2168 2169void KERNEL_4x8 (int64_t ii ,int64_t jj ) { 2170vec_t vec_A [4 ],vec_B [8 ] ,vec_C [4 ]; 2171acc_t acc_0 ,acc_1 ; 2172__builtin_mma_xxsetaccz (& acc_0 ); 2173__builtin_mma_xxsetaccz (& acc_1 ); 2174for (int l = 0 ;l < k ;l += 8 ) { 2175packNormal ((A + (ii * lda )+ l ),lda ,4 ,8 , (uint8_t * )vec_A ); 2176packNormal ((B + (jj * ldb )+ l ),ldb ,8 ,8 , (uint8_t * )vec_B ); 2177for (int x = 0 ;x < 4 ;x ++ ) { 2178mma_instr < TA > ::outer_product (& acc_0 ,vec_A [x ],vec_B [x ]); 2179mma_instr < TA > ::outer_product (& acc_1 ,vec_A [x ],vec_B [x + 4 ]); 2180 } 2181 } 2182save_acc (& acc_0 ,ii ,jj ); 2183save_acc (& acc_1 ,ii ,jj + 4 ); 2184 } 2185 2186void KERNEL_8x4 (int64_t ii ,int64_t jj ) { 2187vec_t vec_A [8 ],vec_B [4 ] ,vec_C [4 ]; 2188acc_t acc_0 ,acc_1 ; 2189__builtin_mma_xxsetaccz (& acc_0 ); 2190__builtin_mma_xxsetaccz (& acc_1 ); 2191for (int l = 0 ;l < k ;l += 8 ) { 2192packNormal ((A + (ii * lda )+ l ),lda ,8 ,8 , (uint8_t * )vec_A ); 2193packNormal ((B + (jj * ldb )+ l ),ldb ,8 ,4 , (uint8_t * )vec_B ); 2194for (int x = 0 ;x < 4 ;x ++ ) { 2195mma_instr < TA > ::outer_product (& acc_0 ,vec_A [x ],vec_B [x ]); 2196mma_instr < TA > ::outer_product (& acc_1 ,vec_A [x + 4 ],vec_B [x ]); 2197 } 2198 } 2199save_acc (& acc_0 ,ii ,jj ); 2200save_acc (& acc_1 ,ii + 4 ,jj ); 2201 } 2202 2203 2204void KERNEL_8x8 (int64_t ii ,int64_t jj ) { 2205vec_t vec_A [8 ],vec_B [8 ],vec_C [4 ]; 2206acc_t acc_0 ,acc_1 ,acc_2 ,acc_3 ; 2207__builtin_mma_xxsetaccz (& acc_0 ); 2208__builtin_mma_xxsetaccz (& acc_1 ); 2209__builtin_mma_xxsetaccz (& acc_2 ); 2210__builtin_mma_xxsetaccz (& acc_3 ); 2211for (int l = 0 ;l < k ;l += 8 ) { 2212packNormal (A + (ii * lda )+ l ,lda ,8 ,8 , (uint8_t * )vec_A ); 2213packNormal (B + (jj * ldb )+ l ,ldb ,8 ,8 , (uint8_t * )vec_B ); 2214for (int x = 0 ;x < 4 ;x ++ ) { 2215mma_instr < TA > ::outer_product (& acc_0 ,vec_A [x ],vec_B [x ]); 2216mma_instr < TA > ::outer_product (& acc_1 ,vec_A [x ],vec_B [x + 4 ]); 2217mma_instr < TA > ::outer_product (& acc_2 ,vec_A [x + 4 ],vec_B [x ]); 2218mma_instr < TA > ::outer_product (& acc_3 ,vec_A [x + 4 ],vec_B [x + 4 ]); 2219 } 2220 } 2221save_acc (& acc_0 ,ii ,jj ); 2222save_acc (& acc_1 ,ii ,jj + 4 ); 2223save_acc (& acc_2 ,ii + 4 ,jj ); 2224save_acc (& acc_3 ,ii + 4 ,jj + 4 ); 2225 } 2226 2227inline void MMA_16x8 (vec_t * vec_A0 ,vec_t * vec_A1 ,vec_t * vec_B ,acc_t * acc ) { 2228for (int x = 0 ;x < 4 ;x ++ ) { 2229mma_instr < TA > ::outer_product (& acc [0 ],vec_A0 [x ],vec_B [x ]); 2230mma_instr < TA > ::outer_product (& acc [1 ],vec_A0 [x ],vec_B [x + 4 ]); 2231mma_instr < TA > ::outer_product (& acc [2 ],vec_A0 [x + 4 ],vec_B [x ]); 2232mma_instr < TA > ::outer_product (& acc [3 ],vec_A0 [x + 4 ],vec_B [x + 4 ]); 2233mma_instr < TA > ::outer_product (& acc [4 ],vec_A1 [x ],vec_B [x ]); 2234mma_instr < TA > ::outer_product (& acc [5 ],vec_A1 [x ],vec_B [x + 4 ]); 2235mma_instr < TA > ::outer_product (& acc [6 ],vec_A1 [x + 4 ],vec_B [x ]); 2236mma_instr < TA > ::outer_product (& acc [7 ],vec_A1 [x + 4 ],vec_B [x + 4 ]); 2237 } 2238 } 2239void KERNEL (int64_t ii ,int64_t jj ,int64_t mc ,int64_t nc ,int64_t kc ,vec_t * vec_A ,vec_t * vec_B ,int64_t kk ) { 2240for (int64_t i = 0 ;i < mc ;i += 16 ) { 2241int A_base_addr = (mc /8 )* (i /8 )* 8 ; 2242for (int64_t j = 0 ;j < nc ;j += 8 ) { 2243int B_base_addr = (nc /8 )* (j /8 )* 8 ; 2244acc_t acc [8 ]; 2245vec_t A0_block [8 ];vec_t A1_block [8 ]; 2246for (int x = 0 ;x < 8 ;x ++ ) 2247__builtin_mma_xxsetaccz (& acc [x ]); 2248for (int64_t l = 0 ;l < kc ;l += 8 ) { 2249int A0_block_idx = A_base_addr + (l /8 )* 8 ; 2250int A1_block_idx = A0_block_idx + (mc /8 )* 8 ; 2251int B_block_idx = B_base_addr + (l /8 )* 8 ; 2252vec_t * A0_block = & vec_A [A0_block_idx ]; 2253vec_t * A1_block = & vec_A [A1_block_idx ]; 2254vec_t * B_block = & vec_B [B_block_idx ]; 2255MMA_16x8 (A0_block ,A1_block ,B_block ,acc ); 2256 } 2257if (kk == 0 ) { 2258save_acc (& acc [0 ],ii + i ,jj + j ); 2259save_acc (& acc [1 ],ii + i ,jj + j + 4 ); 2260save_acc (& acc [2 ],ii + i + 4 ,jj + j ); 2261save_acc (& acc [3 ],ii + i + 4 ,jj + j + 4 ); 2262save_acc (& acc [4 ],ii + i + 8 ,jj + j ); 2263save_acc (& acc [5 ],ii + i + 8 ,jj + j + 4 ); 2264save_acc (& acc [6 ],ii + i + 12 ,jj + j ); 2265save_acc (& acc [7 ],ii + i + 12 ,jj + j + 4 ); 2266 }else { 2267add_save_acc (& acc [0 ],ii + i ,jj + j ); 2268add_save_acc (& acc [1 ],ii + i ,jj + j + 4 ); 2269add_save_acc (& acc [2 ],ii + i + 4 ,jj + j ); 2270add_save_acc (& acc [3 ],ii + i + 4 ,jj + j + 4 ); 2271add_save_acc (& acc [4 ],ii + i + 8 ,jj + j ); 2272add_save_acc (& acc [5 ],ii + i + 8 ,jj + j + 4 ); 2273add_save_acc (& acc [6 ],ii + i + 12 ,jj + j ); 2274add_save_acc (& acc [7 ],ii + i + 12 ,jj + j + 4 ); 2275 } 2276 } 2277 } 2278 } 2279template < int RM ,int RN > 2280void gemm_small (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 2281int64_t ytiles = (m - m0 ) /RM ; 2282int64_t xtiles = (n - n0 ) /RN ; 2283int64_t tiles = xtiles * ytiles ; 2284int64_t duty = (tiles + nth - 1 ) /nth ; 2285int64_t start = duty * ith ; 2286int64_t end = start + duty ; 2287if (end > tiles ) 2288end = tiles ; 2289for (int64_t job = start ;job < end ;++ job ) { 2290int64_t ii = m0 + job /xtiles * RM ; 2291int64_t jj = n0 + job %xtiles * RN ; 2292vec_t vec_C [4 ]; 2293acc_t acc_0 ; 2294__builtin_mma_xxsetaccz (& acc_0 ); 2295vec_t vec_A [2 ],vec_B [2 ]; 2296for (int l = 0 ;l < k ;l += 4 ) { 2297packNormal (A + (ii * lda )+ l ,lda ,RM ,4 , (uint8_t * )vec_A ); 2298packNormal (B + (jj * ldb )+ l ,ldb ,RN ,4 , (uint8_t * )vec_B ); 2299for (int x = 0 ;x < 2 ;x ++ ) { 2300mma_instr < TA > ::outer_product (& acc_0 ,vec_A [x ],vec_B [x ]); 2301 } 2302 } 2303__builtin_mma_disassemble_acc (vec_C ,& acc_0 ); 2304for (int I = 0 ;I < RM ;I ++ ) { 2305for (int J = 0 ;J < RN ;J ++ ) { 2306* ((TC * )(C + ii + ((jj + J )* ldc )+ I ))= * ((TC * )& vec_C [I ]+ J ); 2307 } 2308 } 2309 } 2310 } 2311 2312template < int RM > 2313void gemm_Mx8 (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 2314int RN = 8 ; 2315int64_t ytiles = (m - m0 ) /RM ; 2316int64_t xtiles = (n - n0 ) /RN ; 2317int64_t tiles = xtiles * ytiles ; 2318int64_t duty = (tiles + nth - 1 ) /nth ; 2319int64_t start = duty * ith ; 2320int64_t end = start + duty ; 2321if (end > tiles ) 2322end = tiles ; 2323for (int64_t job = start ;job < end ;++ job ) { 2324int64_t ii = m0 + job /xtiles * RM ; 2325int64_t jj = n0 + job %xtiles * RN ; 2326vec_t vec_C [4 ]; 2327acc_t acc_0 ,acc_1 ; 2328__builtin_mma_xxsetaccz (& acc_0 ); 2329__builtin_mma_xxsetaccz (& acc_1 ); 2330vec_t vec_A [4 ],vec_B [8 ]; 2331for (int l = 0 ;l < k ;l += 8 ) { 2332packNormal (A + (ii * lda )+ l ,lda ,RM ,8 , (uint8_t * )vec_A ); 2333packNormal (B + (jj * ldb )+ l ,ldb ,RN ,8 , (uint8_t * )vec_B ); 2334for (int x = 0 ;x < 4 ;x ++ ) { 2335mma_instr < TA > ::outer_product (& acc_0 ,vec_A [x ],vec_B [x ]); 2336mma_instr < TA > ::outer_product (& acc_1 ,vec_A [x ],vec_B [x + 4 ]); 2337 } 2338 } 2339__builtin_mma_disassemble_acc (vec_C ,& acc_0 ); 2340for (int I = 0 ;I < RM ;I ++ ) { 2341for (int J = 0 ;J < 4 ;J ++ ) { 2342* ((TC * )(C + ii + ((jj + J )* ldc )+ I ))= * ((TC * )& vec_C [I ]+ J ); 2343 } 2344 } 2345__builtin_mma_disassemble_acc (vec_C ,& acc_1 ); 2346for (int I = 0 ;I < RM ;I ++ ) { 2347for (int J = 0 ;J < 4 ;J ++ ) { 2348* ((TC * )(C + ii + ((jj + 4 + J )* ldc )+ I ))= * ((TC * )& vec_C [I ]+ J ); 2349 } 2350 } 2351 } 2352 } 2353 2354template < int RM ,int RN > 2355inline void kernel (int64_t ii ,int64_t jj ) { 2356if constexpr (RM == 4 && RN == 8 ) { 2357KERNEL_4x8 (ii ,jj ); 2358 }else if constexpr (RM == 8 && RN == 8 ) { 2359KERNEL_8x8 (ii ,jj ); 2360 }else if constexpr (RM == 8 && RN == 4 ) { 2361KERNEL_8x4 (ii ,jj ); 2362 }else { 2363assert (false&& "RN/RM values not supported" ); 2364 } 2365 } 2366 2367void matmul_tiled (int64_t m ,int64_t n ,int64_t mc ,int64_t nc ,int64_t kc ) { 2368int64_t ytiles = m /mc ; 2369int64_t xtiles = n /nc ; 2370int64_t tiles = xtiles * ytiles ; 2371int64_t duty = (tiles + nth - 1 ) /nth ; 2372int64_t start = duty * ith ; 2373int64_t end = start + duty ; 2374if (end > tiles ) { 2375end = tiles ; 2376 } 2377for (int64_t job = start ;job < end ;++ job ) { 2378int64_t ii = (job /xtiles )* mc ; 2379int64_t jj = (job %xtiles )* nc ; 2380for (int64_t kk = 0 ;kk < k ;kk += kc ) { 2381vec_t A_pack [kc * mc /8 ]; 2382vec_t B_pack [kc * nc /8 ]; 2383packNormal (A + (ii * lda )+ kk ,lda ,kc ,mc , (uint8_t * )A_pack ); 2384packNormal (B + (jj * ldb )+ kk ,ldb ,kc ,nc , (uint8_t * )B_pack ); 2385KERNEL (ii ,jj ,mc ,nc ,kc ,A_pack ,B_pack ,kk ); 2386 } 2387 } 2388 } 2389 2390template < int RM ,int RN > 2391NOINLINE void gemm (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 2392int64_t ytiles = (m - m0 ) /RM ; 2393int64_t xtiles = (n - n0 ) /RN ; 2394int64_t tiles = xtiles * ytiles ; 2395int64_t duty = (tiles + nth - 1 ) /nth ; 2396int64_t start = duty * ith ; 2397int64_t end = start + duty ; 2398if (end > tiles ) 2399end = tiles ; 2400for (int64_t job = start ;job < end ;++ job ) { 2401int64_t ii = m0 + job /xtiles * RM ; 2402int64_t jj = n0 + job %xtiles * RN ; 2403kernel < RM ,RN > (ii ,jj ); 2404 } 2405 } 2406 2407const TA * const A ; 2408const TB * const B ; 2409TC * C ; 2410const int64_t k ; 2411const int64_t lda ; 2412const int64_t ldb ; 2413const int64_t ldc ; 2414const int ith ; 2415const int nth ; 2416}; 2417 2418template < typename TA > 2419class tinyBLAS_Q0_PPC { 2420public : 2421tinyBLAS_Q0_PPC (int64_t k , 2422const TA * A ,int64_t lda , 2423const block_q8_0 * B ,int64_t ldb , 2424float * C ,int64_t ldc , 2425int ith ,int nth ) 2426 :A (A ),B (B ),C (C ),k (k ),lda (lda ),ldb (ldb ),ldc (ldc ),ith (ith ),nth (nth ) { 2427 } 2428 2429void matmul (int64_t m ,int64_t n ) { 2430int64_t mc = 64 ; 2431int64_t nc = 64 ; 2432int64_t kc = 64 ; 2433int64_t n_chunk = 64 ; 2434#if defined(_AIX )|| defined(__BIG_ENDIAN__ ) 2435mc = 32 ; 2436nc = 32 ; 2437kc = 32 ; 2438n_chunk = 32 ; 2439#endif 2440int64_t n_aligned = 0 ; 2441if (n %n_chunk == 0 ) { 2442n_aligned = n ; 2443 }else if (n == 4 ) { 2444n_aligned = 4 ; 2445 }else if (n < n_chunk ) { 2446n_aligned = (n /8 )* 8 ; 2447 }else { 2448n_aligned = (n /n_chunk )* n_chunk ; 2449 } 2450if (n_aligned > 0 ) { 2451if (n_aligned %n_chunk == 0 )nc = n_chunk ; 2452else if (n_aligned == n )nc = n ; 2453else if (n_aligned %32 == 0 )nc = 32 ; 2454else if (n_aligned %24 == 0 )nc = 24 ; 2455else if (n_aligned %16 == 0 )nc = 16 ; 2456else nc = 8 ; 2457 } 2458bool can_use_tiled = n_aligned > 0 && (m %mc == 0 ); 2459if (can_use_tiled ) { 2460matmul_tiled (m ,n_aligned ,mc ,nc ,kc ); 2461if (n > n_aligned ) { 2462mnpack (0 ,m ,n_aligned ,n ); 2463 } 2464 }else { 2465mnpack (0 ,m ,0 ,n ); 2466 } 2467 } 2468 2469private : 2470inline void save_res (int ii ,int jj ,int idx ,vector float * fin_res ,int RM = 4 ,int RN = 4 ) { 2471for (int I = 0 ;I < RM ;I ++ ) { 2472for (int J = 0 ;J < RN ;J ++ ) { 2473* ((float * )(C + ii + ((jj + J )* ldc )+ I ))= * ((float * )& fin_res [idx + I ]+ J ); 2474 } 2475 } 2476 } 2477 2478inline void save_acc (acc_t * ACC ,int64_t ii ,int64_t jj ) { 2479vec_t vec_C [4 ]; 2480__builtin_mma_disassemble_acc (vec_C ,ACC ); 2481for (int I = 0 ;I < 4 ;I ++ ) { 2482for (int J = 0 ;J < 4 ;J ++ ) { 2483* ((float * )(C + ii + ((jj + J )* ldc )+ I ))= * ((float * )& vec_C [I ]+ J ); 2484 } 2485 } 2486 } 2487 2488inline void add_save_acc (acc_t * ACC ,int64_t ii ,int64_t jj ) { 2489vec_t vec_C [4 ]; 2490__builtin_mma_disassemble_acc (vec_C ,ACC ); 2491for (int I = 0 ;I < 4 ;I ++ ) { 2492for (int J = 0 ;J < 4 ;J ++ ) { 2493float * c_ptr = (float * )(C + ii + ((jj + J )* ldc )+ I ); 2494* c_ptr += * ((float * )& vec_C [I ]+ J ); 2495 } 2496 } 2497 } 2498 2499template < typename ArrayType > 2500inline void compute (acc_t * ACC ,int c_idx ,int s_idx ,ArrayType & comparray ,vector float * vs ,vector float * fin_res ) { 2501vector signed int vec_C [4 ]; 2502vector float CA [4 ]= {0 }; 2503vector float res [4 ]= {0 }; 2504__builtin_mma_disassemble_acc (vec_C ,ACC ); 2505for (int i = 0 ;i < 4 ;i ++ ) { 2506CA [i ]= vec_splats ((float )(((double )comparray [c_idx + i ])* -128.0 )); 2507res [i ]= vec_add (vec_ctf (vec_C [i ],0 ),CA [i ]); 2508fin_res [s_idx + i ]= vec_madd (res [i ],vs [s_idx + i ],fin_res [s_idx + i ]); 2509 } 2510 } 2511 2512inline void process_q4_elements (vector signed char (& c )[2 ],int * ca ) { 2513const vector signed char lowMask = vec_splats ((signed char )0xF ); 2514const vector unsigned char v4 = vec_splats ((unsigned char )0x4 ); 2515const vector signed char v8 = vec_splats ((signed char )0x8 ); 2516vector signed int vsum = {0 }; 2517vector signed int vsum2 = {0 }; 2518c [0 ]= vec_and (c [1 ],lowMask ); 2519c [1 ]= vec_sr (c [1 ],v4 ); 2520c [0 ]= vec_sub (c [0 ],v8 ); 2521c [1 ]= vec_sub (c [1 ],v8 ); 2522vsum = vec_sum4s (c [0 ],vsum ); 2523vsum2 = vec_sum4s (c [1 ],vsum2 ); 2524vsum = vec_add (vsum ,vsum2 ); 2525* (ca )= vsum [0 ]+ vsum [1 ]+ vsum [2 ]+ vsum [3 ]; 2526 } 2527 2528template < typename V1 ,typename V2 > 2529inline void vector_permute_store (V2 & s1 ,V2 & s2 ,V2 & s3 ,V2 & s4 ,V1 * vecOffset ,bool flip ) { 2530vector unsigned char swiz1 = {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,16 ,17 ,18 ,19 ,20 ,21 ,22 ,23 }; 2531vector unsigned char swiz2 = {8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 }; 2532vector unsigned char swiz3 = {0 ,1 ,2 ,3 ,8 ,9 ,10 ,11 ,16 ,17 ,18 ,19 ,24 ,25 ,26 ,27 }; 2533vector unsigned char swiz4 = {4 ,5 ,6 ,7 ,12 ,13 ,14 ,15 ,20 ,21 ,22 ,23 ,28 ,29 ,30 ,31 }; 2534V2 t1 ,t2 ,t3 ,t4 ,t5 ,t6 ,t7 ,t8 ; 2535vector unsigned char xor_vector ; 2536uint8_t flip_vec = 0x80 ; 2537xor_vector = vec_splats (flip_vec ); 2538t1 = vec_perm (s1 ,s2 ,swiz1 ); 2539t2 = vec_perm (s1 ,s2 ,swiz2 ); 2540t3 = vec_perm (s3 ,s4 ,swiz1 ); 2541t4 = vec_perm (s3 ,s4 ,swiz2 ); 2542t5 = vec_perm (t1 ,t3 ,swiz3 ); 2543t6 = vec_perm (t1 ,t3 ,swiz4 ); 2544t7 = vec_perm (t2 ,t4 ,swiz3 ); 2545t8 = vec_perm (t2 ,t4 ,swiz4 ); 2546if (flip == true) { 2547t5 = vec_xor (t5 ,xor_vector ); 2548t6 = vec_xor (t6 ,xor_vector ); 2549t7 = vec_xor (t7 ,xor_vector ); 2550t8 = vec_xor (t8 ,xor_vector ); 2551 } 2552vec_xst (t5 ,0 ,vecOffset ); 2553vec_xst (t6 ,0 ,vecOffset + 16 ); 2554vec_xst (t7 ,0 ,vecOffset + 32 ); 2555vec_xst (t8 ,0 ,vecOffset + 48 ); 2556 } 2557 2558inline void unpack_q4_to_q8 (vector signed char packed ,vector signed char & lo ,vector signed char & hi ) { 2559const vector signed char lowMask = vec_splats ((signed char )0x0F ); 2560const vector signed char v8 = vec_splats ((signed char )0x08 ); 2561const vector unsigned char v4 = vec_splats ((unsigned char )4 ); 2562lo = vec_and (packed ,lowMask ); 2563hi = vec_sr (packed ,v4 ); 2564lo = vec_sub (lo ,v8 ); 2565hi = vec_sub (hi ,v8 ); 2566 } 2567 2568inline void vector_permute_store_fp16 (vec_t * c ,unsigned char * vecOffset ) { 2569vec_t t [8 ],s [8 ]; 2570vec_t swiz1 = {0 ,1 ,2 ,3 ,16 ,17 ,18 ,19 ,4 ,5 ,6 ,7 ,20 ,21 ,22 ,23 }; 2571vec_t swiz2 = {8 ,9 ,10 ,11 ,24 ,25 ,26 ,27 ,12 ,13 ,14 ,15 ,28 ,29 ,30 ,31 }; 2572vec_t swiz3 = {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,16 ,17 ,18 ,19 ,20 ,21 ,22 ,23 }; 2573vec_t swiz4 = {8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 }; 2574for (int i = 0 ;i < 4 ;i += 2 ) { 2575t [i + 0 ]= vec_perm (c [i + 0 ],c [i + 1 ],swiz1 ); 2576t [i + 1 ]= vec_perm (c [i + 0 ],c [i + 1 ],swiz2 ); 2577 } 2578for (int i = 4 ;i < 8 ;i += 2 ) { 2579t [i + 0 ]= vec_perm (c [i + 0 ],c [i + 1 ],swiz1 ); 2580t [i + 1 ]= vec_perm (c [i + 0 ],c [i + 1 ],swiz2 ); 2581 } 2582s [0 ]= vec_perm (t [0 ],t [2 ],swiz3 ); 2583s [1 ]= vec_perm (t [0 ],t [2 ],swiz4 ); 2584s [2 ]= vec_perm (t [1 ],t [3 ],swiz3 ); 2585s [3 ]= vec_perm (t [1 ],t [3 ],swiz4 ); 2586s [4 ]= vec_perm (t [4 ],t [6 ],swiz3 ); 2587s [5 ]= vec_perm (t [4 ],t [6 ],swiz4 ); 2588s [6 ]= vec_perm (t [5 ],t [7 ],swiz3 ); 2589s [7 ]= vec_perm (t [5 ],t [7 ],swiz4 ); 2590for (int i = 0 ;i < 8 ;++ i ) { 2591vec_xst (s [i ],0 , (vec_t * )(vecOffset + i * 16 )); 2592 } 2593 } 2594 2595static inline void convert_and_scale_q8 (vector signed char raw ,vector float v_scale ,vector unsigned short & out_hi ,vector unsigned short & out_lo ) { 2596vector signed short i16_hi = vec_unpackh (raw ); 2597vector signed short i16_lo = vec_unpackl (raw ); 2598 2599vector float f_hi_h = vec_ctf (vec_unpackh (i16_hi ),0 ); 2600vector float f_hi_l = vec_ctf (vec_unpackl (i16_hi ),0 ); 2601vector float f_lo_h = vec_ctf (vec_unpackh (i16_lo ),0 ); 2602vector float f_lo_l = vec_ctf (vec_unpackl (i16_lo ),0 ); 2603out_hi = vec_pack_to_short_fp32 (vec_mul (f_hi_h ,v_scale ),vec_mul (f_hi_l ,v_scale )); 2604out_lo = vec_pack_to_short_fp32 (vec_mul (f_lo_h ,v_scale ),vec_mul (f_lo_l ,v_scale )); 2605 } 2606 2607void packNormal_q4_fp16 (const block_q4_0 * a ,int64_t lda ,int rows ,int blocks ,unsigned char * vec ) { 2608unsigned char * vecOffset = vec ; 2609for (int i = 0 ;i < rows ;i += 8 ) { 2610const block_q4_0 * rows_base [8 ]; 2611for (int r = 0 ;r < 8 ;r ++ ) { 2612rows_base [r ]= a + (i + r )* lda ; 2613 } 2614for (int blk = 0 ;blk < blocks ;blk ++ ) { 2615vector unsigned short hp_res [8 ][4 ]; 2616for (int r = 0 ;r < 8 ;r ++ ) { 2617const block_q4_0 * current_blk = rows_base [r ]+ blk ; 2618vector float v_scale = vec_extract_fp32_from_shorth (vec_splats (current_blk -> d )); 2619vector signed char v_qs = vec_xl (0 , (const vector signed char * )current_blk -> qs ); 2620vector signed char c1 ,c2 ; 2621unpack_q4_to_q8 (v_qs ,c1 ,c2 ); 2622convert_and_scale_q8 (c1 ,v_scale ,hp_res [r ][0 ],hp_res [r ][1 ]); 2623convert_and_scale_q8 (c2 ,v_scale ,hp_res [r ][2 ],hp_res [r ][3 ]); 2624 } 2625for (int c = 0 ;c < 4 ;c ++ ) { 2626vector unsigned char c_arr [8 ]; 2627for (int r = 0 ;r < 8 ;r ++ ) { 2628c_arr [r ]= (vector unsigned char )hp_res [r ][c ]; 2629 } 2630vector_permute_store_fp16 ((vec_t * )c_arr ,vecOffset ); 2631vecOffset += 128 ; 2632 } 2633 } 2634 } 2635 } 2636 2637template < int chunk_size > 2638static inline void pack_q8_block (const block_q8_0 * a ,int64_t lda ,int rows ,int blocks ,unsigned char * vec ) { 2639unsigned char * vecOffset = vec ; 2640const vec_t swiz1 = {0 ,1 ,2 ,3 ,16 ,17 ,18 ,19 ,4 ,5 ,6 ,7 ,20 ,21 ,22 ,23 }; 2641const vec_t swiz2 = {8 ,9 ,10 ,11 ,24 ,25 ,26 ,27 ,12 ,13 ,14 ,15 ,28 ,29 ,30 ,31 }; 2642const vec_t swiz3 = {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,16 ,17 ,18 ,19 ,20 ,21 ,22 ,23 }; 2643const vec_t swiz4 = {8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 }; 2644 2645for (int i = 0 ;i < rows ;i += chunk_size ) { 2646const block_q8_0 * rows_base [chunk_size ]; 2647for (int r = 0 ;r < chunk_size ;r ++ ) { 2648rows_base [r ]= a + (i + r )* lda ; 2649 } 2650for (int blk = 0 ;blk < blocks ;blk ++ ) { 2651vector unsigned short hp_res [chunk_size ][4 ]; 2652for (int r = 0 ;r < chunk_size ;r ++ ) { 2653const block_q8_0 * b = rows_base [r ]+ blk ; 2654vector float v_scale = vec_extract_fp32_from_shorth (vec_splats (b -> d )); 2655vector signed char c [2 ]; 2656__vector_pair pair = __builtin_vsx_lxvp (0 , (__vector_pair * )b -> qs ); 2657__builtin_vsx_disassemble_pair (c ,& pair ); 2658convert_and_scale_q8 (c [0 ],v_scale ,hp_res [r ][0 ],hp_res [r ][1 ]); 2659convert_and_scale_q8 (c [1 ],v_scale ,hp_res [r ][2 ],hp_res [r ][3 ]); 2660 } 2661for (int col = 0 ;col < 4 ;col ++ ) { 2662if constexpr (chunk_size == 8 ) { 2663vec_t t [8 ]; 2664t [0 ]= vec_perm ((vec_t )hp_res [0 ][col ], (vec_t )hp_res [1 ][col ],swiz1 ); 2665t [1 ]= vec_perm ((vec_t )hp_res [0 ][col ], (vec_t )hp_res [1 ][col ],swiz2 ); 2666t [2 ]= vec_perm ((vec_t )hp_res [2 ][col ], (vec_t )hp_res [3 ][col ],swiz1 ); 2667t [3 ]= vec_perm ((vec_t )hp_res [2 ][col ], (vec_t )hp_res [3 ][col ],swiz2 ); 2668t [4 ]= vec_perm ((vec_t )hp_res [4 ][col ], (vec_t )hp_res [5 ][col ],swiz1 ); 2669t [5 ]= vec_perm ((vec_t )hp_res [4 ][col ], (vec_t )hp_res [5 ][col ],swiz2 ); 2670t [6 ]= vec_perm ((vec_t )hp_res [6 ][col ], (vec_t )hp_res [7 ][col ],swiz1 ); 2671t [7 ]= vec_perm ((vec_t )hp_res [6 ][col ], (vec_t )hp_res [7 ][col ],swiz2 ); 2672 2673vec_xst (vec_perm (t [0 ],t [2 ],swiz3 ),0 , (vec_t * )(vecOffset + 0 )); 2674vec_xst (vec_perm (t [0 ],t [2 ],swiz4 ),0 , (vec_t * )(vecOffset + 16 )); 2675vec_xst (vec_perm (t [1 ],t [3 ],swiz3 ),0 , (vec_t * )(vecOffset + 32 )); 2676vec_xst (vec_perm (t [1 ],t [3 ],swiz4 ),0 , (vec_t * )(vecOffset + 48 )); 2677vec_xst (vec_perm (t [4 ],t [6 ],swiz3 ),0 , (vec_t * )(vecOffset + 64 )); 2678vec_xst (vec_perm (t [4 ],t [6 ],swiz4 ),0 , (vec_t * )(vecOffset + 80 )); 2679vec_xst (vec_perm (t [5 ],t [7 ],swiz3 ),0 , (vec_t * )(vecOffset + 96 )); 2680vec_xst (vec_perm (t [5 ],t [7 ],swiz4 ),0 , (vec_t * )(vecOffset + 112 )); 2681vecOffset += 128 ; 2682 }else { 2683vec_t t0 = vec_perm ((vec_t )hp_res [0 ][col ], (vec_t )hp_res [1 ][col ],swiz1 ); 2684vec_t t1 = vec_perm ((vec_t )hp_res [0 ][col ], (vec_t )hp_res [1 ][col ],swiz2 ); 2685vec_t t2 = vec_perm ((vec_t )hp_res [2 ][col ], (vec_t )hp_res [3 ][col ],swiz1 ); 2686vec_t t3 = vec_perm ((vec_t )hp_res [2 ][col ], (vec_t )hp_res [3 ][col ],swiz2 ); 2687 2688vec_xst (vec_perm (t0 ,t2 ,swiz3 ),0 , (vec_t * )(vecOffset + 0 )); 2689vec_xst (vec_perm (t0 ,t2 ,swiz4 ),0 , (vec_t * )(vecOffset + 16 )); 2690vec_xst (vec_perm (t1 ,t3 ,swiz3 ),0 , (vec_t * )(vecOffset + 32 )); 2691vec_xst (vec_perm (t1 ,t3 ,swiz4 ),0 , (vec_t * )(vecOffset + 48 )); 2692vecOffset += 64 ; 2693 } 2694 } 2695 } 2696 } 2697 } 2698 2699void packNormal_q8_fp16 (const block_q8_0 * a ,int64_t lda ,int rows ,int blocks ,unsigned char * vec ) { 2700if (rows == 4 ) { 2701pack_q8_block < 4 > (a ,lda ,rows ,blocks ,vec ); 2702 }else { 2703pack_q8_block < 8 > (a ,lda ,rows ,blocks ,vec ); 2704 } 2705 } 2706 2707template < int size > 2708void packNormalInt4 (const TA * a ,int64_t lda ,int rows ,int cols ,int8_t * vec , std::array < int ,size > & comparray ) { 2709int64_t i ,j ; 2710TA * aoffset = NULL ; 2711int8_t * vecOffset = NULL ; 2712TA * aoffset1 = NULL ,* aoffset2 = NULL ,* aoffset3 = NULL ,* aoffset4 = NULL ; 2713TA * aoffset5 = NULL ,* aoffset6 = NULL ,* aoffset7 = NULL ,* aoffset8 = NULL ; 2714vector signed char c1 [2 ]= {0 },c2 [2 ]= {0 },c3 [2 ]= {0 },c4 [2 ]= {0 }; 2715vector signed char c5 [2 ]= {0 },c6 [2 ]= {0 },c7 [2 ]= {0 },c8 [2 ]= {0 }; 2716aoffset = const_cast < TA *> (a ); 2717vecOffset = vec ; 2718j = (rows >>3 ); 2719if (j > 0 ) { 2720do { 2721aoffset1 = aoffset ; 2722aoffset2 = aoffset1 + lda ; 2723aoffset3 = aoffset2 + lda ; 2724aoffset4 = aoffset3 + lda ; 2725aoffset5 = aoffset4 + lda ; 2726aoffset6 = aoffset5 + lda ; 2727aoffset7 = aoffset6 + lda ; 2728aoffset8 = aoffset7 + lda ; 2729aoffset += 8 * lda ; 2730i = (cols >>2 ); 2731if (i > 0 ) { 2732do { 2733c1 [1 ]= vec_xl (0 , (const vector signed char * )aoffset1 -> qs ); 2734c2 [1 ]= vec_xl (0 , (const vector signed char * )aoffset2 -> qs ); 2735c3 [1 ]= vec_xl (0 , (const vector signed char * )aoffset3 -> qs ); 2736c4 [1 ]= vec_xl (0 , (const vector signed char * )aoffset4 -> qs ); 2737c5 [1 ]= vec_xl (0 , (const vector signed char * )aoffset5 -> qs ); 2738c6 [1 ]= vec_xl (0 , (const vector signed char * )aoffset6 -> qs ); 2739c7 [1 ]= vec_xl (0 , (const vector signed char * )aoffset7 -> qs ); 2740c8 [1 ]= vec_xl (0 , (const vector signed char * )aoffset8 -> qs ); 2741 2742process_q4_elements (c1 ,& comparray [0 ]); 2743process_q4_elements (c2 ,& comparray [1 ]); 2744process_q4_elements (c3 ,& comparray [2 ]); 2745process_q4_elements (c4 ,& comparray [3 ]); 2746process_q4_elements (c5 ,& comparray [4 ]); 2747process_q4_elements (c6 ,& comparray [5 ]); 2748process_q4_elements (c7 ,& comparray [6 ]); 2749process_q4_elements (c8 ,& comparray [7 ]); 2750vector_permute_store < int8_t ,vector signed char > (c1 [0 ],c2 [0 ],c3 [0 ],c4 [0 ],vecOffset , false); 2751vector_permute_store < int8_t ,vector signed char > (c1 [1 ],c2 [1 ],c3 [1 ],c4 [1 ],vecOffset + 64 , false); 2752vector_permute_store < int8_t ,vector signed char > (c5 [0 ],c6 [0 ],c7 [0 ],c8 [0 ],vecOffset + 128 , false); 2753vector_permute_store < int8_t ,vector signed char > (c5 [1 ],c6 [1 ],c7 [1 ],c8 [1 ],vecOffset + 192 , false); 2754aoffset1 += lda ; 2755aoffset2 += lda ; 2756aoffset3 += lda ; 2757aoffset4 += lda ; 2758aoffset5 += lda ; 2759aoffset6 += lda ; 2760aoffset7 += lda ; 2761aoffset8 += lda ; 2762vecOffset += 256 ; 2763i -- ; 2764 }while (i > 0 ); 2765 } 2766j -- ; 2767 }while (j > 0 ); 2768 } 2769 2770if (rows & 4 ) { 2771aoffset1 = aoffset ; 2772aoffset2 = aoffset1 + lda ; 2773aoffset3 = aoffset2 + lda ; 2774aoffset4 = aoffset3 + lda ; 2775aoffset += 4 * lda ; 2776i = (cols >>2 ); 2777if (i > 0 ) { 2778do { 2779c1 [1 ]= vec_xl (0 , (const vector signed char * )aoffset1 -> qs ); 2780c2 [1 ]= vec_xl (0 , (const vector signed char * )aoffset2 -> qs ); 2781c3 [1 ]= vec_xl (0 , (const vector signed char * )aoffset3 -> qs ); 2782c4 [1 ]= vec_xl (0 , (const vector signed char * )aoffset4 -> qs ); 2783 2784process_q4_elements (c1 ,& comparray [0 ]); 2785process_q4_elements (c2 ,& comparray [1 ]); 2786process_q4_elements (c3 ,& comparray [2 ]); 2787process_q4_elements (c4 ,& comparray [3 ]); 2788vector_permute_store < int8_t ,vector signed char > (c1 [0 ],c2 [0 ],c3 [0 ],c4 [0 ],vecOffset , false); 2789vector_permute_store < int8_t ,vector signed char > (c1 [1 ],c2 [1 ],c3 [1 ],c4 [1 ],vecOffset + 64 , false); 2790aoffset1 += lda ; 2791aoffset2 += lda ; 2792aoffset3 += lda ; 2793aoffset4 += lda ; 2794vecOffset += 128 ; 2795i -- ; 2796 }while (i > 0 ); 2797 } 2798 } 2799 2800if (rows & 3 ) { 2801aoffset1 = aoffset ; 2802aoffset2 = aoffset1 + lda ; 2803aoffset3 = aoffset2 + lda ; 2804i = (cols >>2 ); 2805if (i > 0 ) { 2806do { 2807switch (rows ) { 2808case 3 :c3 [1 ]= vec_xl (0 , (const vector signed char * )aoffset3 -> qs ); 2809case 2 :c2 [1 ]= vec_xl (0 , (const vector signed char * )aoffset2 -> qs ); 2810case 1 :c1 [1 ]= vec_xl (0 , (const vector signed char * )aoffset1 -> qs ); 2811break ; 2812 } 2813process_q4_elements (c1 ,& comparray [0 ]); 2814process_q4_elements (c2 ,& comparray [1 ]); 2815process_q4_elements (c3 ,& comparray [2 ]); 2816process_q4_elements (c4 ,& comparray [3 ]); 2817vector_permute_store < int8_t ,vector signed char > (c1 [0 ],c2 [0 ],c3 [0 ],c4 [0 ],vecOffset , false); 2818vector_permute_store < int8_t ,vector signed char > (c1 [1 ],c2 [1 ],c3 [1 ],c4 [1 ],vecOffset + 64 , false); 2819aoffset1 += lda ; 2820aoffset2 += lda ; 2821aoffset3 += lda ; 2822vecOffset += 128 ; 2823i -- ; 2824 }while (i > 0 ); 2825 } 2826 } 2827 } 2828 2829template < typename VA ,typename VB > 2830void packNormal (const block_q8_0 * a ,int64_t lda ,int rows ,int cols ,VA * vec ,bool flip ) { 2831int64_t i ,j ; 2832block_q8_0 * aoffset = NULL ; 2833VA * vecOffset = NULL ; 2834block_q8_0 * aoffsets [8 ]; 2835__vector_pair arr [8 ]; 2836VB c [8 ][2 ]= {0 }; 2837VB c1 [8 ]= {0 };VB c2 [8 ]= {0 }; 2838aoffset = const_cast < block_q8_0 *> (a ); 2839vecOffset = vec ; 2840j = (rows >>3 ); 2841if (j > 0 ) { 2842do { 2843aoffsets [0 ]= aoffset ; 2844for (int it = 1 ;it < 8 ;it ++ ) 2845aoffsets [it ]= aoffsets [it - 1 ]+ lda ; 2846aoffset += 8 * lda ; 2847 2848i = (cols >>3 ); 2849if (i > 0 ) { 2850do { 2851for (int it = 0 ;it < 8 ;it ++ ) { 2852arr [it ]= __builtin_vsx_lxvp (0 , (__vector_pair * )aoffsets [it ]-> qs ); 2853__builtin_vsx_disassemble_pair (c [it ],& arr [it ]); 2854c1 [it ]= c [it ][0 ]; 2855c2 [it ]= c [it ][1 ]; 2856 } 2857vector_permute_store < VA ,VB > (c1 [0 ],c1 [1 ],c1 [2 ],c1 [3 ],vecOffset ,flip ); 2858vector_permute_store < VA ,VB > (c2 [0 ],c2 [1 ],c2 [2 ],c2 [3 ],vecOffset + 64 ,flip ); 2859vector_permute_store < VA ,VB > (c1 [4 ],c1 [5 ],c1 [6 ],c1 [7 ],vecOffset + 128 ,flip ); 2860vector_permute_store < VA ,VB > (c2 [4 ],c2 [5 ],c2 [6 ],c2 [7 ],vecOffset + 192 ,flip ); 2861for (int it = 0 ;it < 8 ;it ++ ) 2862aoffsets [it ]+= lda ; 2863vecOffset += 256 ; 2864i -- ; 2865 }while (i > 0 ); 2866 } 2867j -- ; 2868 }while (j > 0 ); 2869 } 2870if (rows & 4 ) { 2871aoffsets [0 ]= aoffset ; 2872for (int it = 1 ;it < 4 ;it ++ ) 2873aoffsets [it ]= aoffsets [it - 1 ]+ lda ; 2874aoffset += 4 * lda ; 2875i = (cols >>3 ); 2876if (i > 0 ) { 2877do { 2878for (int it = 0 ;it < 4 ;it ++ ) { 2879arr [it ]= __builtin_vsx_lxvp (0 , (__vector_pair * )aoffsets [it ]-> qs ); 2880__builtin_vsx_disassemble_pair (c [it ],& arr [it ]); 2881c1 [it ]= c [it ][0 ]; 2882c2 [it ]= c [it ][1 ]; 2883 } 2884vector_permute_store < VA ,VB > (c1 [0 ],c1 [1 ],c1 [2 ],c1 [3 ],vecOffset ,flip ); 2885vector_permute_store < VA ,VB > (c2 [0 ],c2 [1 ],c2 [2 ],c2 [3 ],vecOffset + 64 ,flip ); 2886for (int it = 0 ;it < 4 ;it ++ ) { 2887aoffsets [it ]+= lda ; 2888 } 2889vecOffset += 128 ; 2890i -- ; 2891 }while (i > 0 ); 2892 } 2893 } 2894 2895if (rows & 3 ) { 2896aoffsets [0 ]= aoffset ; 2897for (int it = 1 ;it < 3 ;it ++ ) 2898aoffsets [it ]= aoffsets [it - 1 ]+ lda ; 2899i = (cols >>3 ); 2900if (i > 0 ) { 2901do { 2902switch (rows ) { 2903case 3 :arr [2 ]= __builtin_vsx_lxvp (0 , (__vector_pair * )aoffsets [2 ]-> qs ); 2904__builtin_vsx_disassemble_pair (c [2 ],& arr [2 ]); 2905c1 [2 ]= c [2 ][0 ];c2 [2 ]= c [2 ][1 ]; 2906case 2 :arr [1 ]= __builtin_vsx_lxvp (0 , (__vector_pair * )aoffsets [1 ]-> qs ); 2907__builtin_vsx_disassemble_pair (c [1 ],& arr [1 ]); 2908c1 [1 ]= c [1 ][0 ];c2 [1 ]= c [1 ][1 ]; 2909case 1 :arr [0 ]= __builtin_vsx_lxvp (0 , (__vector_pair * )aoffsets [0 ]-> qs ); 2910__builtin_vsx_disassemble_pair (c [0 ],& arr [0 ]); 2911c1 [0 ]= c [0 ][0 ];c2 [0 ]= c [0 ][1 ]; 2912break ; 2913 } 2914vector_permute_store < VA ,VB > (c1 [0 ],c1 [1 ],c1 [2 ],c1 [3 ],vecOffset ,flip ); 2915vector_permute_store < VA ,VB > (c2 [0 ],c2 [1 ],c2 [2 ],c2 [3 ],vecOffset + 64 ,flip ); 2916for (int it = 0 ;it < 3 ;it ++ ) 2917aoffsets [it ]+= lda ; 2918vecOffset += 128 ; 2919i -- ; 2920 }while (i > 0 ); 2921 } 2922 } 2923 } 2924 2925void mnpack (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 2926int m_rem = MIN (m - m0 ,16 ); 2927int n_rem = MIN (n - n0 ,16 ); 2928 2929int mc = 0 ,nc = 0 ; 2930 2931if (m_rem >=8 && n_rem >=8 ) { 2932mc = 8 ; 2933nc = 8 ; 2934gemm < 8 ,8 > (m0 ,m ,n0 ,n ); 2935 }else if (m_rem >=4 && n_rem >=8 ) { 2936mc = 4 ; 2937nc = 8 ; 2938gemm < 4 ,8 > (m0 ,m ,n0 ,n ); 2939 }else if (m_rem >=8 && n_rem >=4 ) { 2940mc = 8 ; 2941nc = 4 ; 2942gemm < 8 ,4 > (m0 ,m ,n0 ,n ); 2943 }else if (m_rem >=4 && n_rem >=4 ) { 2944mc = 4 ; 2945nc = 4 ; 2946gemm_small (m0 ,m ,n0 ,n ,mc ,nc ); 2947 }else { 2948mc = (m_rem >=4 ) ?4 :m_rem ; 2949nc = (n_rem >=4 ) ?4 :n_rem ; 2950if (mc == 0 || nc == 0 ) 2951return ; 2952gemm_small (m0 ,m ,n0 ,n ,mc ,nc ); 2953 } 2954 2955int64_t mp = m0 + ((m - m0 ) /mc )* mc ; 2956int64_t np = n0 + ((n - n0 ) /nc )* nc ; 2957mnpack (mp ,m ,n0 ,np ); 2958mnpack (m0 ,m ,np ,n ); 2959 } 2960 2961 2962void KERNEL_4x8 (int64_t ii ,int64_t jj ) { 2963vec_t vec_A [8 ],vec_B [16 ]= {0 }; 2964acc_t acc_0 ,acc_1 ; 2965 std::array < int ,4 > comparray {}; 2966vector float fin_res [8 ]= {0 }; 2967vector float vs [8 ]= {0 }; 2968bool isAblock_q4 = std::is_same_v < TA ,block_q4_0 > ; 2969for (int l = 0 ;l < k ;l ++ ) { 2970__builtin_mma_xxsetaccz (& acc_0 ); 2971__builtin_mma_xxsetaccz (& acc_1 ); 2972if (std::is_same_v < TA ,block_q4_0 > ) { 2973packNormalInt4 < 4 > ((A + (ii * lda )+ l ),lda ,4 ,4 , (int8_t * )vec_A ,comparray ); 2974 }else { 2975packNormal < int8_t ,vector signed char > ((const block_q8_0 * )(A + (ii * lda )+ l ),lda ,4 ,8 , (int8_t * )vec_A , false); 2976 } 2977packNormal < uint8_t ,vector unsigned char > ((B + (jj * ldb )+ l ),ldb ,8 ,8 , (uint8_t * )vec_B , true); 2978for (int x = 0 ;x < 8 ;x ++ ) { 2979__builtin_mma_xvi8ger4pp (& acc_0 ,vec_A [x ],vec_B [x ]); 2980__builtin_mma_xvi8ger4pp (& acc_1 ,vec_A [x ],vec_B [x + 8 ]); 2981 } 2982for (int I = 0 ;I < 4 ;I ++ ) { 2983for (int J = 0 ;J < 4 ;J ++ ) { 2984* ((float * )& vs [I ]+ J )= (unhalf ((A + ((ii + I )* lda )+ l )-> d )* unhalf ((B + ((jj + J )* ldb )+ l )-> d )); 2985* ((float * )& vs [I + 4 ]+ J )= (unhalf ((A + ((ii + I )* lda )+ l )-> d )* unhalf ((B + ((jj + J + 4 )* ldb )+ l )-> d )); 2986 } 2987 } 2988if (!isAblock_q4 ) { 2989auto aoffset = A + (ii * lda )+ l ; 2990for (int i = 0 ;i < 4 ;i ++ ) { 2991comparray [i ]= 0 ; 2992int ca = 0 ; 2993auto * at = aoffset -> qs ; 2994for (int j = 0 ;j < 32 ;j ++ ) 2995ca += (int )* at ++ ; 2996comparray [i ]= ca ; 2997aoffset += lda ; 2998 } 2999 } 3000compute (& acc_0 ,0 ,0 ,comparray ,vs ,fin_res ); 3001compute (& acc_1 ,0 ,4 ,comparray ,vs ,fin_res ); 3002 } 3003save_res (ii ,jj ,0 ,fin_res ); 3004save_res (ii ,jj + 4 ,4 ,fin_res ); 3005 } 3006 3007void KERNEL_8x4 (int64_t ii ,int64_t jj ) { 3008vec_t vec_A [16 ],vec_B [8 ]= {0 }; 3009acc_t acc_0 ,acc_1 ; 3010 std::array < int ,8 > comparray {}; 3011vector float fin_res [8 ]= {0 }; 3012vector float vs [8 ]= {0 }; 3013bool isAblock_q4 = std::is_same_v < TA ,block_q4_0 > ; 3014for (int l = 0 ;l < k ;l ++ ) { 3015__builtin_mma_xxsetaccz (& acc_0 ); 3016__builtin_mma_xxsetaccz (& acc_1 ); 3017if (std::is_same_v < TA ,block_q4_0 > ) { 3018packNormalInt4 < 8 > ((A + (ii * lda )+ l ),lda ,8 ,4 , (int8_t * )vec_A ,comparray ); 3019 }else { 3020packNormal < int8_t ,vector signed char > ((const block_q8_0 * )(A + (ii * lda )+ l ),lda ,8 ,8 , (int8_t * )vec_A , false); 3021 } 3022packNormal < uint8_t ,vector unsigned char > ((B + (jj * ldb )+ l ),ldb ,4 ,8 , (uint8_t * )vec_B , true); 3023for (int x = 0 ;x < 8 ;x ++ ) { 3024__builtin_mma_xvi8ger4pp (& acc_0 ,vec_A [x ],vec_B [x ]); 3025__builtin_mma_xvi8ger4pp (& acc_1 ,vec_A [x + 8 ],vec_B [x ]); 3026 } 3027for (int I = 0 ;I < 8 ;I ++ ) { 3028for (int J = 0 ;J < 4 ;J ++ ) { 3029* ((float * )& vs [I ]+ J )= (unhalf ((A + ((ii + I )* lda )+ l )-> d )* unhalf ((B + ((jj + J )* ldb )+ l )-> d )); 3030 } 3031 } 3032if (!isAblock_q4 ) { 3033auto aoffset = A + (ii * lda )+ l ; 3034for (int i = 0 ;i < 8 ;i ++ ) { 3035comparray [i ]= 0 ; 3036int ca = 0 ; 3037auto * at = aoffset -> qs ; 3038for (int j = 0 ;j < 32 ;j ++ ) 3039ca += (int )* at ++ ; 3040comparray [i ]= ca ; 3041aoffset += lda ; 3042 } 3043 } 3044compute (& acc_0 ,0 ,0 ,comparray ,vs ,fin_res ); 3045compute (& acc_1 ,4 ,4 ,comparray ,vs ,fin_res ); 3046 } 3047save_res (ii ,jj ,0 ,fin_res ); 3048save_res (ii + 4 ,jj ,4 ,fin_res ); 3049 } 3050 3051void KERNEL_8x8 (int64_t ii ,int64_t jj ) { 3052vec_t vec_A [16 ],vec_B [16 ]= {0 }; 3053acc_t acc_0 ,acc_1 ,acc_2 ,acc_3 ; 3054acc_t acc_4 ,acc_5 ,acc_6 ,acc_7 ; 3055 std::array < int ,8 > comparray {}; 3056vector float fin_res [16 ]= {0 }; 3057vector float vs [16 ]= {0 }; 3058bool isAblock_q4 = std::is_same_v < TA ,block_q4_0 > ; 3059for (int l = 0 ;l < k ;l ++ ) { 3060__builtin_mma_xxsetaccz (& acc_0 ); 3061__builtin_mma_xxsetaccz (& acc_1 ); 3062__builtin_mma_xxsetaccz (& acc_2 ); 3063__builtin_mma_xxsetaccz (& acc_3 ); 3064if (std::is_same_v < TA ,block_q4_0 > ) { 3065packNormalInt4 < 8 > ((A + (ii * lda )+ l ),lda ,8 ,4 , (int8_t * )vec_A ,comparray ); 3066 }else { 3067packNormal < int8_t ,vector signed char > ((const block_q8_0 * )(A + (ii * lda )+ l ),lda ,8 ,8 , (int8_t * )vec_A , false); 3068 } 3069packNormal < uint8_t ,vector unsigned char > ((B + (jj * ldb )+ l ),ldb ,8 ,8 , (uint8_t * )vec_B , true); 3070for (int x = 0 ;x < 8 ;x ++ ) { 3071__builtin_mma_xvi8ger4pp (& acc_0 ,vec_A [x ],vec_B [x ]); 3072__builtin_mma_xvi8ger4pp (& acc_1 ,vec_A [x + 8 ],vec_B [x ]); 3073__builtin_mma_xvi8ger4pp (& acc_2 ,vec_A [x ],vec_B [x + 8 ]); 3074__builtin_mma_xvi8ger4pp (& acc_3 ,vec_A [x + 8 ],vec_B [x + 8 ]); 3075 } 3076for (int I = 0 ;I < 8 ;I ++ ) { 3077for (int J = 0 ;J < 4 ;J ++ ) { 3078* ((float * )& vs [I ]+ J )= (unhalf ((A + ((ii + I )* lda )+ l )-> d )* unhalf ((B + ((jj + J )* ldb )+ l )-> d )); 3079* ((float * )& vs [I + 8 ]+ J )= (unhalf ((A + ((ii + I )* lda )+ l )-> d )* unhalf ((B + ((jj + J + 4 )* ldb )+ l )-> d )); 3080 } 3081 } 3082if (!isAblock_q4 ) { 3083auto aoffset = A + (ii * lda )+ l ; 3084for (int i = 0 ;i < 8 ;i ++ ) { 3085comparray [i ]= 0 ; 3086int ca = 0 ; 3087auto * at = aoffset -> qs ; 3088for (int j = 0 ;j < 32 ;j ++ ) 3089ca += (int )* at ++ ; 3090comparray [i ]= ca ; 3091aoffset += lda ; 3092 } 3093 } 3094compute (& acc_0 ,0 ,0 ,comparray ,vs ,fin_res ); 3095compute (& acc_1 ,4 ,4 ,comparray ,vs ,fin_res ); 3096compute (& acc_2 ,0 ,8 ,comparray ,vs ,fin_res ); 3097compute (& acc_3 ,4 ,12 ,comparray ,vs ,fin_res ); 3098 } 3099save_res (ii ,jj ,0 ,fin_res ); 3100save_res (ii + 4 ,jj ,4 ,fin_res ); 3101save_res (ii ,jj + 4 ,8 ,fin_res ); 3102save_res (ii + 4 ,jj + 4 ,12 ,fin_res ); 3103 } 3104 3105void KERNEL_Q0 (int64_t ii ,int64_t jj ,int64_t mc ,int64_t nc ,int64_t kc ,int64_t l ,vec_t * vec_A ,vec_t * vec_B ) { 3106acc_t acc [8 ]; 3107for (int i = 0 ;i < mc ;i += 16 ) { 3108for (int j = 0 ;j < nc ;j += 8 ) { 3109int A0_base = (i /16 )* (2 * 32 * kc ); 3110int B0_base = (j /8 )* (32 * kc ); 3111for (int x = 0 ;x < 8 ;x ++ ) { 3112__builtin_mma_xxsetaccz (& acc [x ]); 3113 } 3114for (int64_t kk = 0 ;kk < kc ;kk ++ ) { 3115int A0_block_idx = A0_base + kk * 32 ; 3116int B0_block_idx = B0_base + kk * 32 ; 3117int A1_block_idx = A0_block_idx + 32 * kc ; 3118int B1_block_idx = B0_block_idx + 32 * kc ; 3119vec_t * A0_block = & vec_A [A0_block_idx ]; 3120vec_t * B0_block = & vec_B [B0_block_idx ]; 3121vec_t * A1_block = & vec_A [A1_block_idx ]; 3122for (int it = 0 ;it < 4 ;it ++ ) { 3123for (int x = 0 ;x < 4 ;x ++ ) { 3124__builtin_mma_xvf16ger2pp (& acc [0 ],A0_block [8 * it + x ],B0_block [8 * it + x ]); 3125__builtin_mma_xvf16ger2pp (& acc [1 ],A0_block [8 * it + x ],B0_block [8 * it + x + 4 ]); 3126__builtin_mma_xvf16ger2pp (& acc [2 ],A0_block [8 * it + x + 4 ],B0_block [8 * it + x ]); 3127__builtin_mma_xvf16ger2pp (& acc [3 ],A0_block [8 * it + x + 4 ],B0_block [8 * it + x + 4 ]); 3128__builtin_mma_xvf16ger2pp (& acc [4 ],A1_block [8 * it + x ],B0_block [8 * it + x ]); 3129__builtin_mma_xvf16ger2pp (& acc [5 ],A1_block [8 * it + x ],B0_block [8 * it + x + 4 ]); 3130__builtin_mma_xvf16ger2pp (& acc [6 ],A1_block [8 * it + x + 4 ],B0_block [8 * it + x ]); 3131__builtin_mma_xvf16ger2pp (& acc [7 ],A1_block [8 * it + x + 4 ],B0_block [8 * it + x + 4 ]); 3132 } 3133 } 3134 } 3135if (l == 0 ) { 3136save_acc (& acc [0 ],ii + i ,jj + j ); 3137save_acc (& acc [1 ],ii + i ,jj + j + 4 ); 3138save_acc (& acc [2 ],ii + i + 4 ,jj + j ); 3139save_acc (& acc [3 ],ii + i + 4 ,jj + j + 4 ); 3140save_acc (& acc [4 ],ii + i + 8 ,jj + j ); 3141save_acc (& acc [5 ],ii + i + 8 ,jj + j + 4 ); 3142save_acc (& acc [6 ],ii + i + 12 ,jj + j ); 3143save_acc (& acc [7 ],ii + i + 12 ,jj + j + 4 ); 3144 }else { 3145add_save_acc (& acc [0 ],ii + i ,jj + j ); 3146add_save_acc (& acc [1 ],ii + i ,jj + j + 4 ); 3147add_save_acc (& acc [2 ],ii + i + 4 ,jj + j ); 3148add_save_acc (& acc [3 ],ii + i + 4 ,jj + j + 4 ); 3149add_save_acc (& acc [4 ],ii + i + 8 ,jj + j ); 3150add_save_acc (& acc [5 ],ii + i + 8 ,jj + j + 4 ); 3151add_save_acc (& acc [6 ],ii + i + 12 ,jj + j ); 3152add_save_acc (& acc [7 ],ii + i + 12 ,jj + j + 4 ); 3153 } 3154 } 3155 } 3156 } 3157 3158void matmul_tiled (int64_t m ,int64_t n ,int64_t mc ,int64_t nc ,int64_t kc ) { 3159vec_t A_pack [mc * kc * 4 ]; 3160vec_t B_pack [nc * kc * 4 ]; 3161constexpr bool is_Ablock_q4 = std::is_same_v < TA ,block_q4_0 > ; 3162int64_t ytiles = m /mc ; 3163int64_t xtiles = n /nc ; 3164int64_t tiles = xtiles * ytiles ; 3165int64_t duty = (tiles + nth - 1 ) /nth ; 3166int64_t start = duty * ith ; 3167int64_t end = start + duty ; 3168if (end > tiles ) { 3169end = tiles ; 3170 } 3171for (int64_t job = start ;job < end ;++ job ) { 3172int64_t ii = (job /xtiles )* mc ; 3173int64_t jj = (job %xtiles )* nc ; 3174for (int64_t kk = 0 ;kk < k ;kk += kc ) { 3175int64_t k_cur = MIN (kc ,k - kk ); 3176if constexpr (is_Ablock_q4 ) { 3177packNormal_q4_fp16 (A + ii * lda + kk ,lda ,mc ,k_cur , (uint8_t * )A_pack ); 3178 }else { 3179packNormal_q8_fp16 (A + ii * lda + kk ,lda ,mc ,k_cur , (uint8_t * )A_pack ); 3180 } 3181packNormal_q8_fp16 (B + jj * ldb + kk ,ldb ,nc ,k_cur , (uint8_t * )B_pack ); 3182KERNEL_Q0 (ii ,jj ,mc ,nc ,k_cur ,kk ,A_pack ,B_pack ); 3183 } 3184 } 3185 } 3186 3187void gemm_small (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ,int RM ,int RN ) { 3188int64_t ytiles = (m - m0 ) /RM ; 3189int64_t xtiles = (n - n0 ) /RN ; 3190int64_t tiles = xtiles * ytiles ; 3191int64_t duty = (tiles + nth - 1 ) /nth ; 3192int64_t start = duty * ith ; 3193int64_t end = start + duty ; 3194vec_t vec_A [8 ]= {0 },vec_B [8 ]= {0 }; 3195vector signed int vec_C [4 ]; 3196acc_t acc_0 ; 3197bool isAblock_q4 = std::is_same_v < TA ,block_q4_0 > ; 3198 3199if (end > tiles ) 3200end = tiles ; 3201for (int64_t job = start ;job < end ;++ job ) { 3202int64_t ii = m0 + job /xtiles * RM ; 3203int64_t jj = n0 + job %xtiles * RN ; 3204 std::array < int ,4 > comparray {}; 3205vector float res [4 ]= {0 }; 3206vector float fin_res [4 ]= {0 }; 3207vector float vs [4 ]= {0 }; 3208vector float CA [4 ]= {0 }; 3209__builtin_prefetch ((A + (ii * lda )+ 0 )-> qs ,0 ,1 );// prefetch first value 3210__builtin_prefetch ((B + (jj * ldb )+ 0 )-> qs ,0 ,1 );// prefetch first value 3211for (int l = 0 ;l < k ;l ++ ) { 3212__builtin_prefetch ((A + (ii * lda )+ (l + 1 ))-> qs ,0 ,1 );// prefetch one loop ahead 3213__builtin_prefetch ((B + (jj * ldb )+ (l + 1 ))-> qs ,0 ,1 );// prefetch one loop ahead 3214__builtin_mma_xxsetaccz (& acc_0 ); 3215if (isAblock_q4 ) { 3216packNormalInt4 < 4 > ((A + (ii * lda )+ l ),lda ,RM ,4 , (int8_t * )vec_A ,comparray ); 3217 }else { 3218packNormal < int8_t ,vector signed char > ((const block_q8_0 * )(A + (ii * lda )+ l ),lda ,RM ,8 , (int8_t * )vec_A , false); 3219 } 3220packNormal < uint8_t ,vector unsigned char > ((B + (jj * ldb )+ l ),ldb ,RN ,8 , (uint8_t * )vec_B , true); 3221for (int x = 0 ;x < 8 ;x += 4 ) { 3222__builtin_mma_xvi8ger4pp (& acc_0 ,vec_A [x ],vec_B [x ]); 3223__builtin_mma_xvi8ger4pp (& acc_0 ,vec_A [x + 1 ],vec_B [x + 1 ]); 3224__builtin_mma_xvi8ger4pp (& acc_0 ,vec_A [x + 2 ],vec_B [x + 2 ]); 3225__builtin_mma_xvi8ger4pp (& acc_0 ,vec_A [x + 3 ],vec_B [x + 3 ]); 3226 } 3227for (int I = 0 ;I < RM ;I ++ ) { 3228for (int J = 0 ;J < RN ;J ++ ) { 3229* ((float * )& vs [I ]+ J )= (unhalf ((A + ((ii + I )* lda )+ l )-> d )* unhalf ((B + ((jj + J )* ldb )+ l )-> d )); 3230 } 3231 } 3232__builtin_mma_disassemble_acc (vec_C ,& acc_0 ); 3233if (!isAblock_q4 ) { 3234auto aoffset = A + (ii * lda )+ l ; 3235for (int i = 0 ;i < RM ;i ++ ) { 3236comparray [i ]= 0 ; 3237int ca = 0 ; 3238auto * at = aoffset -> qs ; 3239for (int j = 0 ;j < 32 ;j ++ ) 3240ca += (int )* at ++ ; 3241comparray [i ]= ca ; 3242aoffset += lda ; 3243 } 3244 } 3245for (int i = 0 ;i < RM ;i ++ ) { 3246CA [i ]= vec_splats ((float )(((double )comparray [i ])* -128.0 )); 3247res [i ]= vec_add (vec_ctf (vec_C [i ],0 ),CA [i ]); 3248fin_res [i ]= vec_madd (res [i ],vs [i ],fin_res [i ]); 3249 } 3250 } 3251save_res (ii ,jj ,0 ,fin_res ,RM ,RN ); 3252 } 3253 } 3254 3255template < int RM ,int RN > 3256inline void kernel (int64_t ii ,int64_t jj ) { 3257if constexpr (RM == 4 && RN == 8 ) { 3258KERNEL_4x8 (ii ,jj ); 3259 }else if constexpr (RM == 8 && RN == 4 ) { 3260KERNEL_8x4 (ii ,jj ); 3261 }else if constexpr (RM == 8 && RN == 8 ) { 3262KERNEL_8x8 (ii ,jj ); 3263 }else { 3264assert (false&& "RN/RM values not supported" ); 3265 } 3266 } 3267 3268template < int RM ,int RN > 3269NOINLINE void gemm (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 3270int64_t ytiles = (m - m0 ) /RM ; 3271int64_t xtiles = (n - n0 ) /RN ; 3272int64_t tiles = xtiles * ytiles ; 3273int64_t duty = (tiles + nth - 1 ) /nth ; 3274int64_t start = duty * ith ; 3275int64_t end = start + duty ; 3276if (end > tiles ) 3277end = tiles ; 3278for (int64_t job = start ;job < end ;++ job ) { 3279int64_t ii = m0 + job /xtiles * RM ; 3280int64_t jj = n0 + job %xtiles * RN ; 3281kernel < RM ,RN > (ii ,jj ); 3282 } 3283 } 3284const TA * const A ; 3285const block_q8_0 * const B ; 3286float * C ; 3287const int64_t k ; 3288int64_t kc ; 3289const int64_t lda ; 3290const int64_t ldb ; 3291const int64_t ldc ; 3292const int ith ; 3293const int nth ; 3294}; 3295 3296class tinyBLAS_PPC { 3297public : 3298tinyBLAS_PPC (int64_t k , 3299const float * A ,int64_t lda , 3300const float * B ,int64_t ldb , 3301float * C ,int64_t ldc , 3302int ith ,int nth ) 3303 :A (A ),B (B ),C (C ),k (k ),lda (lda ),ldb (ldb ),ldc (ldc ),ith (ith ),nth (nth ) { 3304 } 3305 3306void matmul (int64_t m ,int64_t n ) { 3307int64_t mc = 256 ; 3308int64_t nc = 256 ; 3309int64_t kc = 256 ; 3310#if defined(_AIX )|| defined(__BIG_ENDIAN__ ) 3311mc = 128 ; 3312nc = 128 ; 3313kc = 128 ; 3314#endif 3315if (m %mc == 0 && n %nc == 0 && k %kc == 0 ) { 3316matmul_tiled (m ,n ,mc ,nc ,kc ); 3317 }else { 3318mnpack (0 ,m ,0 ,n ); 3319 } 3320 } 3321 3322private : 3323 3324 __attribute__((always_inline )) 3325inline void save_acc (acc_t * ACC ,int64_t ii ,int64_t jj ) { 3326vec_t vec_C [4 ]; 3327__builtin_mma_disassemble_acc (vec_C ,ACC ); 3328for (int I = 0 ;I < 4 ;I ++ ) { 3329for (int J = 0 ;J < 4 ;J ++ ) { 3330* ((float * )(C + ii + ((jj + J )* ldc )+ I ))= * ((float * )& vec_C [I ]+ J ); 3331 } 3332 } 3333 } 3334 3335 __attribute__((always_inline )) 3336inline void add_save_acc (acc_t * ACC ,int64_t ii ,int64_t jj ) { 3337vec_t vec_C [4 ]; 3338__builtin_mma_disassemble_acc (vec_C ,ACC ); 3339for (int I = 0 ;I < 4 ;I ++ ) { 3340for (int J = 0 ;J < 4 ;J ++ ) { 3341float * c_ptr = (float * )(C + ii + ((jj + J )* ldc )+ I ); 3342* c_ptr += * ((float * )& vec_C [I ]+ J ); 3343 } 3344 } 3345 } 3346 3347inline void vector_permute_store_4 (vector float * src ,float * vecOffset ) { 3348vector float t1 ,t2 ,t3 ,t4 ,t5 ,t6 ,t7 ,t8 ; 3349t1 = vec_mergeh (src [0 ],src [1 ]); 3350t2 = vec_mergeh (src [2 ],src [3 ]); 3351t3 = vec_mergel (src [0 ],src [1 ]); 3352t4 = vec_mergel (src [2 ],src [3 ]); 3353 3354t5 = vec_xxpermdi (t1 ,t2 ,0 ); 3355t6 = vec_xxpermdi (t1 ,t2 ,3 ); 3356t7 = vec_xxpermdi (t3 ,t4 ,0 ); 3357t8 = vec_xxpermdi (t3 ,t4 ,3 ); 3358 3359vec_xst (t5 ,0 ,vecOffset ); 3360vec_xst (t6 ,0 ,vecOffset + 4 ); 3361vec_xst (t7 ,0 ,vecOffset + 8 ); 3362vec_xst (t8 ,0 ,vecOffset + 12 ); 3363 } 3364 3365inline void vector_permute_store_8 (vector float * src ,float * vecOffset ) { 3366vector float t1 ,t2 ,t3 ,t4 ,t5 ,t6 ,t7 ,t8 ; 3367t1 = vec_mergeh (src [0 ],src [1 ]); 3368t2 = vec_mergeh (src [2 ],src [3 ]); 3369t3 = vec_mergeh (src [4 ],src [5 ]); 3370t4 = vec_mergeh (src [6 ],src [7 ]); 3371 3372t5 = vec_xxpermdi (t1 ,t2 ,0 ); 3373t6 = vec_xxpermdi (t3 ,t4 ,0 ); 3374t7 = vec_xxpermdi (t1 ,t2 ,3 ); 3375t8 = vec_xxpermdi (t3 ,t4 ,3 ); 3376 3377vec_xst (t5 ,0 ,vecOffset ); 3378vec_xst (t6 ,0 ,vecOffset + 4 ); 3379vec_xst (t7 ,0 ,vecOffset + 8 ); 3380vec_xst (t8 ,0 ,vecOffset + 12 ); 3381 3382t1 = vec_mergel (src [0 ],src [1 ]); 3383t2 = vec_mergel (src [2 ],src [3 ]); 3384t3 = vec_mergel (src [4 ],src [5 ]); 3385t4 = vec_mergel (src [6 ],src [7 ]); 3386 3387t5 = vec_xxpermdi (t1 ,t2 ,0 ); 3388t6 = vec_xxpermdi (t3 ,t4 ,0 ); 3389t7 = vec_xxpermdi (t1 ,t2 ,3 ); 3390t8 = vec_xxpermdi (t3 ,t4 ,3 ); 3391 3392vec_xst (t5 ,0 ,vecOffset + 16 ); 3393vec_xst (t6 ,0 ,vecOffset + 20 ); 3394vec_xst (t7 ,0 ,vecOffset + 24 ); 3395vec_xst (t8 ,0 ,vecOffset + 28 ); 3396 } 3397 3398void packTranspose (const float * a ,int64_t lda ,int rows ,int cols ,float * vec ) { 3399int64_t i ,j ; 3400float * aoffsets [8 ]; 3401float * aoffset = NULL ,* boffset = NULL ; 3402__vector_pair arr [8 ]; 3403vector float c [8 ][2 ]= {0 }; 3404vector float c1 [8 ]= {0 }; 3405vector float c2 [8 ]= {0 }; 3406aoffset = const_cast < float *> (a ); 3407boffset = vec ; 3408j = (rows >>3 ); 3409if (j > 0 ) { 3410do { 3411aoffsets [0 ]= aoffset ; 3412for (int it = 1 ;it < 8 ;it ++ ) 3413aoffsets [it ]= aoffsets [it - 1 ]+ lda ; 3414aoffset += 8 * lda ; 3415i = (cols >>3 ); 3416if (i > 0 ) { 3417do { 3418for (int it = 0 ;it < 8 ;it ++ ) { 3419arr [it ]= __builtin_vsx_lxvp (0 , (__vector_pair * )aoffsets [it ]); 3420__builtin_vsx_disassemble_pair (c [it ],& arr [it ]); 3421c1 [it ]= c [it ][0 ]; 3422c2 [it ]= c [it ][1 ]; 3423 } 3424 3425vector_permute_store_8 (c1 ,boffset ); 3426vector_permute_store_8 (c2 ,boffset + 32 ); 3427boffset += 64 ; 3428i -- ; 3429if (i > 0 ) { 3430for (int it = 0 ;it < 8 ;it ++ ) { 3431aoffsets [it ]= aoffsets [it ]+ 8 ; 3432 } 3433 } 3434 }while (i > 0 ); 3435 } 3436if (cols & 4 ) { 3437for (int it = 0 ;it < 8 ;it ++ ) 3438c1 [it ]= vec_xl (0 ,aoffsets [it ]); 3439vector_permute_store_8 (c1 ,boffset ); 3440 } 3441j -- ; 3442 }while (j > 0 ); 3443 } 3444 3445if (rows & 4 ) { 3446aoffsets [0 ]= aoffset ; 3447for (int it = 1 ;it < 4 ;it ++ ) 3448aoffsets [it ]= aoffsets [it - 1 ]+ lda ; 3449aoffset += 4 * lda ; 3450i = (cols >>3 ); 3451if (i > 0 ) { 3452do { 3453for (int it = 0 ;it < 4 ;it ++ ) { 3454arr [it ]= __builtin_vsx_lxvp (0 , (__vector_pair * )aoffsets [it ]); 3455__builtin_vsx_disassemble_pair (c [it ],& arr [it ]); 3456c1 [it ]= c [it ][0 ]; 3457c2 [it ]= c [it ][1 ]; 3458 } 3459vector_permute_store_4 (c1 ,boffset ); 3460vector_permute_store_4 (c2 ,boffset + 16 ); 3461for (int it = 0 ;it < 4 ;it ++ ) 3462aoffsets [it ]+= 8 * lda ; 3463boffset += 32 ; 3464i -- ; 3465 }while (i > 0 ); 3466 } 3467 3468if (cols & 4 ) { 3469for (int it = 0 ;it < 4 ;it ++ ) 3470c1 [it ]= vec_xl (0 ,aoffsets [it ]); 3471vector_permute_store_4 (c1 ,boffset ); 3472 } 3473 } 3474if (rows & 3 ) { 3475aoffsets [0 ]= aoffset ; 3476for (int it = 1 ;it < 3 ;it ++ ) 3477aoffsets [it ]= aoffsets [it - 1 ]+ lda ; 3478if (cols & 4 ) { 3479for (int it = 0 ;it < 3 ;it ++ ) 3480c1 [it ]= vec_xl (0 ,aoffsets [it ]); 3481vector_permute_store_4 (c1 ,boffset ); 3482 } 3483 } 3484 } 3485 3486void KERNEL_4x4 (int64_t ii ,int64_t jj ) { 3487vec_t vec_A [4 ],vec_B [4 ],vec_C [4 ]; 3488acc_t acc_0 ; 3489__builtin_mma_xxsetaccz (& acc_0 ); 3490for (int l = 0 ;l < k ;l += 4 ) { 3491packTranspose (A + (ii * lda )+ l ,lda ,4 ,4 , (float * )vec_A ); 3492packTranspose (B + (jj * ldb )+ l ,ldb ,4 ,4 , (float * )vec_B ); 3493__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [0 ],vec_B [0 ]); 3494__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [1 ],vec_B [1 ]); 3495__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [2 ],vec_B [2 ]); 3496__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [3 ],vec_B [3 ]); 3497 } 3498save_acc (& acc_0 ,ii ,jj ); 3499 } 3500 3501void KERNEL_4x8 (int64_t ii ,int64_t jj ) { 3502vec_t vec_A [4 ],vec_B [8 ],vec_C [4 ]; 3503acc_t acc_0 ,acc_1 ; 3504__builtin_mma_xxsetaccz (& acc_0 ); 3505__builtin_mma_xxsetaccz (& acc_1 ); 3506for (int64_t l = 0 ;l < k ;l += 4 ) { 3507packTranspose (A + (ii * lda )+ l ,lda ,4 ,4 , (float * )vec_A ); 3508packTranspose (B + (jj * ldb )+ l ,ldb ,8 ,4 , (float * )vec_B ); 3509__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [0 ], (vec_t )vec_B [0 ]); 3510__builtin_mma_xvf32gerpp (& acc_1 ,vec_A [0 ], (vec_t )vec_B [1 ]); 3511__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [1 ], (vec_t )vec_B [2 ]); 3512__builtin_mma_xvf32gerpp (& acc_1 ,vec_A [1 ], (vec_t )vec_B [3 ]); 3513__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [2 ], (vec_t )vec_B [4 ]); 3514__builtin_mma_xvf32gerpp (& acc_1 ,vec_A [2 ], (vec_t )vec_B [5 ]); 3515__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [3 ], (vec_t )vec_B [6 ]); 3516__builtin_mma_xvf32gerpp (& acc_1 ,vec_A [3 ], (vec_t )vec_B [7 ]); 3517 } 3518save_acc (& acc_0 ,ii ,jj ); 3519save_acc (& acc_1 ,ii ,jj + 4 ); 3520 } 3521 3522void KERNEL_8x4 (int64_t ii ,int64_t jj ) { 3523vec_t vec_A [8 ],vec_B [4 ],vec_C [4 ]; 3524acc_t acc_0 ,acc_1 ; 3525__builtin_mma_xxsetaccz (& acc_0 ); 3526__builtin_mma_xxsetaccz (& acc_1 ); 3527for (int64_t l = 0 ;l < k ;l += 4 ) { 3528packTranspose (A + (ii * lda )+ l ,lda ,8 ,4 , (float * )vec_A ); 3529packTranspose (B + (jj * ldb )+ l ,ldb ,4 ,4 , (float * )vec_B ); 3530__builtin_mma_xvf32gerpp (& acc_0 , (vec_t )vec_A [0 ],vec_B [0 ]); 3531__builtin_mma_xvf32gerpp (& acc_1 , (vec_t )vec_A [1 ],vec_B [0 ]); 3532__builtin_mma_xvf32gerpp (& acc_0 , (vec_t )vec_A [2 ],vec_B [1 ]); 3533__builtin_mma_xvf32gerpp (& acc_1 , (vec_t )vec_A [3 ],vec_B [1 ]); 3534__builtin_mma_xvf32gerpp (& acc_0 , (vec_t )vec_A [4 ],vec_B [2 ]); 3535__builtin_mma_xvf32gerpp (& acc_1 , (vec_t )vec_A [5 ],vec_B [2 ]); 3536__builtin_mma_xvf32gerpp (& acc_0 , (vec_t )vec_A [6 ],vec_B [3 ]); 3537__builtin_mma_xvf32gerpp (& acc_1 , (vec_t )vec_A [7 ],vec_B [3 ]); 3538 } 3539save_acc (& acc_0 ,ii ,jj ); 3540save_acc (& acc_1 ,ii + 4 ,jj ); 3541 } 3542 3543void KERNEL_8x8 (int64_t ii ,int64_t jj ) { 3544vec_t vec_A [16 ],vec_B [16 ],vec_C [4 ]; 3545acc_t acc_0 ,acc_1 ,acc_2 ,acc_3 ; 3546__builtin_mma_xxsetaccz (& acc_0 ); 3547__builtin_mma_xxsetaccz (& acc_1 ); 3548__builtin_mma_xxsetaccz (& acc_2 ); 3549__builtin_mma_xxsetaccz (& acc_3 ); 3550for (int l = 0 ;l < k ;l += 8 ) { 3551packTranspose (A + (ii * lda )+ l ,lda ,8 ,8 , (float * )vec_A ); 3552packTranspose (B + (jj * ldb )+ l ,ldb ,8 ,8 , (float * )vec_B ); 3553for (int x = 0 ;x < 16 ;x += 2 ) { 3554__builtin_mma_xvf32gerpp (& acc_0 , (vec_t )vec_A [x ],vec_B [x ]); 3555__builtin_mma_xvf32gerpp (& acc_1 , (vec_t )vec_A [x ],vec_B [x + 1 ]); 3556__builtin_mma_xvf32gerpp (& acc_2 , (vec_t )vec_A [x + 1 ],vec_B [x ]); 3557__builtin_mma_xvf32gerpp (& acc_3 , (vec_t )vec_A [x + 1 ],vec_B [x + 1 ]); 3558 } 3559 } 3560save_acc (& acc_0 ,ii ,jj ); 3561save_acc (& acc_1 ,ii ,jj + 4 ); 3562save_acc (& acc_2 ,ii + 4 ,jj ); 3563save_acc (& acc_3 ,ii + 4 ,jj + 4 ); 3564 } 3565 3566inline void MMA_16x8 (vec_t * vec_A0 ,vec_t * vec_A1 ,vec_t * vec_B ,acc_t * acc ) { 3567for (int x = 0 ;x < 16 ;x += 2 ) { 3568__builtin_mma_xvf32gerpp (& acc [0 ],vec_A0 [x + 0 ],vec_B [x ]); 3569__builtin_mma_xvf32gerpp (& acc [1 ],vec_A0 [x + 0 ],vec_B [x + 1 ]); 3570__builtin_mma_xvf32gerpp (& acc [2 ],vec_A0 [x + 1 ],vec_B [x ]); 3571__builtin_mma_xvf32gerpp (& acc [3 ],vec_A0 [x + 1 ],vec_B [x + 1 ]); 3572__builtin_mma_xvf32gerpp (& acc [4 ],vec_A1 [x + 0 ],vec_B [x ]); 3573__builtin_mma_xvf32gerpp (& acc [5 ],vec_A1 [x + 0 ],vec_B [x + 1 ]); 3574__builtin_mma_xvf32gerpp (& acc [6 ],vec_A1 [x + 1 ],vec_B [x ]); 3575__builtin_mma_xvf32gerpp (& acc [7 ],vec_A1 [x + 1 ],vec_B [x + 1 ]); 3576 } 3577 } 3578 3579void KERNEL (int64_t ii ,int64_t jj ,int64_t mc ,int64_t nc ,int64_t kc ,vec_t * vec_A ,vec_t * vec_B ,int64_t kk ) { 3580for (int64_t i = 0 ;i < mc ;i += 16 ) { 3581int A_base_addr = (mc /8 )* (i /8 )* 16 ; 3582for (int64_t j = 0 ;j < nc ;j += 8 ) { 3583int B_base_addr = (nc /8 )* (j /8 )* 16 ; 3584acc_t acc [8 ]; 3585vec_t A0_block [16 ];vec_t A1_block [16 ]; 3586for (int x = 0 ;x < 8 ;x ++ ) 3587__builtin_mma_xxsetaccz (& acc [x ]); 3588for (int64_t l = 0 ;l < kc ;l += 8 ) { 3589int A0_block_idx = A_base_addr + (l /8 )* 16 ; 3590int A1_block_idx = A0_block_idx + (mc /8 )* 16 ; 3591int B_block_idx = B_base_addr + (l /8 )* 16 ; 3592vec_t * A0_block = & vec_A [A0_block_idx ]; 3593vec_t * A1_block = & vec_A [A1_block_idx ]; 3594vec_t * B_block = & vec_B [B_block_idx ]; 3595MMA_16x8 (A0_block ,A1_block ,B_block ,acc ); 3596 } 3597if (kk == 0 ) { 3598save_acc (& acc [0 ],ii + i ,jj + j ); 3599save_acc (& acc [1 ],ii + i ,jj + j + 4 ); 3600save_acc (& acc [2 ],ii + i + 4 ,jj + j ); 3601save_acc (& acc [3 ],ii + i + 4 ,jj + j + 4 ); 3602save_acc (& acc [4 ],ii + i + 8 ,jj + j ); 3603save_acc (& acc [5 ],ii + i + 8 ,jj + j + 4 ); 3604save_acc (& acc [6 ],ii + i + 12 ,jj + j ); 3605save_acc (& acc [7 ],ii + i + 12 ,jj + j + 4 ); 3606 }else { 3607add_save_acc (& acc [0 ],ii + i ,jj + j ); 3608add_save_acc (& acc [1 ],ii + i ,jj + j + 4 ); 3609add_save_acc (& acc [2 ],ii + i + 4 ,jj + j ); 3610add_save_acc (& acc [3 ],ii + i + 4 ,jj + j + 4 ); 3611add_save_acc (& acc [4 ],ii + i + 8 ,jj + j ); 3612add_save_acc (& acc [5 ],ii + i + 8 ,jj + j + 4 ); 3613add_save_acc (& acc [6 ],ii + i + 12 ,jj + j ); 3614add_save_acc (& acc [7 ],ii + i + 12 ,jj + j + 4 ); 3615 } 3616 } 3617 } 3618 } 3619 3620void matmul_tiled (int64_t m ,int64_t n ,int64_t mc ,int64_t nc ,int64_t kc ) { 3621int64_t ytiles = m /mc ; 3622int64_t xtiles = n /nc ; 3623int64_t tiles = xtiles * ytiles ; 3624int64_t duty = (tiles + nth - 1 ) /nth ; 3625int64_t start = duty * ith ; 3626int64_t end = start + duty ; 3627if (end > tiles ) { 3628end = tiles ; 3629 } 3630for (int64_t job = start ;job < end ;++ job ) { 3631int64_t ii = (job /xtiles )* mc ; 3632int64_t jj = (job %xtiles )* nc ; 3633for (int64_t kk = 0 ;kk < k ;kk += kc ) { 3634vec_t A_pack [kc * mc /4 ]; 3635vec_t B_pack [kc * nc /4 ]; 3636packTranspose (A + (ii * lda )+ kk ,lda ,kc ,mc , (float * )A_pack ); 3637packTranspose (B + (jj * ldb )+ kk ,ldb ,kc ,nc , (float * )B_pack ); 3638KERNEL (ii ,jj ,mc ,nc ,kc ,A_pack ,B_pack ,kk ); 3639 } 3640 } 3641 } 3642 3643void mnpack (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 3644int m_rem = MIN (m - m0 ,8 ); 3645int n_rem = MIN (n - n0 ,8 ); 3646int mc = 0 ,nc = 0 ; 3647if (m_rem >=8 && n_rem >=8 ) { 3648mc = 8 ; 3649nc = 8 ; 3650gemm < 8 ,8 > (m0 ,m ,n0 ,n ); 3651 }else if (m_rem >=4 && n_rem >=8 ) { 3652mc = 4 ; 3653nc = 8 ; 3654gemm < 4 ,8 > (m0 ,m ,n0 ,n ); 3655 }else if (m_rem >=8 && n_rem >=4 ) { 3656mc = 8 ; 3657nc = 4 ; 3658gemm < 8 ,4 > (m0 ,m ,n0 ,n ); 3659 }else if (m_rem >=4 && n_rem >=4 ) { 3660mc = 4 ; 3661nc = 4 ; 3662gemm < 4 ,4 > (m0 ,m ,n0 ,n ); 3663 }else { 3664mc = (m_rem >=4 ) ?4 :m_rem ; 3665nc = (n_rem >=4 ) ?4 :n_rem ; 3666if (mc == 0 || nc == 0 ) 3667return ; 3668gemm_small (m0 ,m ,n0 ,n ,mc ,nc ); 3669 } 3670int64_t mp = m0 + ((m - m0 ) /mc )* mc ; 3671int64_t np = n0 + ((n - n0 ) /nc )* nc ; 3672mnpack (mp ,m ,n0 ,np ); 3673mnpack (m0 ,m ,np ,n ); 3674 } 3675 3676void gemm_small (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ,int RM ,int RN ) { 3677int64_t ytiles = (m - m0 ) /RM ; 3678int64_t xtiles = (n - n0 ) /RN ; 3679int64_t tiles = xtiles * ytiles ; 3680int64_t duty = (tiles + nth - 1 ) /nth ; 3681int64_t start = duty * ith ; 3682int64_t end = start + duty ; 3683if (end > tiles ) 3684end = tiles ; 3685for (int64_t job = start ;job < end ;++ job ) { 3686int64_t ii = m0 + job /xtiles * RM ; 3687int64_t jj = n0 + job %xtiles * RN ; 3688vec_t vec_C [4 ]; 3689acc_t acc_0 ; 3690__builtin_mma_xxsetaccz (& acc_0 ); 3691vec_t vec_A [4 ]= {0 },vec_B [4 ]= {0 }; 3692for (int l = 0 ;l < k ;l += 4 ) { 3693/* 'GEMV Forwarding' concept is used in first two conditional loops. 3694* when one of the matrix has a single row/column, the elements are 3695* broadcasted, instead of using packing routine to prepack the 3696* matrix elements. 3697*/ 3698if (RM == 1 ) { 3699float * a = const_cast < float *> (A + (ii )* lda + l ); 3700packTranspose (B + (jj * ldb )+ l ,ldb ,RN ,4 , (float * )vec_B ); 3701vec_A [0 ]= (vec_t )vec_xl (0 ,a ); 3702vec_A [1 ]= (vec_t )vec_splats (* ((float * )& vec_A + 1 )); 3703vec_A [2 ]= (vec_t )vec_splats (* ((float * )& vec_A + 2 )); 3704vec_A [3 ]= (vec_t )vec_splats (* ((float * )& vec_A + 3 )); 3705 }else if (RN == 1 ) { 3706packTranspose (A + (ii * lda )+ l ,lda ,RM ,4 , (float * )vec_A ); 3707float * b = const_cast < float *> (B + (jj )* ldb + l ); 3708vec_B [0 ]= (vec_t )vec_xl (0 ,b ); 3709vec_B [1 ]= (vec_t )vec_splats (* ((float * )& vec_B + 1 )); 3710vec_B [2 ]= (vec_t )vec_splats (* ((float * )& vec_B + 2 )); 3711vec_B [3 ]= (vec_t )vec_splats (* ((float * )& vec_B + 3 )); 3712 }else { 3713packTranspose (A + (ii * lda )+ l ,lda ,RM ,4 , (float * )vec_A ); 3714packTranspose (B + (jj * ldb )+ l ,ldb ,RN ,4 , (float * )vec_B ); 3715 } 3716__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [0 ],vec_B [0 ]); 3717__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [1 ],vec_B [1 ]); 3718__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [2 ],vec_B [2 ]); 3719__builtin_mma_xvf32gerpp (& acc_0 ,vec_A [3 ],vec_B [3 ]); 3720 } 3721__builtin_mma_disassemble_acc (vec_C ,& acc_0 ); 3722for (int I = 0 ;I < RM ;I ++ ) { 3723for (int J = 0 ;J < RN ;J ++ ) { 3724* ((float * )(C + ii + ((jj + J )* ldc )+ I ))= * ((float * )& vec_C [I ]+ J ); 3725 } 3726 } 3727 } 3728 } 3729 3730template < int RM ,int RN > 3731inline void kernel (int64_t ii ,int64_t jj ) { 3732if constexpr (RM == 4 && RN == 4 ) { 3733KERNEL_4x4 (ii ,jj ); 3734 }else if constexpr (RM == 4 && RN == 8 ) { 3735KERNEL_4x8 (ii ,jj ); 3736 }else if constexpr (RM == 8 && RN == 4 ) { 3737KERNEL_8x4 (ii ,jj ); 3738 }else if constexpr (RM == 8 && RN == 8 ) { 3739KERNEL_8x8 (ii ,jj ); 3740 }else { 3741 static_assert(false,"RN/RM values not supported" ); 3742 } 3743 } 3744 3745template < int RM ,int RN > 3746NOINLINE void gemm (int64_t m0 ,int64_t m ,int64_t n0 ,int64_t n ) { 3747int64_t ytiles = (m - m0 ) /RM ; 3748int64_t xtiles = (n - n0 ) /RN ; 3749int64_t tiles = xtiles * ytiles ; 3750int64_t duty = (tiles + nth - 1 ) /nth ; 3751int64_t start = duty * ith ; 3752int64_t end = start + duty ; 3753if (end > tiles ) 3754end = tiles ; 3755for (int64_t job = start ;job < end ;++ job ) { 3756int64_t ii = m0 + job /xtiles * RM ; 3757int64_t jj = n0 + job %xtiles * RN ; 3758kernel < RM ,RN > (ii ,jj ); 3759 } 3760 } 3761 3762const float * const A ; 3763const float * const B ; 3764float * C ; 3765const int64_t k ; 3766const int64_t lda ; 3767const int64_t ldb ; 3768const int64_t ldc ; 3769const int ith ; 3770const int nth ; 3771}; 3772#endif 3773}// namespace 3774 3775/** 3776* Performs optimized matrix multiplication on CPU. 3777* 3778* This subroutine may compute C = Aᵀ * B with column major ordering. 3779* Despite its name, this isn't a generalized implementation. Work is 3780* only performed when a handwritten kernel is written and available. 3781* Otherwise the caller should fall back to a general matmul routine. 3782* 3783* For example, for single-threaded single-precision GEMM you can say 3784* 3785* llamafile_sgemm(m, n, k, A, lda, B, ldb, C, ldc, 3786* 0, 1, 3787* GGML_TYPE_F32, GGML_TYPE_F32, GGML_TYPE_F32); 3788* 3789* @param m is rows in `A` and `C` 3790* @param n is cols in `B` and `C` 3791* @param k is cols in `A` and rows in `B` 3792* @param A is first input matrix (always transposed) 3793* @param lda is row stride of `A` 3794* @param B is second input matrix (never transposed) 3795* @param ldb is row stride of `B` 3796* @param C is input/output array of output matrices 3797* @param ldc is row stride of `C` 3798* @param ith is thread id (must be less than `nth`) 3799* @param nth is number of threads (must be greater than zero) 3800* @param Atype is GGML data type of `A` 3801* @param Btype is GGML data type of `B` 3802* @param Ctype is GGML data type of `C` 3803* @return true if this function was able to service the matmul request 3804*/ 3805bool llamafile_sgemm (const struct ggml_compute_params * params ,int64_t m ,int64_t n ,int64_t k , 3806const void * A ,int64_t lda ,const void * B ,int64_t ldb ,void * C , 3807int64_t ldc ,int Atype ,int Btype ,int Ctype ) { 3808 3809assert (m >=0 ); 3810assert (n >=0 ); 3811assert (k >=0 ); 3812assert (lda >=k ); 3813assert (ldb >=k ); 3814assert (ldc >=m ); 3815assert (params -> nth > 0 ); 3816assert (params -> ith < params -> nth ); 3817 3818// only enable sgemm for prompt processing 3819#if !defined(__MMA__ ) 3820if (n < 2 ) 3821return false; 3822#endif 3823 3824if (Ctype != GGML_TYPE_F32 ) 3825return false; 3826 3827switch (Atype ) { 3828 3829case GGML_TYPE_F32 : { 3830if (Btype != GGML_TYPE_F32 ) 3831return false; 3832#if defined(__AVX512F__ ) 3833tinyBLAS < 16 ,__m512 ,__m512 ,float ,float ,float > tb {params , 3834k , (const float * )A ,lda , 3835 (const float * )B ,ldb , 3836 (float * )C ,ldc }; 3837return tb .matmul (m ,n ); 3838#elif defined(__AVX__ )|| defined(__AVX2__ ) 3839tinyBLAS < 8 ,__m256 ,__m256 ,float ,float ,float > tb {params , 3840k , (const float * )A ,lda , 3841 (const float * )B ,ldb , 3842 (float * )C ,ldc }; 3843return tb .matmul (m ,n ); 3844#elif defined(__ARM_NEON ) 3845if (n < 4 ) 3846return false; 3847tinyBLAS < 4 ,float32x4_t ,float32x4_t ,float ,float ,float > tb {params , 3848k , (const float * )A ,lda , 3849 (const float * )B ,ldb , 3850 (float * )C ,ldc }; 3851return tb .matmul (m ,n ); 3852#elif defined(__VXE__ )|| defined(__VXE2__ ) 3853if (n < 4 ) 3854return false; 3855tinyBLAS < 4 ,float32x4_t ,float32x4_t ,float ,float ,float > tb {params , 3856k , (const float * )A ,lda , 3857 (const float * )B ,ldb , 3858 (float * )C ,ldc }; 3859return tb .matmul (m ,n ); 3860#elif defined(__MMA__ ) 3861if (k %8 ) 3862return false; 3863tinyBLAS_PPC tb { 3864k , (const float * )A ,lda , 3865 (const float * )B ,ldb , 3866 (float * )C ,ldc , 3867params -> ith ,params -> nth }; 3868tb .matmul (m ,n ); 3869return true; 3870#elif defined(__riscv_v_intrinsic ) 3871#if LMUL == 1 3872tinyBLAS_RVV < vfloat32m1_t ,vfloat32m1_t ,float ,float ,float > tb {params , 3873k , (const float * )A ,lda , 3874 (const float * )B ,ldb , 3875 (float * )C ,ldc }; 3876#elif LMUL == 2 3877tinyBLAS_RVV < vfloat32m2_t ,vfloat32m2_t ,float ,float ,float > tb {params , 3878k , (const float * )A ,lda , 3879 (const float * )B ,ldb , 3880 (float * )C ,ldc }; 3881#else // LMUL = 4 3882tinyBLAS_RVV < vfloat32m4_t ,vfloat32m4_t ,float ,float ,float > tb {params , 3883k , (const float * )A ,lda , 3884 (const float * )B ,ldb , 3885 (float * )C ,ldc }; 3886#endif 3887return tb .matmul (m ,n ); 3888#else 3889return false; 3890#endif 3891 } 3892 3893case GGML_TYPE_BF16 : { 3894#if defined(__AVX512BF16__ ) 3895if (Btype == GGML_TYPE_BF16 ) { 3896tinyBLAS < 32 ,__m512 ,__m512bh ,ggml_bf16_t ,ggml_bf16_t ,float > tb {params ,k , 3897 (const ggml_bf16_t * )A ,lda , 3898 (const ggml_bf16_t * )B ,ldb , 3899 (float * )C ,ldc }; 3900return tb .matmul (m ,n ); 3901 } 3902#elif defined(__AVX512F__ ) 3903if (Btype == GGML_TYPE_BF16 ) { 3904tinyBLAS < 16 ,__m512 ,__m512 ,ggml_bf16_t ,ggml_bf16_t ,float > tb {params ,k , 3905 (const ggml_bf16_t * )A ,lda , 3906 (const ggml_bf16_t * )B ,ldb , 3907 (float * )C ,ldc }; 3908return tb .matmul (m ,n ); 3909 } 3910#elif defined(__AVX2__ ) 3911if (Btype == GGML_TYPE_BF16 ) { 3912tinyBLAS < 8 ,__m256 ,__m256 ,ggml_bf16_t ,ggml_bf16_t ,float > tb {params ,k , 3913 (const ggml_bf16_t * )A ,lda , 3914 (const ggml_bf16_t * )B ,ldb , 3915 (float * )C ,ldc }; 3916return tb .matmul (m ,n ); 3917 } 3918#elif defined(__MMA__ ) 3919if (k %8 ) { 3920return false; 3921 } 3922 3923if (Btype == GGML_TYPE_BF16 ) { 3924tinyBLAS_HP16_PPC < ggml_bf16_t ,ggml_bf16_t ,float > tb {k , 3925 (const ggml_bf16_t * )A ,lda , 3926 (const ggml_bf16_t * )B ,ldb , 3927 (float * )C ,ldc , 3928params -> ith ,params -> nth }; 3929 3930tb .matmul (m ,n ); 3931return true; 3932 } 3933#elif defined(__riscv_zvfbfwma ) 3934if (Btype == GGML_TYPE_BF16 ) { 3935#if LMUL == 1 3936tinyBLAS_RVV < vfloat32m1_t ,vbfloat16mf2_t ,ggml_bf16_t ,ggml_bf16_t ,float > tb {params , 3937k , (const ggml_bf16_t * )A ,lda , 3938 (const ggml_bf16_t * )B ,ldb , 3939 (float * )C ,ldc }; 3940#elif LMUL == 2 3941tinyBLAS_RVV < vfloat32m2_t ,vbfloat16m1_t ,ggml_bf16_t ,ggml_bf16_t ,float > tb {params , 3942k , (const ggml_bf16_t * )A ,lda , 3943 (const ggml_bf16_t * )B ,ldb , 3944 (float * )C ,ldc }; 3945#else // LMUL = 4 3946tinyBLAS_RVV < vfloat32m4_t ,vbfloat16m2_t ,ggml_bf16_t ,ggml_bf16_t ,float > tb {params , 3947k , (const ggml_bf16_t * )A ,lda , 3948 (const ggml_bf16_t * )B ,ldb , 3949 (float * )C ,ldc }; 3950#endif 3951return tb .matmul (m ,n ); 3952 } 3953#endif 3954return false; 3955 } 3956 3957case GGML_TYPE_F16 : { 3958#if defined(__AVX512F__ ) 3959if (Btype == GGML_TYPE_F16 ) { 3960tinyBLAS < 16 ,__m512 ,__m512 ,ggml_fp16_t ,ggml_fp16_t ,float > tb {params ,k , 3961 (const ggml_fp16_t * )A ,lda , 3962 (const ggml_fp16_t * )B ,ldb , 3963 (float * )C ,ldc }; 3964return tb .matmul (m ,n ); 3965 } 3966#elif (defined(__AVX__ )|| defined(__AVX2__ ))&& defined(__F16C__ ) 3967if (Btype == GGML_TYPE_F16 ) { 3968tinyBLAS < 8 ,__m256 ,__m256 ,ggml_fp16_t ,ggml_fp16_t ,float > tb {params ,k , 3969 (const ggml_fp16_t * )A ,lda , 3970 (const ggml_fp16_t * )B ,ldb , 3971 (float * )C ,ldc }; 3972return tb .matmul (m ,n ); 3973 } 3974#elif defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC )&& !defined(_MSC_VER ) 3975if (n < 8 ) 3976return false; 3977if (Btype == GGML_TYPE_F16 ) { 3978tinyBLAS < 8 ,float16x8_t ,float16x8_t ,ggml_fp16_t ,ggml_fp16_t ,float > tb {params , 3979k , (const ggml_fp16_t * )A ,lda , 3980 (const ggml_fp16_t * )B ,ldb , 3981 (float * )C ,ldc }; 3982return tb .matmul (m ,n ); 3983 } 3984#elif defined(__ARM_NEON )&& !defined(_MSC_VER ) 3985if (Btype == GGML_TYPE_F32 ) { 3986tinyBLAS < 4 ,float32x4_t ,float32x4_t ,ggml_fp16_t ,float ,float > tb {params , 3987k , (const ggml_fp16_t * )A ,lda , 3988 (const float * )B ,ldb , 3989 (float * )C ,ldc }; 3990return tb .matmul (m ,n ); 3991 } 3992#elif defined(__VXE__ )|| defined(__VXE2__ ) 3993if (n < 4 ) 3994return false; 3995if (Btype == GGML_TYPE_F16 ) { 3996tinyBLAS < 4 ,float32x4_t ,float32x4_t ,ggml_fp16_t ,ggml_fp16_t ,float > tb {params , 3997k , (const ggml_fp16_t * )A ,lda , 3998 (const ggml_fp16_t * )B ,ldb , 3999 (float * )C ,ldc }; 4000return tb .matmul (m ,n ); 4001 } 4002#elif defined(__riscv_zvfh ) 4003if (Btype == GGML_TYPE_F16 ) { 4004#if LMUL == 1 4005tinyBLAS_RVV < vfloat32m1_t ,vfloat16mf2_t ,ggml_fp16_t ,ggml_fp16_t ,float > tb {params , 4006k , (const ggml_fp16_t * )A ,lda , 4007 (const ggml_fp16_t * )B ,ldb , 4008 (float * )C ,ldc }; 4009#elif LMUL == 2 4010tinyBLAS_RVV < vfloat32m2_t ,vfloat16m1_t ,ggml_fp16_t ,ggml_fp16_t ,float > tb {params , 4011k , (const ggml_fp16_t * )A ,lda , 4012 (const ggml_fp16_t * )B ,ldb , 4013 (float * )C ,ldc }; 4014#else // LMUL = 4 4015tinyBLAS_RVV < vfloat32m4_t ,vfloat16m2_t ,ggml_fp16_t ,ggml_fp16_t ,float > tb {params , 4016k , (const ggml_fp16_t * )A ,lda , 4017 (const ggml_fp16_t * )B ,ldb , 4018 (float * )C ,ldc }; 4019#endif 4020return tb .matmul (m ,n ); 4021 } 4022#elif defined(__MMA__ ) 4023if (k %8 ) { 4024return false; 4025 } 4026 4027if (Btype == GGML_TYPE_F16 ) { 4028tinyBLAS_HP16_PPC < ggml_fp16_t ,ggml_fp16_t ,float > tb {k , 4029 (const ggml_fp16_t * )A ,lda , 4030 (const ggml_fp16_t * )B ,ldb , 4031 (float * )C ,ldc , 4032params -> ith ,params -> nth }; 4033 4034tb .matmul (m ,n ); 4035return true; 4036 } 4037#endif 4038return false; 4039 } 4040 4041case GGML_TYPE_Q8_0 : { 4042if (Btype != GGML_TYPE_Q8_0 ) 4043return false; 4044#if defined(__AVX2__ )|| defined(__AVX512F__ )|| defined(__AVX__ ) 4045tinyBLAS_Q0_AVX < block_q8_0 ,block_q8_0 ,float > tb { 4046k , (const block_q8_0 * )A ,lda , 4047 (const block_q8_0 * )B ,ldb , 4048 (float * )C ,ldc , 4049params -> ith ,params -> nth }; 4050tb .matmul (m ,n ); 4051return true; 4052#elif defined(__ARM_FEATURE_DOTPROD ) 4053tinyBLAS_Q0_ARM < block_q8_0 > tb { 4054k , (const block_q8_0 * )A ,lda , 4055 (const block_q8_0 * )B ,ldb , 4056 (float * )C ,ldc , 4057params -> ith ,params -> nth }; 4058tb .matmul (m ,n ); 4059return true; 4060#elif defined(__MMA__ ) 4061//TO-DO: Remove this condition once gemv forwarding is enabled. 4062if (n < 8 && n != 4 ) 4063return false; 4064if (m < 8 && m != 4 ) 4065return false; 4066tinyBLAS_Q0_PPC < block_q8_0 > tb { 4067k , (const block_q8_0 * )A ,lda , 4068 (const block_q8_0 * )B ,ldb , 4069 (float * )C ,ldc , 4070params -> ith ,params -> nth }; 4071tb .matmul (m ,n ); 4072return true; 4073#else 4074return false; 4075#endif 4076 } 4077 4078case GGML_TYPE_Q4_0 : { 4079if (Btype != GGML_TYPE_Q8_0 ) 4080return false; 4081#if defined(__AVX2__ )|| defined(__AVX512F__ )|| defined(__AVX__ ) 4082tinyBLAS_Q0_AVX < block_q4_0 ,block_q8_0 ,float > tb { 4083k , (const block_q4_0 * )A ,lda , 4084 (const block_q8_0 * )B ,ldb , 4085 (float * )C ,ldc , 4086params -> ith ,params -> nth }; 4087tb .matmul (m ,n ); 4088return true; 4089#elif defined(__ARM_FEATURE_DOTPROD ) 4090tinyBLAS_Q0_ARM < block_q4_0 > tb { 4091k , (const block_q4_0 * )A ,lda , 4092 (const block_q8_0 * )B ,ldb , 4093 (float * )C ,ldc , 4094params -> ith ,params -> nth }; 4095tb .matmul (m ,n ); 4096return true; 4097#elif defined(__MMA__ ) 4098//TO-DO: Remove this condition once gemv forwarding is enabled. 4099if (n < 8 && n != 4 ) 4100return false; 4101if (m < 8 && m != 4 ) 4102return false; 4103tinyBLAS_Q0_PPC < block_q4_0 > tb { 4104k , (const block_q4_0 * )A ,lda , 4105 (const block_q8_0 * )B ,ldb , 4106 (float * )C ,ldc , 4107params -> ith ,params -> nth }; 4108tb .matmul (m ,n ); 4109return true; 4110#else 4111return false; 4112#endif 4113 } 4114 4115case GGML_TYPE_Q5_0 : { 4116if (Btype != GGML_TYPE_Q8_0 ) 4117return false; 4118#if defined(__AVX2__ )|| defined(__AVX512F__ )|| defined(__AVX__ ) 4119tinyBLAS_Q0_AVX < block_q5_0 ,block_q8_0 ,float > tb { 4120k , (const block_q5_0 * )A ,lda , 4121 (const block_q8_0 * )B ,ldb , 4122 (float * )C ,ldc , 4123params -> ith ,params -> nth }; 4124tb .matmul (m ,n ); 4125return true; 4126#else 4127return false; 4128#endif 4129 } 4130 4131case GGML_TYPE_IQ4_NL : { 4132if (Btype != GGML_TYPE_Q8_0 ) 4133return false; 4134#if defined(__AVX2__ )|| defined(__AVX512F__ )|| defined(__AVX__ ) 4135tinyBLAS_Q0_AVX < block_iq4_nl ,block_q8_0 ,float > tb { 4136k , (const block_iq4_nl * )A ,lda , 4137 (const block_q8_0 * )B ,ldb , 4138 (float * )C ,ldc , 4139params -> ith ,params -> nth }; 4140tb .matmul (m ,n ); 4141return true; 4142#else 4143return false; 4144#endif 4145 } 4146 4147default : 4148return false; 4149 } 4150 4151 (void )params ; 4152 (void )m ; 4153 (void )n ; 4154 (void )k ; 4155 (void )A ; 4156 (void )lda ; 4157 (void )B ; 4158 (void )ldb ; 4159 (void )C ; 4160 (void )ldc ; 4161 (void )Atype ; 4162 (void )Btype ; 4163 (void )Ctype ; 4164}