char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
bdc9c743a
char/aliceai-t5-moe
1#define GGML_COMMON_IMPL_CPP 2#define GGML_COMMON_DECL_CPP 3#include "ggml-common.h" 4#include "ggml-backend-impl.h" 5 6#include "ggml-impl.h" 7#include "ggml-cpu.h" 8#include "ggml-cpu-impl.h" 9#include "simd-mappings.h" 10#include "traits.h" 11 12#include <cmath> 13#include <cstring> 14#include <cassert> 15#include <cstdlib> // for qsort 16#include <cstdio> // for GGML_ASSERT 17 18#define GGML_CPU_CLANG_WORKAROUND 19#include "../../repack.h" 20 21#if defined(__GNUC__ ) 22#pragma GCC diagnostic ignored "-Woverlength-strings" 23#endif 24 25#define UNUSED GGML_UNUSED 26 27#if defined(__aarch64__ )&& defined(__ARM_NEON )&& (defined(__ARM_FEATURE_MATMUL_INT8 )|| defined(__ARM_FEATURE_DOTPROD )) 28// Helper for decoding scales and mins of Q4_K and Q5_K block formats 29static inline void decode_q_Kx8_6bit_scales (const uint8_t * scales_in ,int16x8_t * out_mins ,int8_t * out_scales ) { 30constexpr uint32_t kmask1 = 0x3f3f3f3f ; 31constexpr uint32_t kmask2 = 0x0f0f0f0f ; 32constexpr uint32_t kmask3 = 0x03030303 ; 33constexpr uint8_t scales_size = 12 ; 34 35uint32_t sm [3 ]; 36memcpy (sm ,scales_in ,scales_size ); 37 38const uint32_t mins_0_3 = sm [1 ]& kmask1 ; 39const uint32_t mins_4_7 = ((sm [2 ] >>4 )& kmask2 ) | (((sm [1 ] >>6 )& kmask3 ) <<4 ); 40const uint32x2_t mins_u32 = {mins_0_3 ,mins_4_7 }; 41 42* out_mins = vreinterpretq_s16_u16 (vmovl_u8 (vreinterpret_u8_u32 (mins_u32 ))); 43 44uint32_t scales_u32 [2 ]; 45scales_u32 [0 ]= sm [0 ]& kmask1 ; 46scales_u32 [1 ]= (sm [2 ]& kmask2 ) | (((sm [0 ] >>6 )& kmask3 ) <<4 ); 47memcpy (out_scales ,scales_u32 ,8 ); 48} 49#endif 50 51void ggml_quantize_mat_q8_0_4x4 (const float * GGML_RESTRICT x ,void * GGML_RESTRICT vy ,int64_t k ) { 52assert (QK8_0 == 32 ); 53assert (k %QK8_0 == 0 ); 54const int nb = k /QK8_0 ; 55 56block_q8_0x4 * GGML_RESTRICT y = (block_q8_0x4 * )vy ; 57 58#if defined(__ARM_NEON ) 59float32x4_t srcv [4 ][8 ]; 60float id [4 ]; 61 62for (int i = 0 ;i < nb ;i ++ ) { 63float32x4_t asrcv [8 ]; 64float32x4_t amaxv [8 ]; 65 66for (int row_iter = 0 ;row_iter < 4 ;row_iter ++ ) { 67for (int j = 0 ;j < 8 ;j ++ )srcv [row_iter ][j ]= vld1q_f32 (x + row_iter * k + i * 32 + 4 * j ); 68for (int j = 0 ;j < 8 ;j ++ )asrcv [j ]= vabsq_f32 (srcv [row_iter ][j ]); 69 70for (int j = 0 ;j < 4 ;j ++ )amaxv [2 * j ]= vmaxq_f32 (asrcv [2 * j ],asrcv [2 * j + 1 ]); 71for (int j = 0 ;j < 2 ;j ++ )amaxv [4 * j ]= vmaxq_f32 (amaxv [4 * j ],amaxv [4 * j + 2 ]); 72for (int j = 0 ;j < 1 ;j ++ )amaxv [8 * j ]= vmaxq_f32 (amaxv [8 * j ],amaxv [8 * j + 4 ]); 73 74const float amax = vmaxvq_f32 (amaxv [0 ]); 75 76const float d = amax / ((1 <<7 )- 1 ); 77id [row_iter ]= d ?1.0f /d :0.0f ; 78 79y [i ].d [row_iter ]= GGML_CPU_FP32_TO_FP16 (d ); 80 } 81 82for (int j = 0 ;j < 8 ;j ++ ) { 83float32x4_t v = vmulq_n_f32 (srcv [0 ][j ],id [0 ]); 84int32x4_t vi = vcvtnq_s32_f32 (v ); 85y [i ].qs [16 * j + 0 ]= vgetq_lane_s32 (vi ,0 ); 86y [i ].qs [16 * j + 1 ]= vgetq_lane_s32 (vi ,1 ); 87y [i ].qs [16 * j + 2 ]= vgetq_lane_s32 (vi ,2 ); 88y [i ].qs [16 * j + 3 ]= vgetq_lane_s32 (vi ,3 ); 89 90v = vmulq_n_f32 (srcv [1 ][j ],id [1 ]); 91vi = vcvtnq_s32_f32 (v ); 92y [i ].qs [16 * j + 4 ]= vgetq_lane_s32 (vi ,0 ); 93y [i ].qs [16 * j + 5 ]= vgetq_lane_s32 (vi ,1 ); 94y [i ].qs [16 * j + 6 ]= vgetq_lane_s32 (vi ,2 ); 95y [i ].qs [16 * j + 7 ]= vgetq_lane_s32 (vi ,3 ); 96 97v = vmulq_n_f32 (srcv [2 ][j ],id [2 ]); 98vi = vcvtnq_s32_f32 (v ); 99y [i ].qs [16 * j + 8 ]= vgetq_lane_s32 (vi ,0 ); 100y [i ].qs [16 * j + 9 ]= vgetq_lane_s32 (vi ,1 ); 101y [i ].qs [16 * j + 10 ]= vgetq_lane_s32 (vi ,2 ); 102y [i ].qs [16 * j + 11 ]= vgetq_lane_s32 (vi ,3 ); 103 104v = vmulq_n_f32 (srcv [3 ][j ],id [3 ]); 105vi = vcvtnq_s32_f32 (v ); 106y [i ].qs [16 * j + 12 ]= vgetq_lane_s32 (vi ,0 ); 107y [i ].qs [16 * j + 13 ]= vgetq_lane_s32 (vi ,1 ); 108y [i ].qs [16 * j + 14 ]= vgetq_lane_s32 (vi ,2 ); 109y [i ].qs [16 * j + 15 ]= vgetq_lane_s32 (vi ,3 ); 110 } 111 } 112#else 113UNUSED (nb ); 114UNUSED (y ); 115ggml_quantize_mat_q8_0_4x4_generic (x ,vy ,k ); 116#endif 117} 118 119void ggml_quantize_mat_q8_0_4x8 (const float * GGML_RESTRICT x ,void * GGML_RESTRICT vy ,int64_t k ) { 120assert (QK8_0 == 32 ); 121assert (k %QK8_0 == 0 ); 122const int nb = k /QK8_0 ; 123 124block_q8_0x4 * GGML_RESTRICT y = (block_q8_0x4 * )vy ; 125 126#if defined(__ARM_NEON ) 127float32x4_t srcv [4 ][8 ]; 128float id [4 ]; 129 130for (int i = 0 ;i < nb ;i ++ ) { 131float32x4_t asrcv [8 ]; 132float32x4_t amaxv [8 ]; 133 134for (int row_iter = 0 ;row_iter < 4 ;row_iter ++ ) { 135for (int j = 0 ;j < 8 ;j ++ )srcv [row_iter ][j ]= vld1q_f32 (x + row_iter * k + i * 32 + 4 * j ); 136for (int j = 0 ;j < 8 ;j ++ )asrcv [j ]= vabsq_f32 (srcv [row_iter ][j ]); 137 138for (int j = 0 ;j < 4 ;j ++ )amaxv [2 * j ]= vmaxq_f32 (asrcv [2 * j ],asrcv [2 * j + 1 ]); 139for (int j = 0 ;j < 2 ;j ++ )amaxv [4 * j ]= vmaxq_f32 (amaxv [4 * j ],amaxv [4 * j + 2 ]); 140for (int j = 0 ;j < 1 ;j ++ )amaxv [8 * j ]= vmaxq_f32 (amaxv [8 * j ],amaxv [8 * j + 4 ]); 141 142const float amax = vmaxvq_f32 (amaxv [0 ]); 143 144const float d = amax / ((1 <<7 )- 1 ); 145id [row_iter ]= d ?1.0f /d :0.0f ; 146 147y [i ].d [row_iter ]= GGML_CPU_FP32_TO_FP16 (d ); 148 } 149 150for (int j = 0 ;j < 4 ;j ++ ) { 151float32x4_t v = vmulq_n_f32 (srcv [0 ][2 * j ],id [0 ]); 152int32x4_t vi = vcvtnq_s32_f32 (v ); 153y [i ].qs [32 * j + 0 ]= vgetq_lane_s32 (vi ,0 ); 154y [i ].qs [32 * j + 1 ]= vgetq_lane_s32 (vi ,1 ); 155y [i ].qs [32 * j + 2 ]= vgetq_lane_s32 (vi ,2 ); 156y [i ].qs [32 * j + 3 ]= vgetq_lane_s32 (vi ,3 ); 157v = vmulq_n_f32 (srcv [0 ][2 * j + 1 ],id [0 ]); 158vi = vcvtnq_s32_f32 (v ); 159y [i ].qs [32 * j + 4 ]= vgetq_lane_s32 (vi ,0 ); 160y [i ].qs [32 * j + 5 ]= vgetq_lane_s32 (vi ,1 ); 161y [i ].qs [32 * j + 6 ]= vgetq_lane_s32 (vi ,2 ); 162y [i ].qs [32 * j + 7 ]= vgetq_lane_s32 (vi ,3 ); 163 164v = vmulq_n_f32 (srcv [1 ][2 * j ],id [1 ]); 165vi = vcvtnq_s32_f32 (v ); 166y [i ].qs [32 * j + 8 ]= vgetq_lane_s32 (vi ,0 ); 167y [i ].qs [32 * j + 9 ]= vgetq_lane_s32 (vi ,1 ); 168y [i ].qs [32 * j + 10 ]= vgetq_lane_s32 (vi ,2 ); 169y [i ].qs [32 * j + 11 ]= vgetq_lane_s32 (vi ,3 ); 170v = vmulq_n_f32 (srcv [1 ][2 * j + 1 ],id [1 ]); 171vi = vcvtnq_s32_f32 (v ); 172y [i ].qs [32 * j + 12 ]= vgetq_lane_s32 (vi ,0 ); 173y [i ].qs [32 * j + 13 ]= vgetq_lane_s32 (vi ,1 ); 174y [i ].qs [32 * j + 14 ]= vgetq_lane_s32 (vi ,2 ); 175y [i ].qs [32 * j + 15 ]= vgetq_lane_s32 (vi ,3 ); 176 177v = vmulq_n_f32 (srcv [2 ][2 * j ],id [2 ]); 178vi = vcvtnq_s32_f32 (v ); 179y [i ].qs [32 * j + 16 ]= vgetq_lane_s32 (vi ,0 ); 180y [i ].qs [32 * j + 17 ]= vgetq_lane_s32 (vi ,1 ); 181y [i ].qs [32 * j + 18 ]= vgetq_lane_s32 (vi ,2 ); 182y [i ].qs [32 * j + 19 ]= vgetq_lane_s32 (vi ,3 ); 183v = vmulq_n_f32 (srcv [2 ][2 * j + 1 ],id [2 ]); 184vi = vcvtnq_s32_f32 (v ); 185y [i ].qs [32 * j + 20 ]= vgetq_lane_s32 (vi ,0 ); 186y [i ].qs [32 * j + 21 ]= vgetq_lane_s32 (vi ,1 ); 187y [i ].qs [32 * j + 22 ]= vgetq_lane_s32 (vi ,2 ); 188y [i ].qs [32 * j + 23 ]= vgetq_lane_s32 (vi ,3 ); 189 190v = vmulq_n_f32 (srcv [3 ][2 * j ],id [3 ]); 191vi = vcvtnq_s32_f32 (v ); 192y [i ].qs [32 * j + 24 ]= vgetq_lane_s32 (vi ,0 ); 193y [i ].qs [32 * j + 25 ]= vgetq_lane_s32 (vi ,1 ); 194y [i ].qs [32 * j + 26 ]= vgetq_lane_s32 (vi ,2 ); 195y [i ].qs [32 * j + 27 ]= vgetq_lane_s32 (vi ,3 ); 196v = vmulq_n_f32 (srcv [3 ][2 * j + 1 ],id [3 ]); 197vi = vcvtnq_s32_f32 (v ); 198y [i ].qs [32 * j + 28 ]= vgetq_lane_s32 (vi ,0 ); 199y [i ].qs [32 * j + 29 ]= vgetq_lane_s32 (vi ,1 ); 200y [i ].qs [32 * j + 30 ]= vgetq_lane_s32 (vi ,2 ); 201y [i ].qs [32 * j + 31 ]= vgetq_lane_s32 (vi ,3 ); 202 } 203 } 204 205#else 206UNUSED (nb ); 207UNUSED (y ); 208ggml_quantize_mat_q8_0_4x8_generic (x ,vy ,k ); 209#endif 210} 211 212void ggml_gemv_q4_0_4x4_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 213const int qk = QK8_0 ; 214const int nb = n /qk ; 215const int ncols_interleaved = 4 ; 216const int blocklen = 4 ; 217 218assert (n %qk == 0 ); 219assert (nc %ncols_interleaved == 0 ); 220 221UNUSED (s ); 222UNUSED (bs ); 223UNUSED (vx ); 224UNUSED (vy ); 225UNUSED (nr ); 226UNUSED (nc ); 227UNUSED (nb ); 228UNUSED (ncols_interleaved ); 229UNUSED (blocklen ); 230 231#if ! ((defined(_MSC_VER ))&& ! defined(__clang__ ))&& defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 232const block_q4_0x4 * b_ptr = (const block_q4_0x4 * )vx ; 233 234for (int c = 0 ;c < nc ;c += ncols_interleaved ) { 235const block_q8_0 * a_ptr = (const block_q8_0 * )vy ; 236float32x4_t acc = vdupq_n_f32 (0 ); 237for (int b = 0 ;b < nb ;b ++ ) { 238int8x16_t b0 = vld1q_s8 ((const int8_t * )b_ptr -> qs ); 239int8x16_t b1 = vld1q_s8 ((const int8_t * )b_ptr -> qs + 16 ); 240int8x16_t b2 = vld1q_s8 ((const int8_t * )b_ptr -> qs + 32 ); 241int8x16_t b3 = vld1q_s8 ((const int8_t * )b_ptr -> qs + 48 ); 242float16x4_t bd = vld1_f16 ((const __fp16 * )b_ptr -> d ); 243 244int8x16_t a0 = vld1q_s8 (a_ptr -> qs ); 245int8x16_t a1 = vld1q_s8 (a_ptr -> qs + qk /2 ); 246float16x4_t ad = vld1_dup_f16 ((const __fp16 * )& a_ptr -> d ); 247 248int32x4_t ret = vdupq_n_s32 (0 ); 249 250ret = vdotq_laneq_s32 (ret ,b0 <<4 ,a0 ,0 ); 251ret = vdotq_laneq_s32 (ret ,b1 <<4 ,a0 ,1 ); 252ret = vdotq_laneq_s32 (ret ,b2 <<4 ,a0 ,2 ); 253ret = vdotq_laneq_s32 (ret ,b3 <<4 ,a0 ,3 ); 254 255ret = vdotq_laneq_s32 (ret ,b0 & 0xf0U ,a1 ,0 ); 256ret = vdotq_laneq_s32 (ret ,b1 & 0xf0U ,a1 ,1 ); 257ret = vdotq_laneq_s32 (ret ,b2 & 0xf0U ,a1 ,2 ); 258ret = vdotq_laneq_s32 (ret ,b3 & 0xf0U ,a1 ,3 ); 259 260acc = vfmaq_f32 (acc ,vcvtq_n_f32_s32 (ret ,4 ), 261vmulq_f32 (vcvt_f32_f16 (ad ),vcvt_f32_f16 (bd ))); 262a_ptr ++ ; 263b_ptr ++ ; 264 } 265vst1q_f32 (s ,acc ); 266s += ncols_interleaved ; 267 } 268return ; 269#endif // #if ! ((defined(_MSC_VER)) && ! defined(__clang__)) && defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 270ggml_gemv_q4_0_4x4_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 271} 272 273void ggml_gemv_q4_0_4x8_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 274const int qk = QK8_0 ; 275const int nb = n /qk ; 276const int ncols_interleaved = 4 ; 277const int blocklen = 8 ; 278 279assert (n %qk == 0 ); 280assert (nc %ncols_interleaved == 0 ); 281 282UNUSED (s ); 283UNUSED (bs ); 284UNUSED (vx ); 285UNUSED (vy ); 286UNUSED (nr ); 287UNUSED (nc ); 288UNUSED (nb ); 289UNUSED (ncols_interleaved ); 290UNUSED (blocklen ); 291 292#if ! ((defined(_MSC_VER ))&& ! defined(__clang__ ))&& defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 293const block_q4_0x4 * b_ptr = (const block_q4_0x4 * )vx ; 294 295for (int c = 0 ;c < nc ;c += ncols_interleaved ) { 296const block_q8_0 * a_ptr = (const block_q8_0 * )vy ; 297float32x4_t acc = vdupq_n_f32 (0 ); 298for (int b = 0 ;b < nb ;b ++ ) { 299int8x16_t b0 = vld1q_s8 ((const int8_t * )b_ptr -> qs ); 300int8x16_t b1 = vld1q_s8 ((const int8_t * )b_ptr -> qs + 16 ); 301int8x16_t b2 = vld1q_s8 ((const int8_t * )b_ptr -> qs + 32 ); 302int8x16_t b3 = vld1q_s8 ((const int8_t * )b_ptr -> qs + 48 ); 303float16x4_t bd = vld1_f16 ((const __fp16 * )b_ptr -> d ); 304 305int8x16_t a0 = (int8x16_t )vld1q_dup_s64 ((const int64_t * )a_ptr -> qs ); 306int8x16_t a1 = (int8x16_t )vld1q_dup_s64 ((const int64_t * )a_ptr -> qs + 1 ); 307int8x16_t a2 = (int8x16_t )vld1q_dup_s64 ((const int64_t * )a_ptr -> qs + 2 ); 308int8x16_t a3 = (int8x16_t )vld1q_dup_s64 ((const int64_t * )a_ptr -> qs + 3 ); 309float16x4_t ad = vld1_dup_f16 ((const __fp16 * )& a_ptr -> d ); 310 311int32x4_t ret0 = vdupq_n_s32 (0 ); 312int32x4_t ret1 = vdupq_n_s32 (0 ); 313 314ret0 = vdotq_s32 (ret0 ,b0 <<4 ,a0 ); 315ret1 = vdotq_s32 (ret1 ,b1 <<4 ,a0 ); 316ret0 = vdotq_s32 (ret0 ,b2 <<4 ,a1 ); 317ret1 = vdotq_s32 (ret1 ,b3 <<4 ,a1 ); 318 319ret0 = vdotq_s32 (ret0 ,b0 & 0xf0U ,a2 ); 320ret1 = vdotq_s32 (ret1 ,b1 & 0xf0U ,a2 ); 321ret0 = vdotq_s32 (ret0 ,b2 & 0xf0U ,a3 ); 322ret1 = vdotq_s32 (ret1 ,b3 & 0xf0U ,a3 ); 323 324int32x4_t ret = vpaddq_s32 (ret0 ,ret1 ); 325 326acc = vfmaq_f32 (acc ,vcvtq_n_f32_s32 (ret ,4 ), 327vmulq_f32 (vcvt_f32_f16 (ad ),vcvt_f32_f16 (bd ))); 328a_ptr ++ ; 329b_ptr ++ ; 330 } 331vst1q_f32 (s ,acc ); 332s += ncols_interleaved ; 333 } 334return ; 335#endif // #if ! ((defined(_MSC_VER)) && ! defined(__clang__)) && defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 336ggml_gemv_q4_0_4x8_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 337} 338 339void ggml_gemv_q4_0_8x8_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 340const int qk = QK8_0 ; 341const int nb = n /qk ; 342const int ncols_interleaved = 8 ; 343const int blocklen = 8 ; 344 345assert (n %qk == 0 ); 346assert (nc %ncols_interleaved == 0 ); 347 348UNUSED (s ); 349UNUSED (bs ); 350UNUSED (vx ); 351UNUSED (vy ); 352UNUSED (nr ); 353UNUSED (nc ); 354UNUSED (nb ); 355UNUSED (ncols_interleaved ); 356UNUSED (blocklen ); 357 358#if ! ((defined(_MSC_VER ))&& ! defined(__clang__ ))&& defined(__aarch64__ ) 359#if defined(__ARM_FEATURE_SVE ) 360if (ggml_cpu_get_sve_cnt ()== QK8_0 ) { 361const void * b_ptr = vx ; 362const void * a_ptr = vy ; 363float * res_ptr = s ; 364 365 __asm__ __volatile__( 366"ptrue p0.b\n" 367"add %x[b_ptr], %x[b_ptr], #0x10\n" 368"1:" // Column loop 369"add x22, %x[a_ptr], #0x2\n" 370"mov z31.b, #0x0\n" 371"mov x21, %x[nb]\n" 372"2:" // Block loop 373"ld1b { z30.b }, p0/Z, [%x[b_ptr]]\n" 374"ld1b { z29.b }, p0/Z, [%x[b_ptr], #1, MUL VL]\n" 375"mov z28.s, #0x0\n" 376"mov z27.s, #0x0\n" 377"ld1rd { z26.d }, p0/Z, [x22]\n" 378"ld1b { z25.b }, p0/Z, [%x[b_ptr], #2, MUL VL]\n" 379"sub x20, x22, #0x2\n" 380"sub x21, x21, #0x1\n" 381"ld1b { z24.b }, p0/Z, [%x[b_ptr], #3, MUL VL]\n" 382"ld1rd { z23.d }, p0/Z, [x22, #8]\n" 383"lsl z22.b, z30.b, #0x4\n" 384"lsl z16.b, z29.b, #0x4\n" 385"and z30.b, z30.b, #0xf0\n" 386"and z29.b, z29.b, #0xf0\n" 387"ld1rd { z21.d }, p0/Z, [x22, #16]\n" 388"ld1rd { z20.d }, p0/Z, [x22, #24]\n" 389"lsl z19.b, z25.b, #0x4\n" 390"and z25.b, z25.b, #0xf0\n" 391"ld1rh { z17.h }, p0/Z, [x20]\n" 392"ld1h { z18.s }, p0/Z, [%x[b_ptr], #-1, MUL VL]\n" 393"sdot z28.s, z22.b, z26.b\n" 394"sdot z27.s, z16.b, z26.b\n" 395"lsl z16.b, z24.b, #0x4\n" 396"add x22, x22, #0x22\n" 397"and z24.b, z24.b, #0xf0\n" 398"add %x[b_ptr], %x[b_ptr], #0x90\n" 399"fcvt z17.s, p0/m, z17.h\n" 400"fcvt z18.s, p0/m, z18.h\n" 401"sdot z28.s, z19.b, z23.b\n" 402"sdot z27.s, z16.b, z23.b\n" 403"fmul z18.s, z18.s, z17.s\n" 404"sdot z28.s, z30.b, z21.b\n" 405"sdot z27.s, z29.b, z21.b\n" 406"sdot z28.s, z25.b, z20.b\n" 407"sdot z27.s, z24.b, z20.b\n" 408"uzp1 z17.s, z28.s, z27.s\n" 409"uzp2 z16.s, z28.s, z27.s\n" 410"add z17.s, z17.s, z16.s\n" 411"asr z17.s, z17.s, #0x4\n" 412"scvtf z17.s, p0/m, z17.s\n" 413"fmla z31.s, p0/M, z17.s, z18.s\n" 414"cbnz x21, 2b\n" 415"sub %x[nc], %x[nc], #0x8\n" 416"st1w { z31.s }, p0, [%x[res_ptr]]\n" 417"add %x[res_ptr], %x[res_ptr], #0x20\n" 418"cbnz %x[nc], 1b\n" 419 : [b_ptr ]"+&r" (b_ptr ), [res_ptr ]"+&r" (res_ptr ), [nc ]"+&r" (nc ) 420 : [a_ptr ]"r" (a_ptr ), [nb ]"r" (nb ) 421 :"memory" ,"p0" ,"x20" ,"x21" ,"x22" ,"z16" ,"z17" ,"z18" ,"z19" ,"z20" ,"z21" ,"z22" ,"z23" ,"z24" ,"z25" ,"z26" ,"z27" ,"z28" ,"z29" ,"z30" ,"z31" 422 ); 423return ; 424 } 425#endif // #if defined(__ARM_FEATURE_SVE) 426 427#endif // #if ! ((defined(_MSC_VER)) && ! defined(__clang__)) && defined(__aarch64__) 428ggml_gemv_q4_0_8x8_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 429} 430 431void ggml_gemv_iq4_nl_4x4_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 432const int qk = QK8_0 ; 433const int nb = n /qk ; 434const int ncols_interleaved = 4 ; 435const int blocklen = 4 ; 436 437assert (n %qk == 0 ); 438assert (nc %ncols_interleaved == 0 ); 439 440UNUSED (s ); 441UNUSED (bs ); 442UNUSED (vx ); 443UNUSED (vy ); 444UNUSED (nr ); 445UNUSED (nc ); 446UNUSED (nb ); 447UNUSED (ncols_interleaved ); 448UNUSED (blocklen ); 449 450#if ! ((defined(_MSC_VER ))&& ! defined(__clang__ ))&& defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 451const int8x16_t kvalues = vld1q_s8 (kvalues_iq4nl ); 452const block_q8_0 * a_ptr = (const block_q8_0 * )vy ; 453float * res_ptr = s ; 454 455for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 456const block_iq4_nlx4 * b_ptr = (const block_iq4_nlx4 * )vx + (x * nb ); 457 458float32x4_t sumf = vdupq_n_f32 (0 ); 459for (int l = 0 ;l < nb ;l ++ ) { 460uint8x16_t b_0 = vld1q_u8 (b_ptr [l ].qs + 0 ); 461uint8x16_t b_1 = vld1q_u8 (b_ptr [l ].qs + 16 ); 462uint8x16_t b_2 = vld1q_u8 (b_ptr [l ].qs + 32 ); 463uint8x16_t b_3 = vld1q_u8 (b_ptr [l ].qs + 48 ); 464 465int8x16_t b_0_hi = vqtbl1q_s8 (kvalues ,b_0 >>4 ); 466int8x16_t b_0_lo = vqtbl1q_s8 (kvalues ,b_0 & 0x0F ); 467int8x16_t b_1_hi = vqtbl1q_s8 (kvalues ,b_1 >>4 ); 468int8x16_t b_1_lo = vqtbl1q_s8 (kvalues ,b_1 & 0x0F ); 469int8x16_t b_2_hi = vqtbl1q_s8 (kvalues ,b_2 >>4 ); 470int8x16_t b_2_lo = vqtbl1q_s8 (kvalues ,b_2 & 0x0F ); 471int8x16_t b_3_hi = vqtbl1q_s8 (kvalues ,b_3 >>4 ); 472int8x16_t b_3_lo = vqtbl1q_s8 (kvalues ,b_3 & 0x0F ); 473 474int8x16_t a_0 = vld1q_s8 (a_ptr [l ].qs + 0 ); 475int8x16_t a_1 = vld1q_s8 (a_ptr [l ].qs + 16 ); 476 477int32x4_t sumi = vdupq_n_s32 (0 ); 478sumi = vdotq_laneq_s32 (sumi ,b_0_lo ,a_0 ,0 ); 479sumi = vdotq_laneq_s32 (sumi ,b_0_hi ,a_1 ,0 ); 480sumi = vdotq_laneq_s32 (sumi ,b_1_lo ,a_0 ,1 ); 481sumi = vdotq_laneq_s32 (sumi ,b_1_hi ,a_1 ,1 ); 482sumi = vdotq_laneq_s32 (sumi ,b_2_lo ,a_0 ,2 ); 483sumi = vdotq_laneq_s32 (sumi ,b_2_hi ,a_1 ,2 ); 484sumi = vdotq_laneq_s32 (sumi ,b_3_lo ,a_0 ,3 ); 485sumi = vdotq_laneq_s32 (sumi ,b_3_hi ,a_1 ,3 ); 486 487float32x4_t a_d = vcvt_f32_f16 (vld1_dup_f16 ((const float16_t * )& a_ptr [l ].d )); 488float32x4_t b_d = vcvt_f32_f16 (vld1_f16 ((const float16_t * )b_ptr [l ].d )); 489float32x4_t d = a_d * b_d ; 490 491sumf = vmlaq_f32 (sumf ,d ,vcvtq_f32_s32 (sumi )); 492 } 493 494vst1q_f32 (res_ptr + x * 4 ,sumf ); 495 } 496return ; 497#endif // #if ! ((defined(_MSC_VER)) && ! defined(__clang__)) && defined(__aarch64__) && defined(__ARM_NEON) 498ggml_gemv_iq4_nl_4x4_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 499} 500 501void ggml_gemv_mxfp4_4x4_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 502const int qk = QK8_0 ; 503const int nb = n /qk ; 504const int ncols_interleaved = 4 ; 505const int blocklen = 4 ; 506 507assert (n %qk == 0 ); 508assert (nc %ncols_interleaved == 0 ); 509 510UNUSED (s ); 511UNUSED (bs ); 512UNUSED (vx ); 513UNUSED (vy ); 514UNUSED (nr ); 515UNUSED (nc ); 516UNUSED (nb ); 517UNUSED (ncols_interleaved ); 518UNUSED (blocklen ); 519 520#if ! ((defined(_MSC_VER ))&& ! defined(__clang__ ))&& defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 521const int8x16_t kvalues = vld1q_s8 (kvalues_mxfp4 ); 522const block_q8_0 * a_ptr = (const block_q8_0 * )vy ; 523float * res_ptr = s ; 524 525for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 526const block_mxfp4x4 * b_ptr = (const block_mxfp4x4 * )vx + (x * nb ); 527 528float32x4_t sumf = vdupq_n_f32 (0 ); 529for (int l = 0 ;l < nb ;l ++ ) { 530uint8x16_t b_0 = vld1q_u8 (b_ptr [l ].qs + 0 ); 531uint8x16_t b_1 = vld1q_u8 (b_ptr [l ].qs + 16 ); 532uint8x16_t b_2 = vld1q_u8 (b_ptr [l ].qs + 32 ); 533uint8x16_t b_3 = vld1q_u8 (b_ptr [l ].qs + 48 ); 534 535int8x16_t b_0_hi = vqtbl1q_s8 (kvalues ,b_0 >>4 ); 536int8x16_t b_0_lo = vqtbl1q_s8 (kvalues ,b_0 & 0x0F ); 537int8x16_t b_1_hi = vqtbl1q_s8 (kvalues ,b_1 >>4 ); 538int8x16_t b_1_lo = vqtbl1q_s8 (kvalues ,b_1 & 0x0F ); 539int8x16_t b_2_hi = vqtbl1q_s8 (kvalues ,b_2 >>4 ); 540int8x16_t b_2_lo = vqtbl1q_s8 (kvalues ,b_2 & 0x0F ); 541int8x16_t b_3_hi = vqtbl1q_s8 (kvalues ,b_3 >>4 ); 542int8x16_t b_3_lo = vqtbl1q_s8 (kvalues ,b_3 & 0x0F ); 543 544int8x16_t a_0 = vld1q_s8 (a_ptr [l ].qs + 0 ); 545int8x16_t a_1 = vld1q_s8 (a_ptr [l ].qs + 16 ); 546 547int32x4_t sumi = vdupq_n_s32 (0 ); 548sumi = vdotq_laneq_s32 (sumi ,b_0_lo ,a_0 ,0 ); 549sumi = vdotq_laneq_s32 (sumi ,b_0_hi ,a_1 ,0 ); 550sumi = vdotq_laneq_s32 (sumi ,b_1_lo ,a_0 ,1 ); 551sumi = vdotq_laneq_s32 (sumi ,b_1_hi ,a_1 ,1 ); 552sumi = vdotq_laneq_s32 (sumi ,b_2_lo ,a_0 ,2 ); 553sumi = vdotq_laneq_s32 (sumi ,b_2_hi ,a_1 ,2 ); 554sumi = vdotq_laneq_s32 (sumi ,b_3_lo ,a_0 ,3 ); 555sumi = vdotq_laneq_s32 (sumi ,b_3_hi ,a_1 ,3 ); 556 557float32x4_t a_d = vcvt_f32_f16 (vld1_dup_f16 ((const float16_t * )& a_ptr [l ].d )); 558float32x4_t b_d = { 559GGML_CPU_E8M0_TO_FP32_HALF (b_ptr [l ].e [0 ]), 560GGML_CPU_E8M0_TO_FP32_HALF (b_ptr [l ].e [1 ]), 561GGML_CPU_E8M0_TO_FP32_HALF (b_ptr [l ].e [2 ]), 562GGML_CPU_E8M0_TO_FP32_HALF (b_ptr [l ].e [3 ]), 563 }; 564float32x4_t d = a_d * b_d ; 565 566sumf = vmlaq_f32 (sumf ,d ,vcvtq_f32_s32 (sumi )); 567 } 568 569vst1q_f32 (res_ptr + x * 4 ,sumf ); 570 } 571return ; 572#endif // #if ! ((defined(_MSC_VER)) && ! defined(__clang__)) && defined(__aarch64__) && defined(__ARM_NEON) 573ggml_gemv_mxfp4_4x4_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 574} 575 576void ggml_gemv_q4_K_8x4_q8_K (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 577constexpr int qk = QK_K ; 578const int nb = n /qk ; 579 580constexpr int ncols_interleaved = 8 ; 581constexpr int blocklen = 8 ; 582 583assert (n %qk == 0 ); 584assert (nc %ncols_interleaved == 0 ); 585 586UNUSED (nb ); 587UNUSED (ncols_interleaved ); 588UNUSED (blocklen ); 589 590#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 591constexpr int col_groups = ncols_interleaved /4 ;// 0123 and 4567 592const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 593 594// 1x8 tile = 2 x 4 595float32x4_t acc_f32 [col_groups ]; 596 597const block_q8_K * GGML_RESTRICT q8_ptr = (const block_q8_K * )vy ; 598 599for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 600const block_q4_Kx8 * GGML_RESTRICT q4_ptr = (const block_q4_Kx8 * )vx + (x * nb ); 601 602for (int i = 0 ;i < col_groups ;i ++ ) { 603acc_f32 [i ]= vdupq_n_f32 (0 ); 604 } 605 606for (int b = 0 ;b < nb ;b ++ ) { 607float32x4_t q4_d_0 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].d ));// d0 d1 d2 d3 608float32x4_t q4_d_1 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].d + 4 ));// d4 d5 d6 d7 609float32x4_t q8_d = vdupq_n_f32 (q8_ptr [b ].d ); 610float32x4_t sb_scale_0123 = vmulq_f32 (q4_d_0 ,q8_d ); 611float32x4_t sb_scale_4567 = vmulq_f32 (q4_d_1 ,q8_d ); 612float32x4_t q4_dmin_0 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].dmin ));// dmin 0..3 613float32x4_t q4_dmin_1 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].dmin + 4 ));// dmin 4..7 614float32x4_t sb_min_0123 = vmulq_f32 (q4_dmin_0 ,q8_d ); 615float32x4_t sb_min_4567 = vmulq_f32 (q4_dmin_1 ,q8_d ); 616 617// interleaved bias_acc: [0]->r0 0123, [1]->r0 4567 618int32x4_t bias_acc [2 ]= {vdupq_n_s32 (0 ),vdupq_n_s32 (0 ) }; 619int32x4_t acc_lo [col_groups ]; 620int32x4_t acc_hi [col_groups ]; 621 622// Each bsum is 16 elements, pairwise add leaves us with the 8 bsums of the entire block 623const int16x8_t bsums = vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums ),vld1q_s16 (q8_ptr [b ].bsums + 8 )); 624int16_t bsums_arr [8 ]; 625vst1q_s16 (bsums_arr ,bsums ); 626for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 627for (int i = 0 ;i < col_groups ;i ++ ) { 628acc_lo [i ]= vdupq_n_s32 (0 ); 629acc_hi [i ]= vdupq_n_s32 (0 ); 630 } 631// Need scales for the low and high nibbles 632// 2 * 12 = 24 bytes per subblock, 4 sbs -> 4 * 24 = 96 bytes total 633int16x8_t q4sb_mins [2 ]; 634int16x8_t q4sb_scales [2 ]; 635for (int i = 0 ;i < 2 ;i ++ ) { 636int8_t aux_q4sb [8 ]; 637const int offset = sb * 24 + i * 12 ; 638decode_q_Kx8_6bit_scales (& q4_ptr [b ].scales [offset ],& q4sb_mins [i ],aux_q4sb ); 639q4sb_scales [i ]= vmovl_s8 (vld1_s8 (aux_q4sb )); 640 } 641 642int8x16_t q8_qs [64 /16 ]; 643for (int i = 0 ;i < 64 /16 ;i ++ ) { 644q8_qs [i ]= vld1q_s8 (q8_ptr [b ].qs + sb * 64 + i * 16 ); 645 } 646 647for (int c = 0 ;c < col_groups ;c ++ ) { 648uint8x16_t q4_cols [8 ]; 649for (int i = 0 ;i < 8 ;i ++ ) { 650q4_cols [i ]= vld1q_u8 (q4_ptr [b ].qs + sb * QK_K + i * 32 + 16 * c ); 651 } 652 653acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],vreinterpretq_s8_u8 (vandq_u8 (q4_cols [0 ],m4b )),q8_qs [0 ],0 ); 654acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],vreinterpretq_s8_u8 (vandq_u8 (q4_cols [1 ],m4b )),q8_qs [0 ],1 ); 655acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],vreinterpretq_s8_u8 (vandq_u8 (q4_cols [2 ],m4b )),q8_qs [0 ],2 ); 656acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],vreinterpretq_s8_u8 (vandq_u8 (q4_cols [3 ],m4b )),q8_qs [0 ],3 ); 657acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],vreinterpretq_s8_u8 (vandq_u8 (q4_cols [4 ],m4b )),q8_qs [1 ],0 ); 658acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],vreinterpretq_s8_u8 (vandq_u8 (q4_cols [5 ],m4b )),q8_qs [1 ],1 ); 659acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],vreinterpretq_s8_u8 (vandq_u8 (q4_cols [6 ],m4b )),q8_qs [1 ],2 ); 660acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],vreinterpretq_s8_u8 (vandq_u8 (q4_cols [7 ],m4b )),q8_qs [1 ],3 ); 661 662acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_cols [0 ],4 )),q8_qs [2 ],0 ); 663acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_cols [1 ],4 )),q8_qs [2 ],1 ); 664acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_cols [2 ],4 )),q8_qs [2 ],2 ); 665acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_cols [3 ],4 )),q8_qs [2 ],3 ); 666acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_cols [4 ],4 )),q8_qs [3 ],0 ); 667acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_cols [5 ],4 )),q8_qs [3 ],1 ); 668acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_cols [6 ],4 )),q8_qs [3 ],2 ); 669acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_cols [7 ],4 )),q8_qs [3 ],3 ); 670 } 671 672// Scales 673// row c0123 blk0 and blk1 674const int16x4_t sc_0123_lo = vget_low_s16 (q4sb_scales [0 ]); 675const int16x4_t sc_0123_hi = vget_low_s16 (q4sb_scales [1 ]); 676const float32x4_t sumf_0123 = vcvtq_f32_s32 (vaddq_s32 (vmulq_s32 (vmovl_s16 (sc_0123_lo ),acc_lo [0 ]), 677vmulq_s32 (vmovl_s16 (sc_0123_hi ),acc_hi [0 ]))); 678acc_f32 [0 ]= vfmaq_f32 (acc_f32 [0 ],sb_scale_0123 ,sumf_0123 ); 679// row c4567 blk0 and blk1 680const int16x4_t sc_4567_lo = vget_high_s16 (q4sb_scales [0 ]); 681const int16x4_t sc_4567_hi = vget_high_s16 (q4sb_scales [1 ]); 682const float32x4_t sumf_4567 = vcvtq_f32_s32 (vaddq_s32 (vmulq_s32 (vmovl_s16 (sc_4567_lo ),acc_lo [1 ]), 683vmulq_s32 (vmovl_s16 (sc_4567_hi ),acc_hi [1 ]))); 684acc_f32 [1 ]= vfmaq_f32 (acc_f32 [1 ],sb_scale_4567 ,sumf_4567 ); 685 686// Bias Correction 687const int16x4_t bsums_vec_lo = vdup_n_s16 (bsums_arr [2 * sb + 0 ]); 688const int16x4_t bsums_vec_hi = vdup_n_s16 (bsums_arr [2 * sb + 1 ]); 689 690bias_acc [0 ]= vmlal_s16 (bias_acc [0 ],bsums_vec_lo ,vget_low_s16 (q4sb_mins [0 ])); 691bias_acc [0 ]= vmlal_s16 (bias_acc [0 ],bsums_vec_hi ,vget_low_s16 (q4sb_mins [1 ])); 692bias_acc [1 ]= vmlal_s16 (bias_acc [1 ],bsums_vec_lo ,vget_high_s16 (q4sb_mins [0 ])); 693bias_acc [1 ]= vmlal_s16 (bias_acc [1 ],bsums_vec_hi ,vget_high_s16 (q4sb_mins [1 ])); 694 }// for sb 695 696acc_f32 [0 ]= vmlsq_f32 (acc_f32 [0 ],vcvtq_f32_s32 (bias_acc [0 ]),sb_min_0123 ); 697acc_f32 [1 ]= vmlsq_f32 (acc_f32 [1 ],vcvtq_f32_s32 (bias_acc [1 ]),sb_min_4567 ); 698 }// for b 699 700int base = x * ncols_interleaved ; 701vst1q_f32 (s + base ,acc_f32 [0 ]); 702vst1q_f32 (s + base + 4 ,acc_f32 [1 ]); 703 }// for x 704return ; 705#endif // #if defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 706ggml_gemv_q4_K_8x4_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 707} 708 709void ggml_gemv_q4_K_8x8_q8_K (int n , 710float * GGML_RESTRICT s , 711size_t bs , 712const void * GGML_RESTRICT vx , 713const void * GGML_RESTRICT vy , 714int nr , 715int nc ) { 716constexpr int qk = QK_K ; 717const int nb = n /qk ; 718 719constexpr int ncols_interleaved = 8 ; 720constexpr int blocklen = 8 ; 721 722assert (n %qk == 0 ); 723assert (nc %ncols_interleaved == 0 ); 724 725UNUSED (nb ); 726UNUSED (ncols_interleaved ); 727UNUSED (blocklen ); 728 729#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 730constexpr int col_pairs = ncols_interleaved /2 ; 731const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 732 733// 1x8 tile = 2 x 4 734float32x4_t acc_f32 [ncols_interleaved /4 ]; 735 736const block_q8_K * GGML_RESTRICT q8_ptr = (const block_q8_K * )vy ; 737 738for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 739const block_q4_Kx8 * GGML_RESTRICT q4_ptr = (const block_q4_Kx8 * )vx + (x * nb ); 740 741for (int i = 0 ;i < ncols_interleaved /4 ;i ++ ) { 742acc_f32 [i ]= vdupq_n_f32 (0 ); 743 } 744 745for (int b = 0 ;b < nb ;b ++ ) { 746float32x4_t q4_d_0 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].d ));// d0 d1 d2 d3 747float32x4_t q4_d_1 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].d + 4 ));// d4 d5 d6 d7 748float32x4_t q8_d = vdupq_n_f32 (q8_ptr [b ].d ); 749float32x4_t sb_scale_0 = vmulq_f32 (q4_d_0 ,q8_d ); 750float32x4_t sb_scale_1 = vmulq_f32 (q4_d_1 ,q8_d ); 751float32x4_t q4_dmin_0 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].dmin ));// dmin 0..3 752float32x4_t q4_dmin_1 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].dmin + 4 ));// dmin 4..7 753float32x4_t sb_min_0 = vmulq_f32 (q4_dmin_0 ,q8_d ); 754float32x4_t sb_min_1 = vmulq_f32 (q4_dmin_1 ,q8_d ); 755 756// interleaved bias_acc: [0]->r0 0123, [1]->r0 4567 757int32x4_t bias_acc [2 ]= {vdupq_n_s32 (0 ),vdupq_n_s32 (0 ) }; 758// 2 sb each iteration 759int32x4_t acc_lo [col_pairs ]; 760int32x4_t acc_hi [col_pairs ]; 761 762// Each bsum is 16 elements, pairwise add leaves us with the 8 bsums of the entire block 763const int16x8_t bsums = vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums ),vld1q_s16 (q8_ptr [b ].bsums + 8 )); 764int16_t bsums_arr [8 ]; 765vst1q_s16 (bsums_arr ,bsums ); 766for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 767for (int i = 0 ;i < col_pairs ;i ++ ) { 768acc_lo [i ]= vdupq_n_s32 (0 ); 769acc_hi [i ]= vdupq_n_s32 (0 ); 770 } 771// Need scales for the low and high nibbles 772// 2 * 12 = 24 bytes per subblock, 4 sbs -> 4 * 24 = 96 bytes total 773int16x8_t q4sb_mins [2 ];// int16 as its needed for bias_acc later 774int16x8_t q4sb_scales [2 ]; 775for (int i = 0 ;i < 2 ;i ++ ) { 776int8_t aux_q4sb [8 ]; 777const int offset = sb * 24 + i * 12 ; 778decode_q_Kx8_6bit_scales (& q4_ptr [b ].scales [offset ],& q4sb_mins [i ],aux_q4sb ); 779q4sb_scales [i ]= vmovl_s8 (vld1_s8 (aux_q4sb )); 780 } 781 782const uint8_t * q4_base = q4_ptr [b ].qs + sb * QK_K ; 783 784// Load the 64 quants from q8K duplicated to use vecdots with the interleaved columns 785// but still need the qs to use the low and hi bits from q4 786const int8_t * q8_base = q8_ptr [b ].qs + sb * 64 ; 787int8x16_t q8_qs [8 ]; 788for (int i = 0 ;i < 8 ;i ++ ) { 789q8_qs [i ]= (int8x16_t )vld1q_dup_s64 ((const int64_t * ) (q8_base + i * 8 )); 790 } 791 792// Q4s columns iterated in pairs (01, 23, 45, 67) 793for (int cp = 0 ;cp < col_pairs ;cp ++ ) { 794uint8x16_t q4_qs_cp_0 = vld1q_u8 (q4_base + 16 * cp ); 795uint8x16_t q4_qs_cp_1 = vld1q_u8 (q4_base + 16 * cp + 64 ); 796uint8x16_t q4_qs_cp_2 = vld1q_u8 (q4_base + 16 * cp + 128 ); 797uint8x16_t q4_qs_cp_3 = vld1q_u8 (q4_base + 16 * cp + 192 ); 798 799acc_lo [cp ]= 800ggml_vdotq_s32 (acc_lo [cp ],vreinterpretq_s8_u8 (vandq_u8 (q4_qs_cp_0 ,m4b )),q8_qs [0 ]);// 0 .. 7 801acc_lo [cp ]= 802ggml_vdotq_s32 (acc_lo [cp ],vreinterpretq_s8_u8 (vandq_u8 (q4_qs_cp_1 ,m4b )),q8_qs [1 ]);// 8 ..15 803acc_lo [cp ]= 804ggml_vdotq_s32 (acc_lo [cp ],vreinterpretq_s8_u8 (vandq_u8 (q4_qs_cp_2 ,m4b )),q8_qs [2 ]);// 16..23 805acc_lo [cp ]= 806ggml_vdotq_s32 (acc_lo [cp ],vreinterpretq_s8_u8 (vandq_u8 (q4_qs_cp_3 ,m4b )),q8_qs [3 ]);// 24..31 807 808acc_hi [cp ]= 809ggml_vdotq_s32 (acc_hi [cp ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_qs_cp_0 ,4 )),q8_qs [4 ]);// 32..39 810acc_hi [cp ]= 811ggml_vdotq_s32 (acc_hi [cp ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_qs_cp_1 ,4 )),q8_qs [5 ]);// 40..47 812acc_hi [cp ]= 813ggml_vdotq_s32 (acc_hi [cp ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_qs_cp_2 ,4 )),q8_qs [6 ]);// 48..55 814acc_hi [cp ]= 815ggml_vdotq_s32 (acc_hi [cp ],vreinterpretq_s8_u8 (vshrq_n_u8 (q4_qs_cp_3 ,4 )),q8_qs [7 ]);// 56..63 816 } 817 818// Iterates over a pair of column pairs (4 columns) to use a single 128 register 819// p = 0 -> 0123 p2 -> 4567 820for (int i = 0 ,p = 0 ;p < col_pairs ;i ++ ,p += 2 ) { 821int16x4_t group_scales_lo = p == 0 ?vget_low_s16 (q4sb_scales [0 ]) :vget_high_s16 (q4sb_scales [0 ]); 822int16x4_t group_scales_hi = p == 0 ?vget_low_s16 (q4sb_scales [1 ]) :vget_high_s16 (q4sb_scales [1 ]); 823float32x4_t sb_scale = p == 0 ?sb_scale_0 :sb_scale_1 ; 824 825// 0123 or 4567 826float32x4_t sumf_0 = 827vcvtq_f32_s32 (vmulq_s32 (vmovl_s16 (group_scales_lo ),vpaddq_s32 (acc_lo [p ],acc_lo [p + 1 ]))); 828acc_f32 [i ]= vfmaq_f32 (acc_f32 [i ],sb_scale ,sumf_0 ); 829 830float32x4_t sumf_1 = 831vcvtq_f32_s32 (vmulq_s32 (vmovl_s16 (group_scales_hi ),vpaddq_s32 (acc_hi [p ],acc_hi [p + 1 ]))); 832acc_f32 [i ]= vfmaq_f32 (acc_f32 [i ],sb_scale ,sumf_1 ); 833 } 834 835// Multiply Acc bsum + mins 836// Each pair of subblocks share the same bsums 837// Load scalar bsum → broadcast to a vector (vdupq_n_s16(s)). 838int16x4_t bsums_vec_lo = vdup_n_s16 (bsums_arr [2 * sb + 0 ]); 839int16x4_t bsums_vec_hi = vdup_n_s16 (bsums_arr [2 * sb + 1 ]); 840 841// cols 0-3 bias 842bias_acc [0 ]= vmlal_s16 (bias_acc [0 ],bsums_vec_lo ,vget_low_s16 (q4sb_mins [0 ])); 843bias_acc [0 ]= vmlal_s16 (bias_acc [0 ],bsums_vec_hi ,vget_low_s16 (q4sb_mins [1 ])); 844 845// cols 4-7 bias 846bias_acc [1 ]= vmlal_s16 (bias_acc [1 ],bsums_vec_lo ,vget_high_s16 (q4sb_mins [0 ])); 847bias_acc [1 ]= vmlal_s16 (bias_acc [1 ],bsums_vec_hi ,vget_high_s16 (q4sb_mins [1 ])); 848 }// for sb 849 850acc_f32 [0 ]= vmlsq_f32 (acc_f32 [0 ],vcvtq_f32_s32 (bias_acc [0 ]),sb_min_0 ); 851acc_f32 [1 ]= vmlsq_f32 (acc_f32 [1 ],vcvtq_f32_s32 (bias_acc [1 ]),sb_min_1 ); 852 }// for b 853 854int base = x * ncols_interleaved ; 855vst1q_f32 (s + base ,acc_f32 [0 ]); 856vst1q_f32 (s + base + 4 ,acc_f32 [1 ]); 857 }// for x 858return ; 859#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 860ggml_gemv_q4_K_8x8_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 861} 862 863void ggml_gemv_q5_K_8x4_q8_K (int n , 864float * GGML_RESTRICT s , 865size_t bs , 866const void * GGML_RESTRICT vx , 867const void * GGML_RESTRICT vy , 868int nr , 869int nc ) { 870constexpr int qk = QK_K ; 871const int nb = n /qk ; 872 873constexpr int ncols_interleaved = 8 ; 874constexpr int blocklen = 4 ; 875 876assert (n %qk == 0 ); 877assert (nc %ncols_interleaved == 0 ); 878 879UNUSED (nb ); 880UNUSED (ncols_interleaved ); 881UNUSED (blocklen ); 882 883#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 884constexpr int col_groups = ncols_interleaved /4 ;// 0123 and 4567 885const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 886const uint8x16_t mone = vdupq_n_u8 (1 ); 887const uint8x16_t mtwo = vdupq_n_u8 (2 ); 888 889// 1x8 tile = 2 x 4 890float32x4_t acc_f32 [col_groups ]; 891 892const block_q8_K * GGML_RESTRICT q8_ptr = (const block_q8_K * )vy ; 893 894for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 895const block_q5_Kx8 * GGML_RESTRICT q5_ptr = (const block_q5_Kx8 * )vx + (x * nb ); 896 897for (int i = 0 ;i < col_groups ;i ++ ) { 898acc_f32 [i ]= vdupq_n_f32 (0 ); 899 } 900 901for (int b = 0 ;b < nb ;b ++ ) { 902float32x4_t q5_d_0 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].d ));// d0 d1 d2 d3 903float32x4_t q5_d_1 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].d + 4 ));// d4 d5 d6 d7 904float32x4_t q8_d = vdupq_n_f32 (q8_ptr [b ].d ); 905float32x4_t sb_scale_0123 = vmulq_f32 (q5_d_0 ,q8_d ); 906float32x4_t sb_scale_4567 = vmulq_f32 (q5_d_1 ,q8_d ); 907float32x4_t q5_dmin_0 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].dmin ));// dmin 0..3 908float32x4_t q5_dmin_1 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].dmin + 4 ));// dmin 4..7 909float32x4_t sb_min_0123 = vmulq_f32 (q5_dmin_0 ,q8_d ); 910float32x4_t sb_min_4567 = vmulq_f32 (q5_dmin_1 ,q8_d ); 911 912// interleaved bias_acc: [0]->r0 0123, [1]->r0 4567 913int32x4_t bias_acc [2 ]= {vdupq_n_s32 (0 ),vdupq_n_s32 (0 ) }; 914int32x4_t acc_lo [col_groups ]; 915int32x4_t acc_hi [col_groups ]; 916 917// Each bsum is 16 elements, pairwise add leaves us with the 8 bsums of the entire block 918const int16x8_t bsums = vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums ),vld1q_s16 (q8_ptr [b ].bsums + 8 )); 919int16_t bsums_arr [8 ]; 920vst1q_s16 (bsums_arr ,bsums ); 921 922uint8x16_t qh [col_groups ][8 ]; 923for (int c = 0 ;c < col_groups ;c ++ ) { 924for (int i = 0 ;i < 8 ;i ++ ) { 925qh [c ][i ]= vld1q_u8 (q5_ptr [b ].qh + i * 32 + 16 * c ); 926 } 927 } 928 929for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 930for (int i = 0 ;i < col_groups ;i ++ ) { 931acc_lo [i ]= vdupq_n_s32 (0 ); 932acc_hi [i ]= vdupq_n_s32 (0 ); 933 } 934// Need scales for the low and high nibbles 935// 2 * 12 = 24 bytes per subblock, 4 sbs -> 4 * 24 = 96 bytes total 936int16x8_t q5sb_mins [2 ]; 937int16x8_t q5sb_scales [2 ]; 938for (int i = 0 ;i < 2 ;i ++ ) { 939int8_t aux_q5sb [8 ]; 940const int offset = sb * 24 + i * 12 ; 941decode_q_Kx8_6bit_scales (& q5_ptr [b ].scales [offset ],& q5sb_mins [i ],aux_q5sb ); 942q5sb_scales [i ]= vmovl_s8 (vld1_s8 (aux_q5sb )); 943 } 944 945int8x16_t q8_qs [4 ]; 946for (int i = 0 ;i < 4 ;i ++ ) { 947q8_qs [i ]= vld1q_s8 (q8_ptr [b ].qs + sb * 64 + i * 16 ); 948 } 949 950for (int c = 0 ;c < col_groups ;c ++ ) { 951uint8x16_t q5_cols [8 ]; 952uint8x16_t hbit_lo [8 ]; 953uint8x16_t hbit_hi [8 ]; 954int8x16_t q5_lo [8 ]; 955int8x16_t q5_hi [8 ]; 956 957for (int i = 0 ;i < 8 ;i ++ ) { 958q5_cols [i ]= vld1q_u8 (q5_ptr [b ].qs + sb * QK_K + i * 32 + 16 * c ); 959hbit_lo [i ]= vandq_u8 (qh [c ][i ],mone ); 960hbit_hi [i ]= vshlq_n_u8 (vandq_u8 (qh [c ][i ],mtwo ),3 ); 961qh [c ][i ]= vshrq_n_u8 (qh [c ][i ],2 ); 962q5_lo [i ]= vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (q5_cols [i ],m4b ),hbit_lo [i ],4 )); 963q5_hi [i ]= vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (q5_cols [i ],4 ),hbit_hi [i ])); 964 } 965 966acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],q5_lo [0 ],q8_qs [0 ],0 ); 967acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],q5_lo [1 ],q8_qs [0 ],1 ); 968acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],q5_lo [2 ],q8_qs [0 ],2 ); 969acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],q5_lo [3 ],q8_qs [0 ],3 ); 970acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],q5_lo [4 ],q8_qs [1 ],0 ); 971acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],q5_lo [5 ],q8_qs [1 ],1 ); 972acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],q5_lo [6 ],q8_qs [1 ],2 ); 973acc_lo [c ]= vdotq_laneq_s32 (acc_lo [c ],q5_lo [7 ],q8_qs [1 ],3 ); 974 975acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],q5_hi [0 ],q8_qs [2 ],0 ); 976acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],q5_hi [1 ],q8_qs [2 ],1 ); 977acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],q5_hi [2 ],q8_qs [2 ],2 ); 978acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],q5_hi [3 ],q8_qs [2 ],3 ); 979acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],q5_hi [4 ],q8_qs [3 ],0 ); 980acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],q5_hi [5 ],q8_qs [3 ],1 ); 981acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],q5_hi [6 ],q8_qs [3 ],2 ); 982acc_hi [c ]= vdotq_laneq_s32 (acc_hi [c ],q5_hi [7 ],q8_qs [3 ],3 ); 983 } 984 985// Scales 986// row c0123 blk0 and blk1 987const int16x4_t sc_0123_lo = vget_low_s16 (q5sb_scales [0 ]); 988const int16x4_t sc_0123_hi = vget_low_s16 (q5sb_scales [1 ]); 989const float32x4_t sumf_0123 = vcvtq_f32_s32 (vaddq_s32 (vmulq_s32 (vmovl_s16 (sc_0123_lo ),acc_lo [0 ]), 990vmulq_s32 (vmovl_s16 (sc_0123_hi ),acc_hi [0 ]))); 991acc_f32 [0 ]= vfmaq_f32 (acc_f32 [0 ],sb_scale_0123 ,sumf_0123 ); 992// row c4567 blk0 and blk1 993const int16x4_t sc_4567_lo = vget_high_s16 (q5sb_scales [0 ]); 994const int16x4_t sc_4567_hi = vget_high_s16 (q5sb_scales [1 ]); 995const float32x4_t sumf_4567 = vcvtq_f32_s32 (vaddq_s32 (vmulq_s32 (vmovl_s16 (sc_4567_lo ),acc_lo [1 ]), 996vmulq_s32 (vmovl_s16 (sc_4567_hi ),acc_hi [1 ]))); 997acc_f32 [1 ]= vfmaq_f32 (acc_f32 [1 ],sb_scale_4567 ,sumf_4567 ); 998 999// Bias Correction 1000const int16x4_t bsums_vec_lo = vdup_n_s16 (bsums_arr [2 * sb + 0 ]); 1001const int16x4_t bsums_vec_hi = vdup_n_s16 (bsums_arr [2 * sb + 1 ]); 1002 1003bias_acc [0 ]= vmlal_s16 (bias_acc [0 ],bsums_vec_lo ,vget_low_s16 (q5sb_mins [0 ])); 1004bias_acc [0 ]= vmlal_s16 (bias_acc [0 ],bsums_vec_hi ,vget_low_s16 (q5sb_mins [1 ])); 1005bias_acc [1 ]= vmlal_s16 (bias_acc [1 ],bsums_vec_lo ,vget_high_s16 (q5sb_mins [0 ])); 1006bias_acc [1 ]= vmlal_s16 (bias_acc [1 ],bsums_vec_hi ,vget_high_s16 (q5sb_mins [1 ])); 1007 }// for sb 1008 1009acc_f32 [0 ]= vmlsq_f32 (acc_f32 [0 ],vcvtq_f32_s32 (bias_acc [0 ]),sb_min_0123 ); 1010acc_f32 [1 ]= vmlsq_f32 (acc_f32 [1 ],vcvtq_f32_s32 (bias_acc [1 ]),sb_min_4567 ); 1011 }// for b 1012 1013int base = x * ncols_interleaved ; 1014vst1q_f32 (s + base ,acc_f32 [0 ]); 1015vst1q_f32 (s + base + 4 ,acc_f32 [1 ]); 1016 }// for x 1017return ; 1018#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 1019ggml_gemv_q5_K_8x4_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 1020} 1021 1022void ggml_gemv_q5_K_8x8_q8_K (int n , 1023float * GGML_RESTRICT s , 1024size_t bs , 1025const void * GGML_RESTRICT vx , 1026const void * GGML_RESTRICT vy , 1027int nr , 1028int nc ) { 1029constexpr int qk = QK_K ; 1030const int nb = n /qk ; 1031 1032constexpr int ncols_interleaved = 8 ; 1033constexpr int blocklen = 8 ; 1034 1035assert (n %qk == 0 ); 1036assert (nc %ncols_interleaved == 0 ); 1037 1038UNUSED (nb ); 1039UNUSED (ncols_interleaved ); 1040UNUSED (blocklen ); 1041 1042#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 1043constexpr int col_pairs = ncols_interleaved /2 ; 1044const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 1045const uint8x16_t mone = vdupq_n_u8 (1 ); 1046const uint8x16_t mtwo = vdupq_n_u8 (2 ); 1047 1048// 1x8 tile = 2 x 4 1049float32x4_t acc_f32 [ncols_interleaved /4 ]; 1050 1051const block_q8_K * GGML_RESTRICT q8_ptr = (const block_q8_K * )vy ; 1052 1053for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 1054const block_q5_Kx8 * GGML_RESTRICT q5_ptr = (const block_q5_Kx8 * )vx + (x * nb ); 1055 1056for (int i = 0 ;i < ncols_interleaved /4 ;i ++ ) { 1057acc_f32 [i ]= vdupq_n_f32 (0 ); 1058 } 1059 1060for (int b = 0 ;b < nb ;b ++ ) { 1061float32x4_t q5_d_0 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].d ));// d0 d1 d2 d3 1062float32x4_t q5_d_1 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].d + 4 ));// d4 d5 d6 d7 1063float32x4_t q8_d = vdupq_n_f32 (q8_ptr [b ].d ); 1064float32x4_t sb_scale_0 = vmulq_f32 (q5_d_0 ,q8_d ); 1065float32x4_t sb_scale_1 = vmulq_f32 (q5_d_1 ,q8_d ); 1066float32x4_t q5_dmin_0 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].dmin ));// dmin 0..3 1067float32x4_t q5_dmin_1 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].dmin + 4 ));// dmin 4..7 1068float32x4_t sb_min_0 = vmulq_f32 (q5_dmin_0 ,q8_d ); 1069float32x4_t sb_min_1 = vmulq_f32 (q5_dmin_1 ,q8_d ); 1070 1071// 2 sb each iteration 1072int32x4_t acc_lo [col_pairs ]; 1073int32x4_t acc_hi [col_pairs ]; 1074 1075// Each bsum is 16 elements, pairwise add leaves us with the 8 bsums of the entire block 1076const int16x8_t bsums = vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums ),vld1q_s16 (q8_ptr [b ].bsums + 8 )); 1077int16_t bsums_arr [8 ]; 1078vst1q_s16 (bsums_arr ,bsums ); 1079 1080// Load qh once per block and shift after each subblock 1081const uint8_t * qh_base = q5_ptr [b ].qh ; 1082uint8x16_t qh [col_pairs ][4 ]; 1083for (int cp = 0 ;cp < col_pairs ;cp ++ ) { 1084qh [cp ][0 ]= vld1q_u8 (qh_base + 16 * cp ); 1085qh [cp ][1 ]= vld1q_u8 (qh_base + 16 * cp + 64 ); 1086qh [cp ][2 ]= vld1q_u8 (qh_base + 16 * cp + 128 ); 1087qh [cp ][3 ]= vld1q_u8 (qh_base + 16 * cp + 192 ); 1088 } 1089 1090for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 1091for (int i = 0 ;i < col_pairs ;i ++ ) { 1092acc_lo [i ]= vdupq_n_s32 (0 ); 1093acc_hi [i ]= vdupq_n_s32 (0 ); 1094 } 1095// Need scales for the low and high nibbles 1096// 2 * 12 = 24 bytes per subblock, 4 sbs -> 4 * 24 = 96 bytes total 1097int16x8_t q5sb_mins [2 ];// int16 as its needed for bias_acc later 1098int16x8_t q5sb_scales [2 ]; 1099for (int i = 0 ;i < 2 ;i ++ ) { 1100int8_t aux_q5sb [8 ]; 1101const int offset = sb * 24 + i * 12 ; 1102decode_q_Kx8_6bit_scales (& q5_ptr [b ].scales [offset ],& q5sb_mins [i ],aux_q5sb ); 1103q5sb_scales [i ]= vmovl_s8 (vld1_s8 (aux_q5sb )); 1104 } 1105 1106const uint8_t * qs_base = q5_ptr [b ].qs + sb * QK_K ; 1107 1108// Load the 64 quants from q8K duplicated to use vecdots with the interleaved columns 1109const int8_t * q8_base = q8_ptr [b ].qs + sb * 64 ; 1110int8x16_t q8_qs [8 ]; 1111for (int i = 0 ;i < 8 ;i ++ ) { 1112q8_qs [i ]= (int8x16_t )vld1q_dup_s64 ((const int64_t * ) (q8_base + i * 8 )); 1113 } 1114 1115// Q5s column pair loop unrolled 1116 { 1117// Cols 01 1118uint8x16_t qs_0 = vld1q_u8 (qs_base ); 1119uint8x16_t qs_1 = vld1q_u8 (qs_base + 64 ); 1120uint8x16_t qs_2 = vld1q_u8 (qs_base + 128 ); 1121uint8x16_t qs_3 = vld1q_u8 (qs_base + 192 ); 1122 1123uint8x16_t hbit_lo_0 = vandq_u8 (qh [0 ][0 ],mone ); 1124uint8x16_t hbit_lo_1 = vandq_u8 (qh [0 ][1 ],mone ); 1125uint8x16_t hbit_lo_2 = vandq_u8 (qh [0 ][2 ],mone ); 1126uint8x16_t hbit_lo_3 = vandq_u8 (qh [0 ][3 ],mone ); 1127uint8x16_t hbit_hi_0 = vshlq_n_u8 (vandq_u8 (qh [0 ][0 ],mtwo ),3 ); 1128uint8x16_t hbit_hi_1 = vshlq_n_u8 (vandq_u8 (qh [0 ][1 ],mtwo ),3 ); 1129uint8x16_t hbit_hi_2 = vshlq_n_u8 (vandq_u8 (qh [0 ][2 ],mtwo ),3 ); 1130uint8x16_t hbit_hi_3 = vshlq_n_u8 (vandq_u8 (qh [0 ][3 ],mtwo ),3 ); 1131 1132qh [0 ][0 ]= vshrq_n_u8 (qh [0 ][0 ],2 ); 1133qh [0 ][1 ]= vshrq_n_u8 (qh [0 ][1 ],2 ); 1134qh [0 ][2 ]= vshrq_n_u8 (qh [0 ][2 ],2 ); 1135qh [0 ][3 ]= vshrq_n_u8 (qh [0 ][3 ],2 ); 1136 1137acc_lo [0 ]= ggml_vdotq_s32 ( 1138acc_lo [0 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_0 ,m4b ),hbit_lo_0 ,4 )),q8_qs [0 ]); 1139acc_lo [0 ]= ggml_vdotq_s32 ( 1140acc_lo [0 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_1 ,m4b ),hbit_lo_1 ,4 )),q8_qs [1 ]); 1141acc_lo [0 ]= ggml_vdotq_s32 ( 1142acc_lo [0 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_2 ,m4b ),hbit_lo_2 ,4 )),q8_qs [2 ]); 1143acc_lo [0 ]= ggml_vdotq_s32 ( 1144acc_lo [0 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_3 ,m4b ),hbit_lo_3 ,4 )),q8_qs [3 ]); 1145acc_hi [0 ]= ggml_vdotq_s32 (acc_hi [0 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_0 ,4 ),hbit_hi_0 )), 1146q8_qs [4 ]); 1147acc_hi [0 ]= ggml_vdotq_s32 (acc_hi [0 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_1 ,4 ),hbit_hi_1 )), 1148q8_qs [5 ]); 1149acc_hi [0 ]= ggml_vdotq_s32 (acc_hi [0 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_2 ,4 ),hbit_hi_2 )), 1150q8_qs [6 ]); 1151acc_hi [0 ]= ggml_vdotq_s32 (acc_hi [0 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_3 ,4 ),hbit_hi_3 )), 1152q8_qs [7 ]); 1153 1154// Cols 23 1155qs_0 = vld1q_u8 (qs_base + 16 ); 1156qs_1 = vld1q_u8 (qs_base + 80 ); 1157qs_2 = vld1q_u8 (qs_base + 144 ); 1158qs_3 = vld1q_u8 (qs_base + 208 ); 1159 1160hbit_lo_0 = vandq_u8 (qh [1 ][0 ],mone ); 1161hbit_lo_1 = vandq_u8 (qh [1 ][1 ],mone ); 1162hbit_lo_2 = vandq_u8 (qh [1 ][2 ],mone ); 1163hbit_lo_3 = vandq_u8 (qh [1 ][3 ],mone ); 1164hbit_hi_0 = vshlq_n_u8 (vandq_u8 (qh [1 ][0 ],mtwo ),3 ); 1165hbit_hi_1 = vshlq_n_u8 (vandq_u8 (qh [1 ][1 ],mtwo ),3 ); 1166hbit_hi_2 = vshlq_n_u8 (vandq_u8 (qh [1 ][2 ],mtwo ),3 ); 1167hbit_hi_3 = vshlq_n_u8 (vandq_u8 (qh [1 ][3 ],mtwo ),3 ); 1168 1169qh [1 ][0 ]= vshrq_n_u8 (qh [1 ][0 ],2 ); 1170qh [1 ][1 ]= vshrq_n_u8 (qh [1 ][1 ],2 ); 1171qh [1 ][2 ]= vshrq_n_u8 (qh [1 ][2 ],2 ); 1172qh [1 ][3 ]= vshrq_n_u8 (qh [1 ][3 ],2 ); 1173 1174acc_lo [1 ]= ggml_vdotq_s32 ( 1175acc_lo [1 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_0 ,m4b ),hbit_lo_0 ,4 )),q8_qs [0 ]); 1176acc_lo [1 ]= ggml_vdotq_s32 ( 1177acc_lo [1 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_1 ,m4b ),hbit_lo_1 ,4 )),q8_qs [1 ]); 1178acc_lo [1 ]= ggml_vdotq_s32 ( 1179acc_lo [1 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_2 ,m4b ),hbit_lo_2 ,4 )),q8_qs [2 ]); 1180acc_lo [1 ]= ggml_vdotq_s32 ( 1181acc_lo [1 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_3 ,m4b ),hbit_lo_3 ,4 )),q8_qs [3 ]); 1182acc_hi [1 ]= ggml_vdotq_s32 (acc_hi [1 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_0 ,4 ),hbit_hi_0 )), 1183q8_qs [4 ]); 1184acc_hi [1 ]= ggml_vdotq_s32 (acc_hi [1 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_1 ,4 ),hbit_hi_1 )), 1185q8_qs [5 ]); 1186acc_hi [1 ]= ggml_vdotq_s32 (acc_hi [1 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_2 ,4 ),hbit_hi_2 )), 1187q8_qs [6 ]); 1188acc_hi [1 ]= ggml_vdotq_s32 (acc_hi [1 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_3 ,4 ),hbit_hi_3 )), 1189q8_qs [7 ]); 1190 1191// Cols 45 1192qs_0 = vld1q_u8 (qs_base + 32 ); 1193qs_1 = vld1q_u8 (qs_base + 96 ); 1194qs_2 = vld1q_u8 (qs_base + 160 ); 1195qs_3 = vld1q_u8 (qs_base + 224 ); 1196 1197hbit_lo_0 = vandq_u8 (qh [2 ][0 ],mone ); 1198hbit_lo_1 = vandq_u8 (qh [2 ][1 ],mone ); 1199hbit_lo_2 = vandq_u8 (qh [2 ][2 ],mone ); 1200hbit_lo_3 = vandq_u8 (qh [2 ][3 ],mone ); 1201hbit_hi_0 = vshlq_n_u8 (vandq_u8 (qh [2 ][0 ],mtwo ),3 ); 1202hbit_hi_1 = vshlq_n_u8 (vandq_u8 (qh [2 ][1 ],mtwo ),3 ); 1203hbit_hi_2 = vshlq_n_u8 (vandq_u8 (qh [2 ][2 ],mtwo ),3 ); 1204hbit_hi_3 = vshlq_n_u8 (vandq_u8 (qh [2 ][3 ],mtwo ),3 ); 1205 1206qh [2 ][0 ]= vshrq_n_u8 (qh [2 ][0 ],2 ); 1207qh [2 ][1 ]= vshrq_n_u8 (qh [2 ][1 ],2 ); 1208qh [2 ][2 ]= vshrq_n_u8 (qh [2 ][2 ],2 ); 1209qh [2 ][3 ]= vshrq_n_u8 (qh [2 ][3 ],2 ); 1210 1211acc_lo [2 ]= ggml_vdotq_s32 ( 1212acc_lo [2 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_0 ,m4b ),hbit_lo_0 ,4 )),q8_qs [0 ]); 1213acc_lo [2 ]= ggml_vdotq_s32 ( 1214acc_lo [2 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_1 ,m4b ),hbit_lo_1 ,4 )),q8_qs [1 ]); 1215acc_lo [2 ]= ggml_vdotq_s32 ( 1216acc_lo [2 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_2 ,m4b ),hbit_lo_2 ,4 )),q8_qs [2 ]); 1217acc_lo [2 ]= ggml_vdotq_s32 ( 1218acc_lo [2 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_3 ,m4b ),hbit_lo_3 ,4 )),q8_qs [3 ]); 1219acc_hi [2 ]= ggml_vdotq_s32 (acc_hi [2 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_0 ,4 ),hbit_hi_0 )), 1220q8_qs [4 ]); 1221acc_hi [2 ]= ggml_vdotq_s32 (acc_hi [2 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_1 ,4 ),hbit_hi_1 )), 1222q8_qs [5 ]); 1223acc_hi [2 ]= ggml_vdotq_s32 (acc_hi [2 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_2 ,4 ),hbit_hi_2 )), 1224q8_qs [6 ]); 1225acc_hi [2 ]= ggml_vdotq_s32 (acc_hi [2 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_3 ,4 ),hbit_hi_3 )), 1226q8_qs [7 ]); 1227 1228// Cols 45 1229qs_0 = vld1q_u8 (qs_base + 48 ); 1230qs_1 = vld1q_u8 (qs_base + 112 ); 1231qs_2 = vld1q_u8 (qs_base + 176 ); 1232qs_3 = vld1q_u8 (qs_base + 240 ); 1233 1234hbit_lo_0 = vandq_u8 (qh [3 ][0 ],mone ); 1235hbit_lo_1 = vandq_u8 (qh [3 ][1 ],mone ); 1236hbit_lo_2 = vandq_u8 (qh [3 ][2 ],mone ); 1237hbit_lo_3 = vandq_u8 (qh [3 ][3 ],mone ); 1238hbit_hi_0 = vshlq_n_u8 (vandq_u8 (qh [3 ][0 ],mtwo ),3 ); 1239hbit_hi_1 = vshlq_n_u8 (vandq_u8 (qh [3 ][1 ],mtwo ),3 ); 1240hbit_hi_2 = vshlq_n_u8 (vandq_u8 (qh [3 ][2 ],mtwo ),3 ); 1241hbit_hi_3 = vshlq_n_u8 (vandq_u8 (qh [3 ][3 ],mtwo ),3 ); 1242 1243qh [3 ][0 ]= vshrq_n_u8 (qh [3 ][0 ],2 ); 1244qh [3 ][1 ]= vshrq_n_u8 (qh [3 ][1 ],2 ); 1245qh [3 ][2 ]= vshrq_n_u8 (qh [3 ][2 ],2 ); 1246qh [3 ][3 ]= vshrq_n_u8 (qh [3 ][3 ],2 ); 1247 1248acc_lo [3 ]= ggml_vdotq_s32 ( 1249acc_lo [3 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_0 ,m4b ),hbit_lo_0 ,4 )),q8_qs [0 ]); 1250acc_lo [3 ]= ggml_vdotq_s32 ( 1251acc_lo [3 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_1 ,m4b ),hbit_lo_1 ,4 )),q8_qs [1 ]); 1252acc_lo [3 ]= ggml_vdotq_s32 ( 1253acc_lo [3 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_2 ,m4b ),hbit_lo_2 ,4 )),q8_qs [2 ]); 1254acc_lo [3 ]= ggml_vdotq_s32 ( 1255acc_lo [3 ],vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_3 ,m4b ),hbit_lo_3 ,4 )),q8_qs [3 ]); 1256acc_hi [3 ]= ggml_vdotq_s32 (acc_hi [3 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_0 ,4 ),hbit_hi_0 )), 1257q8_qs [4 ]); 1258acc_hi [3 ]= ggml_vdotq_s32 (acc_hi [3 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_1 ,4 ),hbit_hi_1 )), 1259q8_qs [5 ]); 1260acc_hi [3 ]= ggml_vdotq_s32 (acc_hi [3 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_2 ,4 ),hbit_hi_2 )), 1261q8_qs [6 ]); 1262acc_hi [3 ]= ggml_vdotq_s32 (acc_hi [3 ],vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_3 ,4 ),hbit_hi_3 )), 1263q8_qs [7 ]); 1264 } 1265 1266// Prepare bsum vectors for bias computation 1267// Each pair of subblocks share the same bsums 1268int16x4_t bsums_vec_lo = vdup_n_s16 (bsums_arr [2 * sb + 0 ]); 1269int16x4_t bsums_vec_hi = vdup_n_s16 (bsums_arr [2 * sb + 1 ]); 1270 1271// Iterates over a pair of column pairs (4 columns) to use a single 128 register 1272// p = 0 -> 0123 p2 -> 4567 1273for (int i = 0 ,p = 0 ;p < col_pairs ;i ++ ,p += 2 ) { 1274int16x4_t group_scales_lo = p == 0 ?vget_low_s16 (q5sb_scales [0 ]) :vget_high_s16 (q5sb_scales [0 ]); 1275int16x4_t group_scales_hi = p == 0 ?vget_low_s16 (q5sb_scales [1 ]) :vget_high_s16 (q5sb_scales [1 ]); 1276int16x4_t group_mins_lo = p == 0 ?vget_low_s16 (q5sb_mins [0 ]) :vget_high_s16 (q5sb_mins [0 ]); 1277int16x4_t group_mins_hi = p == 0 ?vget_low_s16 (q5sb_mins [1 ]) :vget_high_s16 (q5sb_mins [1 ]); 1278float32x4_t sb_scale = p == 0 ?sb_scale_0 :sb_scale_1 ; 1279float32x4_t sb_min = p == 0 ?sb_min_0 :sb_min_1 ; 1280 1281// 0123 or 4567 1282float32x4_t sumf_0 = 1283vcvtq_f32_s32 (vmulq_s32 (vmovl_s16 (group_scales_lo ),vpaddq_s32 (acc_lo [p ],acc_lo [p + 1 ]))); 1284acc_f32 [i ]= vfmaq_f32 (acc_f32 [i ],sb_scale ,sumf_0 ); 1285 1286float32x4_t sumf_1 = 1287vcvtq_f32_s32 (vmulq_s32 (vmovl_s16 (group_scales_hi ),vpaddq_s32 (acc_hi [p ],acc_hi [p + 1 ]))); 1288acc_f32 [i ]= vfmaq_f32 (acc_f32 [i ],sb_scale ,sumf_1 ); 1289 1290// FUSED BIAS: Compute and subtract bias immediately 1291// bias = (bsums_lo * mins_lo + bsums_hi * mins_hi) * sb_min 1292int32x4_t bias = vmull_s16 (bsums_vec_lo ,group_mins_lo ); 1293bias = vmlal_s16 (bias ,bsums_vec_hi ,group_mins_hi ); 1294float32x4_t bias_f32 = vcvtq_f32_s32 (bias ); 1295acc_f32 [i ]= vmlsq_f32 (acc_f32 [i ],sb_min ,bias_f32 ); 1296 } 1297 }// for sb 1298 }// for b 1299 1300int base = x * ncols_interleaved ; 1301vst1q_f32 (s + base ,acc_f32 [0 ]); 1302vst1q_f32 (s + base + 4 ,acc_f32 [1 ]); 1303 }// for x 1304return ; 1305#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 1306ggml_gemv_q5_K_8x8_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 1307} 1308 1309void ggml_gemv_q6_K_8x4_q8_K (int n , 1310float * GGML_RESTRICT s , 1311size_t bs , 1312const void * GGML_RESTRICT vx , 1313const void * GGML_RESTRICT vy , 1314int nr , 1315int nc ) { 1316constexpr int qk = QK_K ; 1317const int nb = n /qk ; 1318 1319constexpr int ncols_interleaved = 8 ; 1320constexpr int blocklen = 4 ; 1321 1322assert (n %qk == 0 ); 1323assert (nc %ncols_interleaved == 0 ); 1324 1325UNUSED (nb ); 1326UNUSED (ncols_interleaved ); 1327UNUSED (blocklen ); 1328 1329#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 1330constexpr int col_groups = ncols_interleaved /4 ; 1331const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 1332const uint8x16_t mask_lo = vdupq_n_u8 (0x03 ); 1333const uint8x16_t mask_hi = vdupq_n_u8 (0x30 ); 1334 1335// 1x8 tile = 2 x 4 1336float32x4_t acc_f32 [2 ]; 1337 1338const block_q8_K * GGML_RESTRICT q8_ptr = (const block_q8_K * )vy ; 1339 1340for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 1341const block_q6_Kx8 * GGML_RESTRICT q6_ptr = (const block_q6_Kx8 * )vx + (x * nb ); 1342 1343for (int i = 0 ;i < col_groups ;i ++ ) { 1344acc_f32 [i ]= vdupq_n_f32 (0 ); 1345 } 1346 1347for (int b = 0 ;b < nb ;b ++ ) { 1348float32x4_t q6_d_0 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q6_ptr [b ].d ));// d0 d1 d2 d3 1349float32x4_t q6_d_1 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q6_ptr [b ].d + 4 ));// d4 d5 d6 d7 1350float32x4_t q8_d = vdupq_n_f32 (q8_ptr [b ].d ); 1351float32x4_t sb_scale_0 = vmulq_f32 (q6_d_0 ,q8_d ); 1352float32x4_t sb_scale_1 = vmulq_f32 (q6_d_1 ,q8_d ); 1353 1354int32x4_t acc [col_groups ]; 1355for (int i = 0 ;i < col_groups ;i ++ ) { 1356acc [i ]= vdupq_n_s32 (0 ); 1357 } 1358 1359// Load all 16 scales once and widen to int16 (Q6_K has 16 scales per block) 1360// Reused for bias and dequantization later 1361int16_t q6_scales [16 * 8 ]; 1362for (int i = 0 ;i < 16 ;i ++ ) { 1363int16x8_t scales = vmovl_s8 (vld1_s8 (q6_ptr [b ].scales + i * 8 )); 1364vst1q_s16 (q6_scales + i * 8 ,scales ); 1365 } 1366 1367// Compute bias per column using q8 bsums and preloaded scales to skip the -32 shift 1368int32x4_t bias_lo = vdupq_n_s32 (0 ); 1369int32x4_t bias_hi = vdupq_n_s32 (0 ); 1370 1371// Load bsums in chunks of 4 to process with vectorized operations 1372for (int i = 0 ;i < 16 ;i += 4 ) { 1373int16x4_t bsums_vec = vld1_s16 (q8_ptr [b ].bsums + i ); 1374int16x4_t scales_lo_0 = vld1_s16 (q6_scales + (i + 0 )* 8 ); 1375int16x4_t scales_hi_0 = vld1_s16 (q6_scales + (i + 0 )* 8 + 4 ); 1376int16x4_t scales_lo_1 = vld1_s16 (q6_scales + (i + 1 )* 8 ); 1377int16x4_t scales_hi_1 = vld1_s16 (q6_scales + (i + 1 )* 8 + 4 ); 1378int16x4_t scales_lo_2 = vld1_s16 (q6_scales + (i + 2 )* 8 ); 1379int16x4_t scales_hi_2 = vld1_s16 (q6_scales + (i + 2 )* 8 + 4 ); 1380int16x4_t scales_lo_3 = vld1_s16 (q6_scales + (i + 3 )* 8 ); 1381int16x4_t scales_hi_3 = vld1_s16 (q6_scales + (i + 3 )* 8 + 4 ); 1382 1383bias_lo = vmlal_lane_s16 (bias_lo ,scales_lo_0 ,bsums_vec ,0 ); 1384bias_hi = vmlal_lane_s16 (bias_hi ,scales_hi_0 ,bsums_vec ,0 ); 1385bias_lo = vmlal_lane_s16 (bias_lo ,scales_lo_1 ,bsums_vec ,1 ); 1386bias_hi = vmlal_lane_s16 (bias_hi ,scales_hi_1 ,bsums_vec ,1 ); 1387bias_lo = vmlal_lane_s16 (bias_lo ,scales_lo_2 ,bsums_vec ,2 ); 1388bias_hi = vmlal_lane_s16 (bias_hi ,scales_hi_2 ,bsums_vec ,2 ); 1389bias_lo = vmlal_lane_s16 (bias_lo ,scales_lo_3 ,bsums_vec ,3 ); 1390bias_hi = vmlal_lane_s16 (bias_hi ,scales_hi_3 ,bsums_vec ,3 ); 1391 } 1392bias_lo = vshlq_n_s32 (bias_lo ,5 ); 1393bias_hi = vshlq_n_s32 (bias_hi ,5 ); 1394 1395// Process two 128-value halves per superblock 1396for (int half = 0 ;half < 2 ;half ++ ) { 1397const uint8_t * ql_base = q6_ptr [b ].ql + half * 512 ; 1398const uint8_t * qh_base = q6_ptr [b ].qh + half * 256 ; 1399 1400// A subblock (sb) is a set of weights that share the scale 1401// Since q6_K scales are per 16 elements 1402// num sbs -> 256 elements / (16 elements/scale * 2 elements/byte * 2 halves) 1403for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 1404const int8_t * q8_base_l = q8_ptr [b ].qs + half * 128 + sb * 16 ; 1405const int8_t * q8_base_h = q8_base_l + 64 ; 1406 1407// Load and duplicate q8 values (each register covers four interleaved columns of q6) 1408int8x16_t q8_l [4 ]; 1409int8x16_t q8_h [4 ]; 1410for (int i = 0 ;i < 4 ;i ++ ) { 1411q8_l [i ]= (int8x16_t )vld1q_dup_s32 ((const int32_t * ) (q8_base_l + i * 4 )); 1412q8_h [i ]= (int8x16_t )vld1q_dup_s32 ((const int32_t * ) (q8_base_h + i * 4 )); 1413 } 1414 1415const int ql_off_base = sb * QK_K /2 ; 1416const int qh_off_base = ql_off_base & 255 ;// wraps after 256 bytes 1417 1418// Load 4 vectors at once (64 bytes each for ql_0, ql_1, qh_0, qh_1) 1419uint8x16x4_t q6_ql_0 = vld1q_u8_x4 (ql_base + ql_off_base ); 1420uint8x16x4_t q6_ql_1 = vld1q_u8_x4 (ql_base + ql_off_base + 64 ); 1421uint8x16x4_t q6_qh_0 = vld1q_u8_x4 (qh_base + qh_off_base ); 1422uint8x16x4_t q6_qh_1 = vld1q_u8_x4 (qh_base + qh_off_base + 64 ); 1423 1424// Adjust qh for subblocks 2 and 3 (shift right by 2) 1425if (sb > 1 ) { 1426q6_qh_0 .val [0 ]= vshrq_n_u8 (q6_qh_0 .val [0 ],2 ); 1427q6_qh_0 .val [1 ]= vshrq_n_u8 (q6_qh_0 .val [1 ],2 ); 1428q6_qh_0 .val [2 ]= vshrq_n_u8 (q6_qh_0 .val [2 ],2 ); 1429q6_qh_0 .val [3 ]= vshrq_n_u8 (q6_qh_0 .val [3 ],2 ); 1430q6_qh_1 .val [0 ]= vshrq_n_u8 (q6_qh_1 .val [0 ],2 ); 1431q6_qh_1 .val [1 ]= vshrq_n_u8 (q6_qh_1 .val [1 ],2 ); 1432q6_qh_1 .val [2 ]= vshrq_n_u8 (q6_qh_1 .val [2 ],2 ); 1433q6_qh_1 .val [3 ]= vshrq_n_u8 (q6_qh_1 .val [3 ],2 ); 1434 } 1435 1436const uint8x16_t q6_ql [8 ]= {q6_ql_0 .val [0 ],q6_ql_0 .val [1 ],q6_ql_0 .val [2 ],q6_ql_0 .val [3 ], 1437q6_ql_1 .val [0 ],q6_ql_1 .val [1 ],q6_ql_1 .val [2 ],q6_ql_1 .val [3 ] }; 1438const uint8x16_t q6_qh [8 ]= {q6_qh_0 .val [0 ],q6_qh_0 .val [1 ],q6_qh_0 .val [2 ],q6_qh_0 .val [3 ], 1439q6_qh_1 .val [0 ],q6_qh_1 .val [1 ],q6_qh_1 .val [2 ],q6_qh_1 .val [3 ] }; 1440 1441// Process column groups (0-3, 4-7) 1442for (int g = 0 ;g < col_groups ;g ++ ) { 1443int32x4_t sb_acc_l = vdupq_n_s32 (0 ); 1444int32x4_t sb_acc_h = vdupq_n_s32 (0 ); 1445 1446for (int chunk = 0 ;chunk < 4 ;chunk ++ ) { 1447const int idx = chunk * 2 + g ; 1448 1449const uint8x16_t q6_qs_l = q6_ql [idx ]; 1450const uint8x16_t q6_qs_h = q6_qh [idx ]; 1451 1452// Extract high 2 bits for upper nibble reconstruction 1453const uint8x16_t q6_qs_hh = vandq_u8 (q6_qs_h ,mask_hi ); 1454 1455// q6 = (low4 | high2<<4), without -32 bias (handled via bsums) 1456const int8x16_t q6_l = 1457vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (q6_qs_l ,m4b ),vandq_u8 (q6_qs_h ,mask_lo ),4 )); 1458const int8x16_t q6_h = vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (q6_qs_l ,4 ),q6_qs_hh )); 1459 1460sb_acc_l = vdotq_s32 (sb_acc_l ,q6_l ,q8_l [chunk ]); 1461sb_acc_h = vdotq_s32 (sb_acc_h ,q6_h ,q8_h [chunk ]); 1462 } 1463 1464const int scale_idx_l = half * 8 + sb ; 1465const int scale_idx_h = half * 8 + sb + 4 ; 1466 1467const int32x4_t scale_vec_l = vmovl_s16 (vld1_s16 (q6_scales + scale_idx_l * 8 + g * 4 )); 1468const int32x4_t scale_vec_h = vmovl_s16 (vld1_s16 (q6_scales + scale_idx_h * 8 + g * 4 )); 1469 1470acc [g ]= vmlaq_s32 (acc [g ],sb_acc_l ,scale_vec_l ); 1471acc [g ]= vmlaq_s32 (acc [g ],sb_acc_h ,scale_vec_h ); 1472 } 1473 } 1474 }// for half 1475 1476// Bias correction 1477acc [0 ]= vsubq_s32 (acc [0 ],bias_lo ); 1478acc [1 ]= vsubq_s32 (acc [1 ],bias_hi ); 1479 1480// Apply superblock scale (no mins for q6_K) 1481// acc[g] has [c0, c1, c2, c3] 1482float32x4_t w_0123 = vmulq_f32 (vcvtq_f32_s32 (acc [0 ]),sb_scale_0 ); 1483float32x4_t w_4567 = vmulq_f32 (vcvtq_f32_s32 (acc [1 ]),sb_scale_1 ); 1484 1485acc_f32 [0 ]= vaddq_f32 (acc_f32 [0 ],w_0123 ); 1486acc_f32 [1 ]= vaddq_f32 (acc_f32 [1 ],w_4567 ); 1487 }// for b 1488 1489int base = x * ncols_interleaved ; 1490vst1q_f32 (s + base ,acc_f32 [0 ]); 1491vst1q_f32 (s + base + 4 ,acc_f32 [1 ]); 1492 }// for x 1493return ; 1494#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 1495ggml_gemv_q6_K_8x4_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 1496} 1497 1498void ggml_gemv_q6_K_8x8_q8_K (int n , 1499float * GGML_RESTRICT s , 1500size_t bs , 1501const void * GGML_RESTRICT vx , 1502const void * GGML_RESTRICT vy , 1503int nr , 1504int nc ) { 1505constexpr int qk = QK_K ; 1506const int nb = n /qk ; 1507 1508constexpr int ncols_interleaved = 8 ; 1509constexpr int blocklen = 8 ; 1510 1511assert (n %qk == 0 ); 1512assert (nc %ncols_interleaved == 0 ); 1513 1514UNUSED (nb ); 1515UNUSED (ncols_interleaved ); 1516UNUSED (blocklen ); 1517 1518#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 1519constexpr int col_pairs = ncols_interleaved /2 ; 1520const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 1521const uint8x16_t mask_lo = vdupq_n_u8 (0x03 ); 1522const uint8x16_t mask_hi = vdupq_n_u8 (0x30 ); 1523 1524// 1x8 tile = 2 x 4 1525float32x4_t acc_f32 [2 ]; 1526 1527const block_q8_K * GGML_RESTRICT q8_ptr = (const block_q8_K * )vy ; 1528 1529for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 1530const block_q6_Kx8 * GGML_RESTRICT q6_ptr = (const block_q6_Kx8 * )vx + (x * nb ); 1531 1532acc_f32 [0 ]= vdupq_n_f32 (0 ); 1533acc_f32 [1 ]= vdupq_n_f32 (0 ); 1534 1535for (int b = 0 ;b < nb ;b ++ ) { 1536float32x4_t q6_d_0 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q6_ptr [b ].d ));// d0 d1 d2 d3 1537float32x4_t q6_d_1 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q6_ptr [b ].d + 4 ));// d4 d5 d6 d7 1538float32x4_t q8_d = vdupq_n_f32 (q8_ptr [b ].d ); 1539float32x4_t sb_scale_0 = vmulq_f32 (q6_d_0 ,q8_d ); 1540float32x4_t sb_scale_1 = vmulq_f32 (q6_d_1 ,q8_d ); 1541 1542int32x2_t acc [col_pairs ]; 1543for (int i = 0 ;i < col_pairs ;i ++ ) { 1544acc [i ]= vdup_n_s32 (0 ); 1545 } 1546 1547// Load all 16 scales once and widen to int16 (Q6_K has 16 scales per block) 1548// Reused for bias and dequantization later 1549int16_t q6_scales [16 * 8 ]; 1550for (int i = 0 ;i < 16 ;i ++ ) { 1551int16x8_t scales = vmovl_s8 (vld1_s8 (q6_ptr [b ].scales + i * 8 )); 1552vst1q_s16 (q6_scales + i * 8 ,scales ); 1553 } 1554 1555// Compute bias per column using q8 bsums and preloaded scales to skip the -32 shift 1556int32x4_t bias_lo = vdupq_n_s32 (0 ); 1557int32x4_t bias_hi = vdupq_n_s32 (0 ); 1558 1559// Load bsums in chunks of 4 to process with vectorized operations 1560for (int i = 0 ;i < 16 ;i += 4 ) { 1561int16x4_t bsums_vec = vld1_s16 (q8_ptr [b ].bsums + i ); 1562int16x4_t scales_lo_0 = vld1_s16 (q6_scales + (i + 0 )* 8 ); 1563int16x4_t scales_hi_0 = vld1_s16 (q6_scales + (i + 0 )* 8 + 4 ); 1564int16x4_t scales_lo_1 = vld1_s16 (q6_scales + (i + 1 )* 8 ); 1565int16x4_t scales_hi_1 = vld1_s16 (q6_scales + (i + 1 )* 8 + 4 ); 1566int16x4_t scales_lo_2 = vld1_s16 (q6_scales + (i + 2 )* 8 ); 1567int16x4_t scales_hi_2 = vld1_s16 (q6_scales + (i + 2 )* 8 + 4 ); 1568int16x4_t scales_lo_3 = vld1_s16 (q6_scales + (i + 3 )* 8 ); 1569int16x4_t scales_hi_3 = vld1_s16 (q6_scales + (i + 3 )* 8 + 4 ); 1570 1571bias_lo = vmlal_lane_s16 (bias_lo ,scales_lo_0 ,bsums_vec ,0 ); 1572bias_hi = vmlal_lane_s16 (bias_hi ,scales_hi_0 ,bsums_vec ,0 ); 1573bias_lo = vmlal_lane_s16 (bias_lo ,scales_lo_1 ,bsums_vec ,1 ); 1574bias_hi = vmlal_lane_s16 (bias_hi ,scales_hi_1 ,bsums_vec ,1 ); 1575bias_lo = vmlal_lane_s16 (bias_lo ,scales_lo_2 ,bsums_vec ,2 ); 1576bias_hi = vmlal_lane_s16 (bias_hi ,scales_hi_2 ,bsums_vec ,2 ); 1577bias_lo = vmlal_lane_s16 (bias_lo ,scales_lo_3 ,bsums_vec ,3 ); 1578bias_hi = vmlal_lane_s16 (bias_hi ,scales_hi_3 ,bsums_vec ,3 ); 1579 } 1580bias_lo = vshlq_n_s32 (bias_lo ,5 ); 1581bias_hi = vshlq_n_s32 (bias_hi ,5 ); 1582 1583// Process two 128-value halves per superblock 1584for (int half = 0 ;half < 2 ;half ++ ) { 1585const uint8_t * ql_base = q6_ptr [b ].ql + half * 512 ; 1586const uint8_t * qh_base = q6_ptr [b ].qh + half * 256 ; 1587 1588// A subblock (sb) is a set of weights that share the scale 1589// Since q6_K scales are per 16 elements 1590// num sbs -> 256 elements / (16 elements/scale * 2 elements/byte * 2 halves) 1591for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 1592const int8_t * q8_base_l = q8_ptr [b ].qs + half * 128 + sb * 16 ; 1593const int8_t * q8_base_h = q8_base_l + 64 ; 1594 1595// Load and duplicate q8 values (each register covers two interleaved columns of q6) 1596int8x16_t q8_l [2 ]; 1597int8x16_t q8_h [2 ]; 1598for (int i = 0 ;i < 2 ;i ++ ) { 1599q8_l [i ]= (int8x16_t )vld1q_dup_s64 ((const int64_t * ) (q8_base_l + i * 8 )); 1600q8_h [i ]= (int8x16_t )vld1q_dup_s64 ((const int64_t * ) (q8_base_h + i * 8 )); 1601 } 1602 1603const int ql_off_base = sb * QK_K /2 ; 1604const int qh_off_base = ql_off_base & 255 ;// wraps after 256 bytes 1605 1606// Load 4 vectors at once (64 bytes each for ql_0, ql_1, qh_0, qh_1) 1607uint8x16x4_t q6_ql_0 = vld1q_u8_x4 (ql_base + ql_off_base ); 1608uint8x16x4_t q6_ql_1 = vld1q_u8_x4 (ql_base + ql_off_base + 64 ); 1609uint8x16x4_t q6_qh_0 = vld1q_u8_x4 (qh_base + qh_off_base ); 1610uint8x16x4_t q6_qh_1 = vld1q_u8_x4 (qh_base + qh_off_base + 64 ); 1611 1612// Adjust qh for subblocks 2 and 3 (shift right by 2) 1613if (sb > 1 ) { 1614q6_qh_0 .val [0 ]= vshrq_n_u8 (q6_qh_0 .val [0 ],2 ); 1615q6_qh_0 .val [1 ]= vshrq_n_u8 (q6_qh_0 .val [1 ],2 ); 1616q6_qh_0 .val [2 ]= vshrq_n_u8 (q6_qh_0 .val [2 ],2 ); 1617q6_qh_0 .val [3 ]= vshrq_n_u8 (q6_qh_0 .val [3 ],2 ); 1618q6_qh_1 .val [0 ]= vshrq_n_u8 (q6_qh_1 .val [0 ],2 ); 1619q6_qh_1 .val [1 ]= vshrq_n_u8 (q6_qh_1 .val [1 ],2 ); 1620q6_qh_1 .val [2 ]= vshrq_n_u8 (q6_qh_1 .val [2 ],2 ); 1621q6_qh_1 .val [3 ]= vshrq_n_u8 (q6_qh_1 .val [3 ],2 ); 1622 } 1623 1624// Process column pairs (0-1, 2-3, 4-5, 6-7) 1625for (int cp = 0 ;cp < col_pairs ;cp ++ ) { 1626const uint8x16_t q6_qs_cp_0_l = q6_ql_0 .val [cp ]; 1627const uint8x16_t q6_qs_cp_1_l = q6_ql_1 .val [cp ]; 1628const uint8x16_t q6_qs_cp_0_h = q6_qh_0 .val [cp ]; 1629const uint8x16_t q6_qs_cp_1_h = q6_qh_1 .val [cp ]; 1630 1631// Extract high 2 bits for upper nibble reconstruction 1632const uint8x16_t q6_qs_cp_0_hh = vandq_u8 (q6_qs_cp_0_h ,mask_hi ); 1633const uint8x16_t q6_qs_cp_1_hh = vandq_u8 (q6_qs_cp_1_h ,mask_hi ); 1634 1635// q6 = (low4 | high2<<4), without -32 bias (handled via bsums) 1636const int8x16_t q6_l0 = vreinterpretq_s8_u8 ( 1637vsliq_n_u8 (vandq_u8 (q6_qs_cp_0_l ,m4b ),vandq_u8 (q6_qs_cp_0_h ,mask_lo ),4 )); 1638const int8x16_t q6_l1 = vreinterpretq_s8_u8 ( 1639vsliq_n_u8 (vandq_u8 (q6_qs_cp_1_l ,m4b ),vandq_u8 (q6_qs_cp_1_h ,mask_lo ),4 )); 1640const int8x16_t q6_h0 = 1641vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (q6_qs_cp_0_l ,4 ),q6_qs_cp_0_hh )); 1642const int8x16_t q6_h1 = 1643vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (q6_qs_cp_1_l ,4 ),q6_qs_cp_1_hh )); 1644 1645int32x4_t sb_acc_l = vdupq_n_s32 (0 ); 1646sb_acc_l = vdotq_s32 (sb_acc_l ,q6_l0 ,q8_l [0 ]); 1647sb_acc_l = vdotq_s32 (sb_acc_l ,q6_l1 ,q8_l [1 ]); 1648 1649int32x4_t sb_acc_h = vdupq_n_s32 (0 ); 1650sb_acc_h = vdotq_s32 (sb_acc_h ,q6_h0 ,q8_h [0 ]); 1651sb_acc_h = vdotq_s32 (sb_acc_h ,q6_h1 ,q8_h [1 ]); 1652 1653// Pairwise add to get per-column sums: [col0, col1] 1654int32x2_t sum_l = vpadd_s32 (vget_low_s32 (sb_acc_l ),vget_high_s32 (sb_acc_l )); 1655int32x2_t sum_h = vpadd_s32 (vget_low_s32 (sb_acc_h ),vget_high_s32 (sb_acc_h )); 1656 1657const int scale_idx_l = half * 8 + sb ; 1658const int scale_idx_h = half * 8 + sb + 4 ; 1659 1660// Access scales using array indexing (scales are interleaved by column) 1661const int32x2_t scale_vec_l = { (int32_t )q6_scales [scale_idx_l * 8 + cp * 2 ], 1662 (int32_t )q6_scales [scale_idx_l * 8 + cp * 2 + 1 ] }; 1663const int32x2_t scale_vec_h = { (int32_t )q6_scales [scale_idx_h * 8 + cp * 2 ], 1664 (int32_t )q6_scales [scale_idx_h * 8 + cp * 2 + 1 ] }; 1665 1666// Accumulate scaled results 1667acc [cp ]= vmla_s32 (acc [cp ],sum_l ,scale_vec_l ); 1668acc [cp ]= vmla_s32 (acc [cp ],sum_h ,scale_vec_h ); 1669 } 1670 } 1671 }// for half 1672 1673// Bias correction 1674acc [0 ]= vsub_s32 (acc [0 ],vget_low_s32 (bias_lo )); 1675acc [1 ]= vsub_s32 (acc [1 ],vget_high_s32 (bias_lo )); 1676acc [2 ]= vsub_s32 (acc [2 ],vget_low_s32 (bias_hi )); 1677acc [3 ]= vsub_s32 (acc [3 ],vget_high_s32 (bias_hi )); 1678 1679// Apply superblock scale (no mins for q6_K) 1680// acc[cp] has [c0, c1] 1681float32x2_t w_01 = vmul_f32 (vcvt_f32_s32 (acc [0 ]),vget_low_f32 (sb_scale_0 )); 1682float32x2_t w_23 = vmul_f32 (vcvt_f32_s32 (acc [1 ]),vget_high_f32 (sb_scale_0 )); 1683float32x2_t w_45 = vmul_f32 (vcvt_f32_s32 (acc [2 ]),vget_low_f32 (sb_scale_1 )); 1684float32x2_t w_67 = vmul_f32 (vcvt_f32_s32 (acc [3 ]),vget_high_f32 (sb_scale_1 )); 1685 1686acc_f32 [0 ]= vaddq_f32 (acc_f32 [0 ],vcombine_f32 (w_01 ,w_23 )); 1687acc_f32 [1 ]= vaddq_f32 (acc_f32 [1 ],vcombine_f32 (w_45 ,w_67 )); 1688 }// for b 1689 1690int base = x * ncols_interleaved ; 1691vst1q_f32 (s + base ,acc_f32 [0 ]); 1692vst1q_f32 (s + base + 4 ,acc_f32 [1 ]); 1693 }// for x 1694return ; 1695#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 1696ggml_gemv_q6_K_8x8_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 1697} 1698 1699void ggml_gemv_q8_0_4x4_q8_0 (int n , 1700float * GGML_RESTRICT s , 1701size_t bs , 1702const void * GGML_RESTRICT vx , 1703const void * GGML_RESTRICT vy , 1704int nr , 1705int nc ) { 1706const int qk = QK8_0 ; 1707const int nb = n /qk ; 1708const int ncols_interleaved = 4 ; 1709const int blocklen = 4 ; 1710 1711assert (n %qk == 0 ); 1712assert (nc %ncols_interleaved == 0 ); 1713 1714UNUSED (nb ); 1715UNUSED (ncols_interleaved ); 1716UNUSED (blocklen ); 1717 1718#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 1719const block_q8_0x4 * b_ptr = (const block_q8_0x4 * )vx ; 1720 1721for (int c = 0 ;c < nc ;c += ncols_interleaved ) { 1722const block_q8_0 * a_ptr = (const block_q8_0 * )vy ; 1723float32x4_t acc = vdupq_n_f32 (0 ); 1724for (int b = 0 ;b < nb ;b ++ ) { 1725int8x16x4_t b_low = vld1q_s8_x4 ((const int8_t * )b_ptr -> qs ); 1726int8x16x4_t b_high = vld1q_s8_x4 ((const int8_t * )b_ptr -> qs + 64 ); 1727float16x4_t bd = vld1_f16 ((const __fp16 * )b_ptr -> d ); 1728 1729int8x16x2_t a = vld1q_s8_x2 (a_ptr -> qs ); 1730float16x4_t ad = vld1_dup_f16 ((const __fp16 * )& a_ptr -> d ); 1731 1732int32x4_t ret = vdupq_n_s32 (0 ); 1733 1734ret = vdotq_laneq_s32 (ret ,b_low .val [0 ],a .val [0 ],0 ); 1735ret = vdotq_laneq_s32 (ret ,b_low .val [1 ],a .val [0 ],1 ); 1736ret = vdotq_laneq_s32 (ret ,b_low .val [2 ],a .val [0 ],2 ); 1737ret = vdotq_laneq_s32 (ret ,b_low .val [3 ],a .val [0 ],3 ); 1738 1739ret = vdotq_laneq_s32 (ret ,b_high .val [0 ],a .val [1 ],0 ); 1740ret = vdotq_laneq_s32 (ret ,b_high .val [1 ],a .val [1 ],1 ); 1741ret = vdotq_laneq_s32 (ret ,b_high .val [2 ],a .val [1 ],2 ); 1742ret = vdotq_laneq_s32 (ret ,b_high .val [3 ],a .val [1 ],3 ); 1743 1744acc = vfmaq_f32 (acc ,vcvtq_f32_s32 (ret ),vmulq_f32 (vcvt_f32_f16 (ad ),vcvt_f32_f16 (bd ))); 1745a_ptr ++ ; 1746b_ptr ++ ; 1747 } 1748vst1q_f32 (s ,acc ); 1749s += ncols_interleaved ; 1750 } 1751return ; 1752 1753#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 1754ggml_gemv_q8_0_4x4_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 1755} 1756 1757void ggml_gemv_q8_0_4x8_q8_0 (int n , 1758float * GGML_RESTRICT s , 1759size_t bs , 1760const void * GGML_RESTRICT vx , 1761const void * GGML_RESTRICT vy , 1762int nr , 1763int nc ) { 1764const int qk = QK8_0 ; 1765const int nb = n /qk ; 1766const int ncols_interleaved = 4 ; 1767const int blocklen = 8 ; 1768 1769assert (n %qk == 0 ); 1770assert (nc %ncols_interleaved == 0 ); 1771 1772UNUSED (nb ); 1773UNUSED (ncols_interleaved ); 1774UNUSED (blocklen ); 1775 1776#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 1777const block_q8_0x4 * b_ptr = (const block_q8_0x4 * )vx ; 1778 1779for (int c = 0 ;c < nc ;c += ncols_interleaved ) { 1780const block_q8_0 * a_ptr = (const block_q8_0 * )vy ; 1781float32x4_t acc = vdupq_n_f32 (0 ); 1782 1783for (int b = 0 ;b < nb ;b ++ ) { 1784int8x16x4_t b_low = vld1q_s8_x4 ((const int8_t * )b_ptr -> qs ); 1785int8x16x4_t b_high = vld1q_s8_x4 ((const int8_t * )b_ptr -> qs + 64 ); 1786float16x4_t bd = vld1_f16 ((const __fp16 * )b_ptr -> d ); 1787 1788int8x8x4_t a_chunks = vld1_s8_x4 (a_ptr -> qs ); 1789int8x16_t a0 = vcombine_s8 (a_chunks .val [0 ],a_chunks .val [0 ]); 1790int8x16_t a1 = vcombine_s8 (a_chunks .val [1 ],a_chunks .val [1 ]); 1791int8x16_t a2 = vcombine_s8 (a_chunks .val [2 ],a_chunks .val [2 ]); 1792int8x16_t a3 = vcombine_s8 (a_chunks .val [3 ],a_chunks .val [3 ]); 1793float16x4_t ad = vld1_dup_f16 ((const __fp16 * )& a_ptr -> d ); 1794 1795int32x4_t ret0 = vdupq_n_s32 (0 ); 1796int32x4_t ret1 = vdupq_n_s32 (0 ); 1797 1798// 0..7 1799ret0 = vdotq_s32 (ret0 ,b_low .val [0 ],a0 ); 1800ret1 = vdotq_s32 (ret1 ,b_low .val [1 ],a0 ); 1801// 8..15 1802ret0 = vdotq_s32 (ret0 ,b_low .val [2 ],a1 ); 1803ret1 = vdotq_s32 (ret1 ,b_low .val [3 ],a1 ); 1804// 16..23 1805ret0 = vdotq_s32 (ret0 ,b_high .val [0 ],a2 ); 1806ret1 = vdotq_s32 (ret1 ,b_high .val [1 ],a2 ); 1807// 24..31 1808ret0 = vdotq_s32 (ret0 ,b_high .val [2 ],a3 ); 1809ret1 = vdotq_s32 (ret1 ,b_high .val [3 ],a3 ); 1810 1811int32x4_t ret = vpaddq_s32 (ret0 ,ret1 ); 1812 1813acc = vfmaq_f32 (acc ,vcvtq_f32_s32 (ret ),vmulq_f32 (vcvt_f32_f16 (ad ),vcvt_f32_f16 (bd ))); 1814a_ptr ++ ; 1815b_ptr ++ ; 1816 } 1817vst1q_f32 (s ,acc ); 1818s += ncols_interleaved ; 1819 } 1820return ; 1821 1822#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 1823ggml_gemv_q8_0_4x8_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 1824} 1825 1826void ggml_gemm_q4_0_4x4_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 1827const int qk = QK8_0 ; 1828const int nb = n /qk ; 1829const int ncols_interleaved = 4 ; 1830const int blocklen = 4 ; 1831 1832assert (n %qk == 0 ); 1833assert (nr %4 == 0 ); 1834assert (nc %ncols_interleaved == 0 ); 1835 1836UNUSED (s ); 1837UNUSED (bs ); 1838UNUSED (vx ); 1839UNUSED (vy ); 1840UNUSED (nr ); 1841UNUSED (nc ); 1842UNUSED (nb ); 1843UNUSED (ncols_interleaved ); 1844UNUSED (blocklen ); 1845 1846#if ! ((defined(_MSC_VER ))&& ! defined(__clang__ ))&& defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 1847const void * b_ptr = vx ; 1848const void * a_ptr = vy ; 1849float * res_ptr = s ; 1850size_t res_stride = bs * sizeof (float ); 1851 1852 __asm__ __volatile__( 1853"mov x10, %x[nr]\n" 1854"mov x9, #0x88\n" 1855"cmp x10, #0x10\n" 1856"mul x9, %x[nb], x9\n" 1857"blt 4f\n" 1858"1:" // Row loop 1859"add x28, %x[b_ptr], #0x8\n" 1860"mov x27, %x[nc]\n" 1861"add x26, %x[res_ptr], %x[res_stride], LSL #4\n" 1862"2:" // Column loop 1863"add x25, %x[a_ptr], #0x8\n" 1864"movi v15.16b, #0x0\n" 1865"movi v19.16b, #0x0\n" 1866"mov x24, %x[nb]\n" 1867"add x23, x25, x9\n" 1868"movi v18.16b, #0x0\n" 1869"movi v14.16b, #0x0\n" 1870"add x22, x23, x9\n" 1871"movi v11.16b, #0x0\n" 1872"movi v13.16b, #0x0\n" 1873"add x21, x22, x9\n" 1874"movi v23.16b, #0x0\n" 1875"movi v16.16b, #0x0\n" 1876"movi v25.16b, #0x0\n" 1877"movi v7.16b, #0x0\n" 1878"movi v0.16b, #0x0\n" 1879"movi v4.16b, #0x0\n" 1880"movi v5.16b, #0x0\n" 1881"movi v21.16b, #0x0\n" 1882"movi v8.16b, #0x0\n" 1883"movi v1.16b, #0x0\n" 1884"3:" // Block loop 1885"ldr q3, [x28, #0x0]\n" 1886"ldr q31, [x25, #0x0]\n" 1887"movi v28.16b, #0x4\n" 1888"movi v10.4s, #0x0\n" 1889"ldr q22, [x28, #0x10]\n" 1890"ldr q6, [x25, #0x10]\n" 1891"movi v29.4s, #0x0\n" 1892"movi v9.4s, #0x0\n" 1893"ldr q27, [x28, #0x20]\n" 1894"ldr q30, [x28, #0x30]\n" 1895"movi v20.4s, #0x0\n" 1896"movi v24.16b, #0xf0\n" 1897"ldr d2, [x25, #-0x8]\n" 1898"ldr d26, [x23, #-0x8]\n" 1899"sshl v12.16b, v3.16b, v28.16b\n" 1900"sub x20, x28, #0x8\n" 1901"ldr d17, [x20, #0x0]\n" 1902"and v3.16b, v3.16b, v24.16b\n" 1903"subs x24, x24, #0x1\n" 1904"add x28, x28, #0x48\n" 1905".inst 0x4f9fe18a // sdot v10.4s, v12.16b, v31.4b[0]\n" 1906".inst 0x4fbfe19d // sdot v29.4s, v12.16b, v31.4b[1]\n" 1907".inst 0x4f9fe989 // sdot v9.4s, v12.16b, v31.4b[2]\n" 1908".inst 0x4fbfe994 // sdot v20.4s, v12.16b, v31.4b[3]\n" 1909"sshl v31.16b, v22.16b, v28.16b\n" 1910"and v22.16b, v22.16b, v24.16b\n" 1911"fcvtl v17.4s, v17.4h\n" 1912"fcvtl v2.4s, v2.4h\n" 1913"fcvtl v26.4s, v26.4h\n" 1914".inst 0x4f86e3ea // sdot v10.4s, v31.16b, v6.4b[0]\n" 1915".inst 0x4fa6e3fd // sdot v29.4s, v31.16b, v6.4b[1]\n" 1916".inst 0x4f86ebe9 // sdot v9.4s, v31.16b, v6.4b[2]\n" 1917".inst 0x4fa6ebf4 // sdot v20.4s, v31.16b, v6.4b[3]\n" 1918"sshl v6.16b, v27.16b, v28.16b\n" 1919"sshl v28.16b, v30.16b, v28.16b\n" 1920"and v27.16b, v27.16b, v24.16b\n" 1921"and v30.16b, v30.16b, v24.16b\n" 1922"ldr q24, [x25, #0x20]\n" 1923".inst 0x4f98e0ca // sdot v10.4s, v6.16b, v24.4b[0]\n" 1924".inst 0x4fb8e0dd // sdot v29.4s, v6.16b, v24.4b[1]\n" 1925".inst 0x4f98e8c9 // sdot v9.4s, v6.16b, v24.4b[2]\n" 1926".inst 0x4fb8e8d4 // sdot v20.4s, v6.16b, v24.4b[3]\n" 1927"ldr q24, [x25, #0x30]\n" 1928".inst 0x4f98e38a // sdot v10.4s, v28.16b, v24.4b[0]\n" 1929".inst 0x4fb8e39d // sdot v29.4s, v28.16b, v24.4b[1]\n" 1930".inst 0x4f98eb89 // sdot v9.4s, v28.16b, v24.4b[2]\n" 1931".inst 0x4fb8eb94 // sdot v20.4s, v28.16b, v24.4b[3]\n" 1932"ldr q24, [x25, #0x40]\n" 1933".inst 0x4f98e06a // sdot v10.4s, v3.16b, v24.4b[0]\n" 1934".inst 0x4fb8e07d // sdot v29.4s, v3.16b, v24.4b[1]\n" 1935".inst 0x4f98e869 // sdot v9.4s, v3.16b, v24.4b[2]\n" 1936".inst 0x4fb8e874 // sdot v20.4s, v3.16b, v24.4b[3]\n" 1937"ldr q24, [x25, #0x50]\n" 1938".inst 0x4f98e2ca // sdot v10.4s, v22.16b, v24.4b[0]\n" 1939".inst 0x4fb8e2dd // sdot v29.4s, v22.16b, v24.4b[1]\n" 1940".inst 0x4f98eac9 // sdot v9.4s, v22.16b, v24.4b[2]\n" 1941".inst 0x4fb8ead4 // sdot v20.4s, v22.16b, v24.4b[3]\n" 1942"ldr q24, [x25, #0x60]\n" 1943".inst 0x4f98e36a // sdot v10.4s, v27.16b, v24.4b[0]\n" 1944".inst 0x4fb8e37d // sdot v29.4s, v27.16b, v24.4b[1]\n" 1945".inst 0x4f98eb69 // sdot v9.4s, v27.16b, v24.4b[2]\n" 1946".inst 0x4fb8eb74 // sdot v20.4s, v27.16b, v24.4b[3]\n" 1947"ldr q24, [x25, #0x70]\n" 1948"add x25, x25, #0x88\n" 1949".inst 0x4f98e3ca // sdot v10.4s, v30.16b, v24.4b[0]\n" 1950".inst 0x4fb8e3dd // sdot v29.4s, v30.16b, v24.4b[1]\n" 1951".inst 0x4f98ebc9 // sdot v9.4s, v30.16b, v24.4b[2]\n" 1952".inst 0x4fb8ebd4 // sdot v20.4s, v30.16b, v24.4b[3]\n" 1953"fmul v24.4s, v17.4s, v2.s[0]\n" 1954"scvtf v10.4s, v10.4s, #0x4\n" 1955"scvtf v29.4s, v29.4s, #0x4\n" 1956"scvtf v9.4s, v9.4s, #0x4\n" 1957"scvtf v20.4s, v20.4s, #0x4\n" 1958"fmla v15.4s, v10.4s, v24.4s\n" 1959"ldr q24, [x23, #0x0]\n" 1960"fmul v10.4s, v17.4s, v2.s[1]\n" 1961"fmla v19.4s, v29.4s, v10.4s\n" 1962"ldr q10, [x23, #0x10]\n" 1963"fmul v29.4s, v17.4s, v2.s[2]\n" 1964"fmul v2.4s, v17.4s, v2.s[3]\n" 1965"fmla v18.4s, v9.4s, v29.4s\n" 1966"movi v9.4s, #0x0\n" 1967"movi v29.4s, #0x0\n" 1968".inst 0x4f98e189 // sdot v9.4s, v12.16b, v24.4b[0]\n" 1969".inst 0x4fb8e19d // sdot v29.4s, v12.16b, v24.4b[1]\n" 1970"fmla v14.4s, v20.4s, v2.4s\n" 1971"movi v20.4s, #0x0\n" 1972"movi v2.4s, #0x0\n" 1973".inst 0x4f98e994 // sdot v20.4s, v12.16b, v24.4b[2]\n" 1974".inst 0x4fb8e982 // sdot v2.4s, v12.16b, v24.4b[3]\n" 1975"ldr q24, [x23, #0x20]\n" 1976".inst 0x4f8ae3e9 // sdot v9.4s, v31.16b, v10.4b[0]\n" 1977".inst 0x4faae3fd // sdot v29.4s, v31.16b, v10.4b[1]\n" 1978".inst 0x4f8aebf4 // sdot v20.4s, v31.16b, v10.4b[2]\n" 1979".inst 0x4faaebe2 // sdot v2.4s, v31.16b, v10.4b[3]\n" 1980"ldr q10, [x23, #0x30]\n" 1981".inst 0x4f98e0c9 // sdot v9.4s, v6.16b, v24.4b[0]\n" 1982".inst 0x4fb8e0dd // sdot v29.4s, v6.16b, v24.4b[1]\n" 1983".inst 0x4f98e8d4 // sdot v20.4s, v6.16b, v24.4b[2]\n" 1984".inst 0x4fb8e8c2 // sdot v2.4s, v6.16b, v24.4b[3]\n" 1985"ldr q24, [x23, #0x40]\n" 1986".inst 0x4f8ae389 // sdot v9.4s, v28.16b, v10.4b[0]\n" 1987".inst 0x4faae39d // sdot v29.4s, v28.16b, v10.4b[1]\n" 1988".inst 0x4f8aeb94 // sdot v20.4s, v28.16b, v10.4b[2]\n" 1989".inst 0x4faaeb82 // sdot v2.4s, v28.16b, v10.4b[3]\n" 1990"ldr q10, [x23, #0x50]\n" 1991".inst 0x4f98e069 // sdot v9.4s, v3.16b, v24.4b[0]\n" 1992".inst 0x4fb8e07d // sdot v29.4s, v3.16b, v24.4b[1]\n" 1993".inst 0x4f98e874 // sdot v20.4s, v3.16b, v24.4b[2]\n" 1994".inst 0x4fb8e862 // sdot v2.4s, v3.16b, v24.4b[3]\n" 1995"ldr q24, [x23, #0x60]\n" 1996".inst 0x4f8ae2c9 // sdot v9.4s, v22.16b, v10.4b[0]\n" 1997".inst 0x4faae2dd // sdot v29.4s, v22.16b, v10.4b[1]\n" 1998".inst 0x4f8aead4 // sdot v20.4s, v22.16b, v10.4b[2]\n" 1999".inst 0x4faaeac2 // sdot v2.4s, v22.16b, v10.4b[3]\n" 2000"ldr q10, [x23, #0x70]\n" 2001"add x23, x23, #0x88\n" 2002".inst 0x4f98e369 // sdot v9.4s, v27.16b, v24.4b[0]\n" 2003".inst 0x4fb8e37d // sdot v29.4s, v27.16b, v24.4b[1]\n" 2004".inst 0x4f98eb74 // sdot v20.4s, v27.16b, v24.4b[2]\n" 2005".inst 0x4fb8eb62 // sdot v2.4s, v27.16b, v24.4b[3]\n" 2006"ldr q24, [x22, #0x0]\n" 2007".inst 0x4f8ae3c9 // sdot v9.4s, v30.16b, v10.4b[0]\n" 2008".inst 0x4faae3dd // sdot v29.4s, v30.16b, v10.4b[1]\n" 2009".inst 0x4f8aebd4 // sdot v20.4s, v30.16b, v10.4b[2]\n" 2010".inst 0x4faaebc2 // sdot v2.4s, v30.16b, v10.4b[3]\n" 2011"fmul v10.4s, v17.4s, v26.s[0]\n" 2012"scvtf v9.4s, v9.4s, #0x4\n" 2013"scvtf v29.4s, v29.4s, #0x4\n" 2014"scvtf v20.4s, v20.4s, #0x4\n" 2015"scvtf v2.4s, v2.4s, #0x4\n" 2016"fmla v11.4s, v9.4s, v10.4s\n" 2017"ldr q9, [x22, #0x10]\n" 2018"fmul v10.4s, v17.4s, v26.s[1]\n" 2019"fmla v13.4s, v29.4s, v10.4s\n" 2020"ldr d29, [x22, #-0x8]\n" 2021"fmul v10.4s, v17.4s, v26.s[2]\n" 2022"fmul v26.4s, v17.4s, v26.s[3]\n" 2023"fcvtl v29.4s, v29.4h\n" 2024"fmla v23.4s, v20.4s, v10.4s\n" 2025"movi v20.4s, #0x0\n" 2026"movi v10.4s, #0x0\n" 2027"fmla v16.4s, v2.4s, v26.4s\n" 2028"movi v26.4s, #0x0\n" 2029"movi v2.4s, #0x0\n" 2030".inst 0x4f98e194 // sdot v20.4s, v12.16b, v24.4b[0]\n" 2031".inst 0x4fb8e18a // sdot v10.4s, v12.16b, v24.4b[1]\n" 2032".inst 0x4f98e99a // sdot v26.4s, v12.16b, v24.4b[2]\n" 2033".inst 0x4fb8e982 // sdot v2.4s, v12.16b, v24.4b[3]\n" 2034"ldr q24, [x22, #0x20]\n" 2035".inst 0x4f89e3f4 // sdot v20.4s, v31.16b, v9.4b[0]\n" 2036".inst 0x4fa9e3ea // sdot v10.4s, v31.16b, v9.4b[1]\n" 2037".inst 0x4f89ebfa // sdot v26.4s, v31.16b, v9.4b[2]\n" 2038".inst 0x4fa9ebe2 // sdot v2.4s, v31.16b, v9.4b[3]\n" 2039"ldr q9, [x22, #0x30]\n" 2040".inst 0x4f98e0d4 // sdot v20.4s, v6.16b, v24.4b[0]\n" 2041".inst 0x4fb8e0ca // sdot v10.4s, v6.16b, v24.4b[1]\n" 2042".inst 0x4f98e8da // sdot v26.4s, v6.16b, v24.4b[2]\n" 2043".inst 0x4fb8e8c2 // sdot v2.4s, v6.16b, v24.4b[3]\n" 2044"ldr q24, [x22, #0x40]\n" 2045".inst 0x4f89e394 // sdot v20.4s, v28.16b, v9.4b[0]\n" 2046".inst 0x4fa9e38a // sdot v10.4s, v28.16b, v9.4b[1]\n" 2047".inst 0x4f89eb9a // sdot v26.4s, v28.16b, v9.4b[2]\n" 2048".inst 0x4fa9eb82 // sdot v2.4s, v28.16b, v9.4b[3]\n" 2049"ldr q9, [x22, #0x50]\n" 2050".inst 0x4f98e074 // sdot v20.4s, v3.16b, v24.4b[0]\n" 2051".inst 0x4fb8e06a // sdot v10.4s, v3.16b, v24.4b[1]\n" 2052".inst 0x4f98e87a // sdot v26.4s, v3.16b, v24.4b[2]\n" 2053".inst 0x4fb8e862 // sdot v2.4s, v3.16b, v24.4b[3]\n" 2054"ldr q24, [x22, #0x60]\n" 2055".inst 0x4f89e2d4 // sdot v20.4s, v22.16b, v9.4b[0]\n" 2056".inst 0x4fa9e2ca // sdot v10.4s, v22.16b, v9.4b[1]\n" 2057".inst 0x4f89eada // sdot v26.4s, v22.16b, v9.4b[2]\n" 2058".inst 0x4fa9eac2 // sdot v2.4s, v22.16b, v9.4b[3]\n" 2059"ldr q9, [x22, #0x70]\n" 2060"add x22, x22, #0x88\n" 2061".inst 0x4f98e374 // sdot v20.4s, v27.16b, v24.4b[0]\n" 2062".inst 0x4fb8e36a // sdot v10.4s, v27.16b, v24.4b[1]\n" 2063".inst 0x4f98eb7a // sdot v26.4s, v27.16b, v24.4b[2]\n" 2064".inst 0x4fb8eb62 // sdot v2.4s, v27.16b, v24.4b[3]\n" 2065"ldr q24, [x21, #0x0]\n" 2066".inst 0x4f89e3d4 // sdot v20.4s, v30.16b, v9.4b[0]\n" 2067".inst 0x4fa9e3ca // sdot v10.4s, v30.16b, v9.4b[1]\n" 2068".inst 0x4f89ebda // sdot v26.4s, v30.16b, v9.4b[2]\n" 2069".inst 0x4fa9ebc2 // sdot v2.4s, v30.16b, v9.4b[3]\n" 2070"fmul v9.4s, v17.4s, v29.s[0]\n" 2071"scvtf v20.4s, v20.4s, #0x4\n" 2072"scvtf v10.4s, v10.4s, #0x4\n" 2073"scvtf v26.4s, v26.4s, #0x4\n" 2074"scvtf v2.4s, v2.4s, #0x4\n" 2075"fmla v25.4s, v20.4s, v9.4s\n" 2076"ldr q9, [x21, #0x10]\n" 2077"fmul v20.4s, v17.4s, v29.s[1]\n" 2078"fmla v7.4s, v10.4s, v20.4s\n" 2079"ldr d20, [x21, #-0x8]\n" 2080"fmul v10.4s, v17.4s, v29.s[2]\n" 2081"fmul v29.4s, v17.4s, v29.s[3]\n" 2082"fcvtl v20.4s, v20.4h\n" 2083"fmla v0.4s, v26.4s, v10.4s\n" 2084"movi v26.4s, #0x0\n" 2085"movi v10.4s, #0x0\n" 2086"fmla v4.4s, v2.4s, v29.4s\n" 2087"movi v2.4s, #0x0\n" 2088"movi v29.4s, #0x0\n" 2089".inst 0x4f98e19a // sdot v26.4s, v12.16b, v24.4b[0]\n" 2090".inst 0x4fb8e18a // sdot v10.4s, v12.16b, v24.4b[1]\n" 2091".inst 0x4f98e982 // sdot v2.4s, v12.16b, v24.4b[2]\n" 2092".inst 0x4fb8e99d // sdot v29.4s, v12.16b, v24.4b[3]\n" 2093"ldr q12, [x21, #0x20]\n" 2094"fmul v24.4s, v17.4s, v20.s[0]\n" 2095".inst 0x4f89e3fa // sdot v26.4s, v31.16b, v9.4b[0]\n" 2096".inst 0x4fa9e3ea // sdot v10.4s, v31.16b, v9.4b[1]\n" 2097".inst 0x4f89ebe2 // sdot v2.4s, v31.16b, v9.4b[2]\n" 2098".inst 0x4fa9ebfd // sdot v29.4s, v31.16b, v9.4b[3]\n" 2099"ldr q9, [x21, #0x30]\n" 2100"fmul v31.4s, v17.4s, v20.s[1]\n" 2101".inst 0x4f8ce0da // sdot v26.4s, v6.16b, v12.4b[0]\n" 2102".inst 0x4face0ca // sdot v10.4s, v6.16b, v12.4b[1]\n" 2103".inst 0x4f8ce8c2 // sdot v2.4s, v6.16b, v12.4b[2]\n" 2104".inst 0x4face8dd // sdot v29.4s, v6.16b, v12.4b[3]\n" 2105"ldr q12, [x21, #0x40]\n" 2106"fmul v6.4s, v17.4s, v20.s[2]\n" 2107"fmul v20.4s, v17.4s, v20.s[3]\n" 2108".inst 0x4f89e39a // sdot v26.4s, v28.16b, v9.4b[0]\n" 2109".inst 0x4fa9e38a // sdot v10.4s, v28.16b, v9.4b[1]\n" 2110".inst 0x4f89eb82 // sdot v2.4s, v28.16b, v9.4b[2]\n" 2111".inst 0x4fa9eb9d // sdot v29.4s, v28.16b, v9.4b[3]\n" 2112"ldr q9, [x21, #0x50]\n" 2113".inst 0x4f8ce07a // sdot v26.4s, v3.16b, v12.4b[0]\n" 2114".inst 0x4face06a // sdot v10.4s, v3.16b, v12.4b[1]\n" 2115".inst 0x4f8ce862 // sdot v2.4s, v3.16b, v12.4b[2]\n" 2116".inst 0x4face87d // sdot v29.4s, v3.16b, v12.4b[3]\n" 2117"ldr q12, [x21, #0x60]\n" 2118".inst 0x4f89e2da // sdot v26.4s, v22.16b, v9.4b[0]\n" 2119".inst 0x4fa9e2ca // sdot v10.4s, v22.16b, v9.4b[1]\n" 2120".inst 0x4f89eac2 // sdot v2.4s, v22.16b, v9.4b[2]\n" 2121".inst 0x4fa9eadd // sdot v29.4s, v22.16b, v9.4b[3]\n" 2122"ldr q17, [x21, #0x70]\n" 2123"add x21, x21, #0x88\n" 2124".inst 0x4f8ce37a // sdot v26.4s, v27.16b, v12.4b[0]\n" 2125".inst 0x4face36a // sdot v10.4s, v27.16b, v12.4b[1]\n" 2126".inst 0x4f8ceb62 // sdot v2.4s, v27.16b, v12.4b[2]\n" 2127".inst 0x4faceb7d // sdot v29.4s, v27.16b, v12.4b[3]\n" 2128".inst 0x4f91e3da // sdot v26.4s, v30.16b, v17.4b[0]\n" 2129".inst 0x4fb1e3ca // sdot v10.4s, v30.16b, v17.4b[1]\n" 2130".inst 0x4f91ebc2 // sdot v2.4s, v30.16b, v17.4b[2]\n" 2131".inst 0x4fb1ebdd // sdot v29.4s, v30.16b, v17.4b[3]\n" 2132"scvtf v26.4s, v26.4s, #0x4\n" 2133"scvtf v10.4s, v10.4s, #0x4\n" 2134"fmla v5.4s, v26.4s, v24.4s\n" 2135"scvtf v2.4s, v2.4s, #0x4\n" 2136"scvtf v29.4s, v29.4s, #0x4\n" 2137"fmla v21.4s, v10.4s, v31.4s\n" 2138"fmla v8.4s, v2.4s, v6.4s\n" 2139"fmla v1.4s, v29.4s, v20.4s\n" 2140"bgt 3b\n" 2141"mov x20, %x[res_ptr]\n" 2142"subs x27, x27, #0x4\n" 2143"add %x[res_ptr], %x[res_ptr], #0x10\n" 2144"str q15, [x20, #0x0]\n" 2145"add x20, x20, %x[res_stride]\n" 2146"str q19, [x20, #0x0]\n" 2147"add x20, x20, %x[res_stride]\n" 2148"str q18, [x20, #0x0]\n" 2149"add x20, x20, %x[res_stride]\n" 2150"str q14, [x20, #0x0]\n" 2151"add x20, x20, %x[res_stride]\n" 2152"str q11, [x20, #0x0]\n" 2153"add x20, x20, %x[res_stride]\n" 2154"str q13, [x20, #0x0]\n" 2155"add x20, x20, %x[res_stride]\n" 2156"str q23, [x20, #0x0]\n" 2157"add x20, x20, %x[res_stride]\n" 2158"str q16, [x20, #0x0]\n" 2159"add x20, x20, %x[res_stride]\n" 2160"str q25, [x20, #0x0]\n" 2161"add x20, x20, %x[res_stride]\n" 2162"str q7, [x20, #0x0]\n" 2163"add x20, x20, %x[res_stride]\n" 2164"str q0, [x20, #0x0]\n" 2165"add x20, x20, %x[res_stride]\n" 2166"str q4, [x20, #0x0]\n" 2167"add x20, x20, %x[res_stride]\n" 2168"str q5, [x20, #0x0]\n" 2169"add x20, x20, %x[res_stride]\n" 2170"str q21, [x20, #0x0]\n" 2171"add x20, x20, %x[res_stride]\n" 2172"str q8, [x20, #0x0]\n" 2173"add x20, x20, %x[res_stride]\n" 2174"str q1, [x20, #0x0]\n" 2175"bne 2b\n" 2176"mov x20, #0x4\n" 2177"sub x10, x10, #0x10\n" 2178"cmp x10, #0x10\n" 2179"mov %x[res_ptr], x26\n" 2180"madd %x[a_ptr], x20, x9, %x[a_ptr]\n" 2181"bge 1b\n" 2182"4:" // Row loop skip 2183"cbz x10, 9f\n" 2184"5:" // Row tail: Row loop 2185"add x24, %x[b_ptr], #0x8\n" 2186"mov x23, %x[nc]\n" 2187"add x22, %x[res_ptr], %x[res_stride], LSL #2\n" 2188"6:" // Row tail: Column loop 2189"movi v15.16b, #0x0\n" 2190"movi v19.16b, #0x0\n" 2191"add x25, %x[a_ptr], #0x8\n" 2192"mov x21, %x[nb]\n" 2193"movi v18.16b, #0x0\n" 2194"movi v14.16b, #0x0\n" 2195"7:" // Row tail: Block loop 2196"ldr q7, [x24, #0x0]\n" 2197"ldr q5, [x25, #0x0]\n" 2198"movi v9.16b, #0x4\n" 2199"movi v4.4s, #0x0\n" 2200"ldr q3, [x24, #0x10]\n" 2201"ldr q2, [x25, #0x10]\n" 2202"movi v1.4s, #0x0\n" 2203"movi v0.4s, #0x0\n" 2204"ldr q13, [x24, #0x20]\n" 2205"ldr q31, [x25, #0x20]\n" 2206"movi v30.4s, #0x0\n" 2207"movi v29.16b, #0xf0\n" 2208"ldr q28, [x24, #0x30]\n" 2209"ldr q27, [x25, #0x30]\n" 2210"sshl v20.16b, v7.16b, v9.16b\n" 2211"sub x20, x24, #0x8\n" 2212"ldr q26, [x25, #0x40]\n" 2213"ldr q25, [x25, #0x50]\n" 2214"sshl v17.16b, v3.16b, v9.16b\n" 2215"and v7.16b, v7.16b, v29.16b\n" 2216"ldr q24, [x25, #0x60]\n" 2217"ldr q16, [x25, #0x70]\n" 2218"sshl v22.16b, v13.16b, v9.16b\n" 2219"and v3.16b, v3.16b, v29.16b\n" 2220"ldr d21, [x20, #0x0]\n" 2221"ldr d12, [x25, #-0x8]\n" 2222".inst 0x4f85e284 // sdot v4.4s, v20.16b, v5.4b[0]\n" 2223".inst 0x4fa5e281 // sdot v1.4s, v20.16b, v5.4b[1]\n" 2224".inst 0x4f85ea80 // sdot v0.4s, v20.16b, v5.4b[2]\n" 2225".inst 0x4fa5ea9e // sdot v30.4s, v20.16b, v5.4b[3]\n" 2226"sshl v9.16b, v28.16b, v9.16b\n" 2227"subs x21, x21, #0x1\n" 2228"and v13.16b, v13.16b, v29.16b\n" 2229"and v28.16b, v28.16b, v29.16b\n" 2230"add x25, x25, #0x88\n" 2231"add x24, x24, #0x48\n" 2232"fcvtl v21.4s, v21.4h\n" 2233"fcvtl v12.4s, v12.4h\n" 2234".inst 0x4f82e224 // sdot v4.4s, v17.16b, v2.4b[0]\n" 2235".inst 0x4fa2e221 // sdot v1.4s, v17.16b, v2.4b[1]\n" 2236".inst 0x4f82ea20 // sdot v0.4s, v17.16b, v2.4b[2]\n" 2237".inst 0x4fa2ea3e // sdot v30.4s, v17.16b, v2.4b[3]\n" 2238"fmul v11.4s, v21.4s, v12.s[0]\n" 2239"fmul v23.4s, v21.4s, v12.s[1]\n" 2240"fmul v17.4s, v21.4s, v12.s[2]\n" 2241".inst 0x4f9fe2c4 // sdot v4.4s, v22.16b, v31.4b[0]\n" 2242"fmul v6.4s, v21.4s, v12.s[3]\n" 2243".inst 0x4fbfe2c1 // sdot v1.4s, v22.16b, v31.4b[1]\n" 2244".inst 0x4f9feac0 // sdot v0.4s, v22.16b, v31.4b[2]\n" 2245".inst 0x4fbfeade // sdot v30.4s, v22.16b, v31.4b[3]\n" 2246".inst 0x4f9be124 // sdot v4.4s, v9.16b, v27.4b[0]\n" 2247".inst 0x4fbbe121 // sdot v1.4s, v9.16b, v27.4b[1]\n" 2248".inst 0x4f9be920 // sdot v0.4s, v9.16b, v27.4b[2]\n" 2249".inst 0x4fbbe93e // sdot v30.4s, v9.16b, v27.4b[3]\n" 2250".inst 0x4f9ae0e4 // sdot v4.4s, v7.16b, v26.4b[0]\n" 2251".inst 0x4fbae0e1 // sdot v1.4s, v7.16b, v26.4b[1]\n" 2252".inst 0x4f9ae8e0 // sdot v0.4s, v7.16b, v26.4b[2]\n" 2253".inst 0x4fbae8fe // sdot v30.4s, v7.16b, v26.4b[3]\n" 2254".inst 0x4f99e064 // sdot v4.4s, v3.16b, v25.4b[0]\n" 2255".inst 0x4fb9e061 // sdot v1.4s, v3.16b, v25.4b[1]\n" 2256".inst 0x4f99e860 // sdot v0.4s, v3.16b, v25.4b[2]\n" 2257".inst 0x4fb9e87e // sdot v30.4s, v3.16b, v25.4b[3]\n" 2258".inst 0x4f98e1a4 // sdot v4.4s, v13.16b, v24.4b[0]\n" 2259".inst 0x4fb8e1a1 // sdot v1.4s, v13.16b, v24.4b[1]\n" 2260".inst 0x4f98e9a0 // sdot v0.4s, v13.16b, v24.4b[2]\n" 2261".inst 0x4fb8e9be // sdot v30.4s, v13.16b, v24.4b[3]\n" 2262".inst 0x4f90e384 // sdot v4.4s, v28.16b, v16.4b[0]\n" 2263".inst 0x4fb0e381 // sdot v1.4s, v28.16b, v16.4b[1]\n" 2264".inst 0x4f90eb80 // sdot v0.4s, v28.16b, v16.4b[2]\n" 2265".inst 0x4fb0eb9e // sdot v30.4s, v28.16b, v16.4b[3]\n" 2266"scvtf v4.4s, v4.4s, #0x4\n" 2267"scvtf v1.4s, v1.4s, #0x4\n" 2268"scvtf v0.4s, v0.4s, #0x4\n" 2269"fmla v15.4s, v4.4s, v11.4s\n" 2270"scvtf v30.4s, v30.4s, #0x4\n" 2271"fmla v19.4s, v1.4s, v23.4s\n" 2272"fmla v18.4s, v0.4s, v17.4s\n" 2273"fmla v14.4s, v30.4s, v6.4s\n" 2274"bgt 7b\n" 2275"mov x20, %x[res_ptr]\n" 2276"cmp x10, #0x1\n" 2277"str q15, [x20, #0x0]\n" 2278"add x20, x20, %x[res_stride]\n" 2279"ble 8f\n" 2280"cmp x10, #0x2\n" 2281"str q19, [x20, #0x0]\n" 2282"add x20, x20, %x[res_stride]\n" 2283"ble 8f\n" 2284"cmp x10, #0x3\n" 2285"str q18, [x20, #0x0]\n" 2286"add x20, x20, %x[res_stride]\n" 2287"ble 8f\n" 2288"str q14, [x20, #0x0]\n" 2289"8:" // Row tail: Accumulator store skip 2290"subs x23, x23, #0x4\n" 2291"add %x[res_ptr], %x[res_ptr], #0x10\n" 2292"bne 6b\n" 2293"subs x10, x10, #0x4\n" 2294"add %x[a_ptr], %x[a_ptr], x9\n" 2295"mov %x[res_ptr], x22\n" 2296"bgt 5b\n" 2297"9:" // Row tail: Row loop skip 2298 : [a_ptr ]"+&r" (a_ptr ), [res_ptr ]"+&r" (res_ptr ) 2299 : [b_ptr ]"r" (b_ptr ), [nr ]"r" (nr ), [nb ]"r" (nb ), [res_stride ]"r" (res_stride ), [nc ]"r" (nc ) 2300 :"cc" ,"memory" ,"v0" ,"v1" ,"v2" ,"v3" ,"v4" ,"v5" ,"v6" ,"v7" ,"v8" ,"v9" ,"v10" ,"v11" ,"v12" ,"v13" ,"v14" ,"v15" ,"v16" ,"v17" ,"v18" ,"v19" ,"v20" ,"v21" ,"v22" ,"v23" ,"v24" ,"v25" ,"v26" ,"v27" ,"v28" ,"v29" ,"v30" ,"v31" ,"x9" ,"x10" ,"x20" ,"x21" ,"x22" ,"x23" ,"x24" ,"x25" ,"x26" ,"x27" ,"x28" 2301 ); 2302return ; 2303#endif // #if ! ((defined(_MSC_VER)) && ! defined(__clang__)) && defined(__aarch64__) && defined(__ARM_NEON) 2304ggml_gemm_q4_0_4x4_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 2305} 2306 2307void ggml_gemm_q4_0_4x8_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 2308const int qk = QK8_0 ; 2309const int nb = n /qk ; 2310const int ncols_interleaved = 4 ; 2311const int blocklen = 8 ; 2312 2313assert (n %qk == 0 ); 2314assert (nr %4 == 0 ); 2315assert (nc %ncols_interleaved == 0 ); 2316 2317UNUSED (s ); 2318UNUSED (bs ); 2319UNUSED (vx ); 2320UNUSED (vy ); 2321UNUSED (nr ); 2322UNUSED (nc ); 2323UNUSED (nb ); 2324UNUSED (ncols_interleaved ); 2325UNUSED (blocklen ); 2326 2327#if ! ((defined(_MSC_VER ))&& ! defined(__clang__ ))&& defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_MATMUL_INT8 ) 2328const void * b_ptr = vx ; 2329const void * a_ptr = vy ; 2330float * res_ptr = s ; 2331size_t res_stride = bs * sizeof (float ); 2332 2333 __asm__ __volatile__( 2334"mov x10, %x[nr]\n" 2335"mov x9, #0x88\n" 2336"cmp x10, #0x10\n" 2337"mul x9, %x[nb], x9\n" 2338"blt 4f\n" 2339"1:" // Row loop 2340"add x28, %x[b_ptr], #0x8\n" 2341"mov x27, %x[nc]\n" 2342"add x26, %x[res_ptr], %x[res_stride], LSL #4\n" 2343"2:" // Column loop 2344"add x25, %x[a_ptr], #0x8\n" 2345"movi v2.16b, #0x0\n" 2346"movi v10.16b, #0x0\n" 2347"mov x24, %x[nb]\n" 2348"add x23, x25, x9\n" 2349"movi v12.16b, #0x0\n" 2350"movi v28.16b, #0x0\n" 2351"add x22, x23, x9\n" 2352"movi v11.16b, #0x0\n" 2353"movi v13.16b, #0x0\n" 2354"add x21, x22, x9\n" 2355"movi v22.16b, #0x0\n" 2356"movi v23.16b, #0x0\n" 2357"movi v25.16b, #0x0\n" 2358"movi v5.16b, #0x0\n" 2359"movi v7.16b, #0x0\n" 2360"movi v4.16b, #0x0\n" 2361"movi v6.16b, #0x0\n" 2362"movi v30.16b, #0x0\n" 2363"movi v24.16b, #0x0\n" 2364"movi v14.16b, #0x0\n" 2365"3:" // Block loop 2366"ldr q21, [x28, #0x0]\n" 2367"ldr q16, [x28, #0x10]\n" 2368"movi v1.16b, #0x4\n" 2369"movi v19.4s, #0x0\n" 2370"ldr q27, [x25, #0x0]\n" 2371"ldr q15, [x25, #0x10]\n" 2372"movi v26.4s, #0x0\n" 2373"movi v18.4s, #0x0\n" 2374"ldr q29, [x28, #0x20]\n" 2375"ldr q3, [x28, #0x30]\n" 2376"movi v17.4s, #0x0\n" 2377"movi v0.16b, #0xf0\n" 2378"ldr d20, [x25, #-0x8]\n" 2379"ldr d9, [x23, #-0x8]\n" 2380"sshl v8.16b, v21.16b, v1.16b\n" 2381"sshl v31.16b, v16.16b, v1.16b\n" 2382"and v21.16b, v21.16b, v0.16b\n" 2383"and v16.16b, v16.16b, v0.16b\n" 2384"sub x20, x28, #0x8\n" 2385"subs x24, x24, #0x1\n" 2386"add x28, x28, #0x48\n" 2387".inst 0x4e88a773 // smmla v19.4s, v27.16b, v8.16b\n" 2388".inst 0x4e9fa77a // smmla v26.4s, v27.16b, v31.16b\n" 2389"ldr q27, [x25, #0x20]\n" 2390".inst 0x4e88a5f2 // smmla v18.4s, v15.16b, v8.16b\n" 2391".inst 0x4e9fa5f1 // smmla v17.4s, v15.16b, v31.16b\n" 2392"sshl v15.16b, v29.16b, v1.16b\n" 2393"sshl v1.16b, v3.16b, v1.16b\n" 2394"and v29.16b, v29.16b, v0.16b\n" 2395"and v3.16b, v3.16b, v0.16b\n" 2396"ldr q0, [x25, #0x30]\n" 2397"fcvtl v20.4s, v20.4h\n" 2398".inst 0x4e8fa773 // smmla v19.4s, v27.16b, v15.16b\n" 2399"fcvtl v9.4s, v9.4h\n" 2400".inst 0x4e81a77a // smmla v26.4s, v27.16b, v1.16b\n" 2401"ldr q27, [x25, #0x40]\n" 2402".inst 0x4e8fa412 // smmla v18.4s, v0.16b, v15.16b\n" 2403".inst 0x4e81a411 // smmla v17.4s, v0.16b, v1.16b\n" 2404"ldr q0, [x25, #0x50]\n" 2405".inst 0x4e95a773 // smmla v19.4s, v27.16b, v21.16b\n" 2406".inst 0x4e90a77a // smmla v26.4s, v27.16b, v16.16b\n" 2407"ldr q27, [x25, #0x60]\n" 2408".inst 0x4e95a412 // smmla v18.4s, v0.16b, v21.16b\n" 2409".inst 0x4e90a411 // smmla v17.4s, v0.16b, v16.16b\n" 2410"ldr q0, [x25, #0x70]\n" 2411"add x25, x25, #0x88\n" 2412".inst 0x4e9da773 // smmla v19.4s, v27.16b, v29.16b\n" 2413".inst 0x4e83a77a // smmla v26.4s, v27.16b, v3.16b\n" 2414"ldr d27, [x20, #0x0]\n" 2415".inst 0x4e9da412 // smmla v18.4s, v0.16b, v29.16b\n" 2416".inst 0x4e83a411 // smmla v17.4s, v0.16b, v3.16b\n" 2417"fcvtl v27.4s, v27.4h\n" 2418"uzp1 v0.2d, v19.2d, v26.2d\n" 2419"uzp2 v26.2d, v19.2d, v26.2d\n" 2420"fmul v19.4s, v27.4s, v20.s[0]\n" 2421"scvtf v0.4s, v0.4s, #0x4\n" 2422"scvtf v26.4s, v26.4s, #0x4\n" 2423"fmla v2.4s, v0.4s, v19.4s\n" 2424"ldr q19, [x23, #0x0]\n" 2425"uzp1 v0.2d, v18.2d, v17.2d\n" 2426"uzp2 v18.2d, v18.2d, v17.2d\n" 2427"fmul v17.4s, v27.4s, v20.s[1]\n" 2428"scvtf v0.4s, v0.4s, #0x4\n" 2429"scvtf v18.4s, v18.4s, #0x4\n" 2430"fmla v10.4s, v26.4s, v17.4s\n" 2431"ldr q17, [x23, #0x10]\n" 2432"fmul v26.4s, v27.4s, v20.s[2]\n" 2433"fmul v20.4s, v27.4s, v20.s[3]\n" 2434"fmla v12.4s, v0.4s, v26.4s\n" 2435"ldr d0, [x22, #-0x8]\n" 2436"ldr d26, [x21, #-0x8]\n" 2437"fcvtl v0.4s, v0.4h\n" 2438"fmla v28.4s, v18.4s, v20.4s\n" 2439"movi v20.4s, #0x0\n" 2440"movi v18.4s, #0x0\n" 2441".inst 0x4e88a674 // smmla v20.4s, v19.16b, v8.16b\n" 2442".inst 0x4e9fa672 // smmla v18.4s, v19.16b, v31.16b\n" 2443"ldr q19, [x23, #0x20]\n" 2444"fcvtl v26.4s, v26.4h\n" 2445".inst 0x4e8fa674 // smmla v20.4s, v19.16b, v15.16b\n" 2446".inst 0x4e81a672 // smmla v18.4s, v19.16b, v1.16b\n" 2447"ldr q19, [x23, #0x40]\n" 2448".inst 0x4e95a674 // smmla v20.4s, v19.16b, v21.16b\n" 2449".inst 0x4e90a672 // smmla v18.4s, v19.16b, v16.16b\n" 2450"ldr q19, [x23, #0x60]\n" 2451".inst 0x4e9da674 // smmla v20.4s, v19.16b, v29.16b\n" 2452".inst 0x4e83a672 // smmla v18.4s, v19.16b, v3.16b\n" 2453"uzp1 v19.2d, v20.2d, v18.2d\n" 2454"scvtf v19.4s, v19.4s, #0x4\n" 2455"uzp2 v20.2d, v20.2d, v18.2d\n" 2456"fmul v18.4s, v27.4s, v9.s[0]\n" 2457"scvtf v20.4s, v20.4s, #0x4\n" 2458"fmla v11.4s, v19.4s, v18.4s\n" 2459"ldr q18, [x22, #0x0]\n" 2460"fmul v19.4s, v27.4s, v9.s[1]\n" 2461"fmla v13.4s, v20.4s, v19.4s\n" 2462"movi v19.4s, #0x0\n" 2463"movi v20.4s, #0x0\n" 2464".inst 0x4e88a633 // smmla v19.4s, v17.16b, v8.16b\n" 2465".inst 0x4e9fa634 // smmla v20.4s, v17.16b, v31.16b\n" 2466"ldr q17, [x23, #0x30]\n" 2467".inst 0x4e8fa633 // smmla v19.4s, v17.16b, v15.16b\n" 2468".inst 0x4e81a634 // smmla v20.4s, v17.16b, v1.16b\n" 2469"ldr q17, [x23, #0x50]\n" 2470".inst 0x4e95a633 // smmla v19.4s, v17.16b, v21.16b\n" 2471".inst 0x4e90a634 // smmla v20.4s, v17.16b, v16.16b\n" 2472"ldr q17, [x23, #0x70]\n" 2473"add x23, x23, #0x88\n" 2474".inst 0x4e9da633 // smmla v19.4s, v17.16b, v29.16b\n" 2475".inst 0x4e83a634 // smmla v20.4s, v17.16b, v3.16b\n" 2476"uzp1 v17.2d, v19.2d, v20.2d\n" 2477"scvtf v17.4s, v17.4s, #0x4\n" 2478"uzp2 v20.2d, v19.2d, v20.2d\n" 2479"fmul v19.4s, v27.4s, v9.s[2]\n" 2480"fmul v9.4s, v27.4s, v9.s[3]\n" 2481"scvtf v20.4s, v20.4s, #0x4\n" 2482"fmla v22.4s, v17.4s, v19.4s\n" 2483"ldr q17, [x22, #0x10]\n" 2484"movi v19.4s, #0x0\n" 2485".inst 0x4e88a653 // smmla v19.4s, v18.16b, v8.16b\n" 2486"fmla v23.4s, v20.4s, v9.4s\n" 2487"movi v20.4s, #0x0\n" 2488"movi v9.4s, #0x0\n" 2489".inst 0x4e9fa654 // smmla v20.4s, v18.16b, v31.16b\n" 2490"ldr q18, [x22, #0x20]\n" 2491".inst 0x4e88a629 // smmla v9.4s, v17.16b, v8.16b\n" 2492".inst 0x4e8fa653 // smmla v19.4s, v18.16b, v15.16b\n" 2493".inst 0x4e81a654 // smmla v20.4s, v18.16b, v1.16b\n" 2494"ldr q18, [x22, #0x40]\n" 2495".inst 0x4e95a653 // smmla v19.4s, v18.16b, v21.16b\n" 2496".inst 0x4e90a654 // smmla v20.4s, v18.16b, v16.16b\n" 2497"ldr q18, [x22, #0x60]\n" 2498".inst 0x4e9da653 // smmla v19.4s, v18.16b, v29.16b\n" 2499".inst 0x4e83a654 // smmla v20.4s, v18.16b, v3.16b\n" 2500"movi v18.4s, #0x0\n" 2501".inst 0x4e9fa632 // smmla v18.4s, v17.16b, v31.16b\n" 2502"ldr q17, [x22, #0x30]\n" 2503".inst 0x4e8fa629 // smmla v9.4s, v17.16b, v15.16b\n" 2504".inst 0x4e81a632 // smmla v18.4s, v17.16b, v1.16b\n" 2505"ldr q17, [x22, #0x50]\n" 2506".inst 0x4e95a629 // smmla v9.4s, v17.16b, v21.16b\n" 2507".inst 0x4e90a632 // smmla v18.4s, v17.16b, v16.16b\n" 2508"ldr q17, [x22, #0x70]\n" 2509"add x22, x22, #0x88\n" 2510".inst 0x4e9da629 // smmla v9.4s, v17.16b, v29.16b\n" 2511".inst 0x4e83a632 // smmla v18.4s, v17.16b, v3.16b\n" 2512"uzp1 v17.2d, v19.2d, v20.2d\n" 2513"uzp2 v20.2d, v19.2d, v20.2d\n" 2514"fmul v19.4s, v27.4s, v0.s[0]\n" 2515"scvtf v17.4s, v17.4s, #0x4\n" 2516"scvtf v20.4s, v20.4s, #0x4\n" 2517"fmla v25.4s, v17.4s, v19.4s\n" 2518"ldr q19, [x21, #0x0]\n" 2519"fmul v17.4s, v27.4s, v0.s[1]\n" 2520"fmla v5.4s, v20.4s, v17.4s\n" 2521"ldr q17, [x21, #0x10]\n" 2522"uzp1 v20.2d, v9.2d, v18.2d\n" 2523"uzp2 v9.2d, v9.2d, v18.2d\n" 2524"fmul v18.4s, v27.4s, v0.s[2]\n" 2525"fmul v0.4s, v27.4s, v0.s[3]\n" 2526"scvtf v20.4s, v20.4s, #0x4\n" 2527"scvtf v9.4s, v9.4s, #0x4\n" 2528"fmla v7.4s, v20.4s, v18.4s\n" 2529"movi v20.4s, #0x0\n" 2530"movi v18.4s, #0x0\n" 2531".inst 0x4e88a674 // smmla v20.4s, v19.16b, v8.16b\n" 2532".inst 0x4e9fa672 // smmla v18.4s, v19.16b, v31.16b\n" 2533"ldr q19, [x21, #0x20]\n" 2534"fmla v4.4s, v9.4s, v0.4s\n" 2535"movi v9.4s, #0x0\n" 2536"movi v0.4s, #0x0\n" 2537".inst 0x4e88a629 // smmla v9.4s, v17.16b, v8.16b\n" 2538"fmul v8.4s, v27.4s, v26.s[0]\n" 2539".inst 0x4e9fa620 // smmla v0.4s, v17.16b, v31.16b\n" 2540"ldr q17, [x21, #0x30]\n" 2541".inst 0x4e8fa674 // smmla v20.4s, v19.16b, v15.16b\n" 2542"fmul v31.4s, v27.4s, v26.s[1]\n" 2543".inst 0x4e81a672 // smmla v18.4s, v19.16b, v1.16b\n" 2544"ldr q19, [x21, #0x40]\n" 2545".inst 0x4e8fa629 // smmla v9.4s, v17.16b, v15.16b\n" 2546"fmul v15.4s, v27.4s, v26.s[2]\n" 2547"fmul v27.4s, v27.4s, v26.s[3]\n" 2548".inst 0x4e81a620 // smmla v0.4s, v17.16b, v1.16b\n" 2549"ldr q1, [x21, #0x50]\n" 2550".inst 0x4e95a674 // smmla v20.4s, v19.16b, v21.16b\n" 2551".inst 0x4e90a672 // smmla v18.4s, v19.16b, v16.16b\n" 2552"ldr q26, [x21, #0x60]\n" 2553".inst 0x4e95a429 // smmla v9.4s, v1.16b, v21.16b\n" 2554".inst 0x4e90a420 // smmla v0.4s, v1.16b, v16.16b\n" 2555"ldr q21, [x21, #0x70]\n" 2556"add x21, x21, #0x88\n" 2557".inst 0x4e9da754 // smmla v20.4s, v26.16b, v29.16b\n" 2558".inst 0x4e83a752 // smmla v18.4s, v26.16b, v3.16b\n" 2559".inst 0x4e9da6a9 // smmla v9.4s, v21.16b, v29.16b\n" 2560".inst 0x4e83a6a0 // smmla v0.4s, v21.16b, v3.16b\n" 2561"uzp1 v29.2d, v20.2d, v18.2d\n" 2562"uzp2 v21.2d, v20.2d, v18.2d\n" 2563"scvtf v29.4s, v29.4s, #0x4\n" 2564"uzp1 v18.2d, v9.2d, v0.2d\n" 2565"uzp2 v16.2d, v9.2d, v0.2d\n" 2566"scvtf v21.4s, v21.4s, #0x4\n" 2567"fmla v6.4s, v29.4s, v8.4s\n" 2568"scvtf v18.4s, v18.4s, #0x4\n" 2569"scvtf v16.4s, v16.4s, #0x4\n" 2570"fmla v30.4s, v21.4s, v31.4s\n" 2571"fmla v24.4s, v18.4s, v15.4s\n" 2572"fmla v14.4s, v16.4s, v27.4s\n" 2573"bgt 3b\n" 2574"mov x20, %x[res_ptr]\n" 2575"subs x27, x27, #0x4\n" 2576"add %x[res_ptr], %x[res_ptr], #0x10\n" 2577"str q2, [x20, #0x0]\n" 2578"add x20, x20, %x[res_stride]\n" 2579"str q10, [x20, #0x0]\n" 2580"add x20, x20, %x[res_stride]\n" 2581"str q12, [x20, #0x0]\n" 2582"add x20, x20, %x[res_stride]\n" 2583"str q28, [x20, #0x0]\n" 2584"add x20, x20, %x[res_stride]\n" 2585"str q11, [x20, #0x0]\n" 2586"add x20, x20, %x[res_stride]\n" 2587"str q13, [x20, #0x0]\n" 2588"add x20, x20, %x[res_stride]\n" 2589"str q22, [x20, #0x0]\n" 2590"add x20, x20, %x[res_stride]\n" 2591"str q23, [x20, #0x0]\n" 2592"add x20, x20, %x[res_stride]\n" 2593"str q25, [x20, #0x0]\n" 2594"add x20, x20, %x[res_stride]\n" 2595"str q5, [x20, #0x0]\n" 2596"add x20, x20, %x[res_stride]\n" 2597"str q7, [x20, #0x0]\n" 2598"add x20, x20, %x[res_stride]\n" 2599"str q4, [x20, #0x0]\n" 2600"add x20, x20, %x[res_stride]\n" 2601"str q6, [x20, #0x0]\n" 2602"add x20, x20, %x[res_stride]\n" 2603"str q30, [x20, #0x0]\n" 2604"add x20, x20, %x[res_stride]\n" 2605"str q24, [x20, #0x0]\n" 2606"add x20, x20, %x[res_stride]\n" 2607"str q14, [x20, #0x0]\n" 2608"bne 2b\n" 2609"mov x20, #0x4\n" 2610"sub x10, x10, #0x10\n" 2611"cmp x10, #0x10\n" 2612"mov %x[res_ptr], x26\n" 2613"madd %x[a_ptr], x20, x9, %x[a_ptr]\n" 2614"bge 1b\n" 2615"4:" // Row loop skip 2616"cbz x10, 9f\n" 2617"5:" // Row tail: Row loop 2618"add x24, %x[b_ptr], #0x8\n" 2619"mov x23, %x[nc]\n" 2620"add x22, %x[res_ptr], %x[res_stride], LSL #2\n" 2621"6:" // Row tail: Column loop 2622"movi v2.16b, #0x0\n" 2623"movi v10.16b, #0x0\n" 2624"add x25, %x[a_ptr], #0x8\n" 2625"mov x21, %x[nb]\n" 2626"movi v12.16b, #0x0\n" 2627"movi v28.16b, #0x0\n" 2628"7:" // Row tail: Block loop 2629"ldr q6, [x24, #0x0]\n" 2630"ldr q5, [x24, #0x10]\n" 2631"movi v17.16b, #0x4\n" 2632"movi v8.4s, #0x0\n" 2633"ldr q4, [x25, #0x0]\n" 2634"ldr q13, [x25, #0x10]\n" 2635"movi v27.4s, #0x0\n" 2636"movi v0.4s, #0x0\n" 2637"ldr q31, [x24, #0x20]\n" 2638"ldr q14, [x24, #0x30]\n" 2639"movi v29.4s, #0x0\n" 2640"movi v22.16b, #0xf0\n" 2641"ldr q11, [x25, #0x20]\n" 2642"ldr q23, [x25, #0x30]\n" 2643"sshl v21.16b, v6.16b, v17.16b\n" 2644"sshl v16.16b, v5.16b, v17.16b\n" 2645"ldr q20, [x25, #0x40]\n" 2646"ldr q26, [x25, #0x50]\n" 2647"and v6.16b, v6.16b, v22.16b\n" 2648"and v5.16b, v5.16b, v22.16b\n" 2649"ldr q25, [x25, #0x60]\n" 2650"ldr q3, [x25, #0x70]\n" 2651"sshl v19.16b, v31.16b, v17.16b\n" 2652"sshl v18.16b, v14.16b, v17.16b\n" 2653"ldr d17, [x25, #-0x8]\n" 2654".inst 0x4e95a488 // smmla v8.4s, v4.16b, v21.16b\n" 2655".inst 0x4e90a49b // smmla v27.4s, v4.16b, v16.16b\n" 2656"and v31.16b, v31.16b, v22.16b\n" 2657".inst 0x4e95a5a0 // smmla v0.4s, v13.16b, v21.16b\n" 2658".inst 0x4e90a5bd // smmla v29.4s, v13.16b, v16.16b\n" 2659"and v14.16b, v14.16b, v22.16b\n" 2660"sub x20, x24, #0x8\n" 2661"ldr d16, [x20, #0x0]\n" 2662"subs x21, x21, #0x1\n" 2663"add x25, x25, #0x88\n" 2664"fcvtl v17.4s, v17.4h\n" 2665"add x24, x24, #0x48\n" 2666".inst 0x4e93a568 // smmla v8.4s, v11.16b, v19.16b\n" 2667".inst 0x4e92a57b // smmla v27.4s, v11.16b, v18.16b\n" 2668".inst 0x4e93a6e0 // smmla v0.4s, v23.16b, v19.16b\n" 2669".inst 0x4e92a6fd // smmla v29.4s, v23.16b, v18.16b\n" 2670"fcvtl v16.4s, v16.4h\n" 2671".inst 0x4e86a688 // smmla v8.4s, v20.16b, v6.16b\n" 2672".inst 0x4e85a69b // smmla v27.4s, v20.16b, v5.16b\n" 2673"fmul v23.4s, v16.4s, v17.s[0]\n" 2674"fmul v21.4s, v16.4s, v17.s[1]\n" 2675"fmul v1.4s, v16.4s, v17.s[2]\n" 2676"fmul v20.4s, v16.4s, v17.s[3]\n" 2677".inst 0x4e86a740 // smmla v0.4s, v26.16b, v6.16b\n" 2678".inst 0x4e85a75d // smmla v29.4s, v26.16b, v5.16b\n" 2679".inst 0x4e9fa728 // smmla v8.4s, v25.16b, v31.16b\n" 2680".inst 0x4e8ea73b // smmla v27.4s, v25.16b, v14.16b\n" 2681".inst 0x4e9fa460 // smmla v0.4s, v3.16b, v31.16b\n" 2682".inst 0x4e8ea47d // smmla v29.4s, v3.16b, v14.16b\n" 2683"uzp1 v19.2d, v8.2d, v27.2d\n" 2684"uzp2 v18.2d, v8.2d, v27.2d\n" 2685"scvtf v19.4s, v19.4s, #0x4\n" 2686"uzp1 v17.2d, v0.2d, v29.2d\n" 2687"uzp2 v16.2d, v0.2d, v29.2d\n" 2688"scvtf v18.4s, v18.4s, #0x4\n" 2689"fmla v2.4s, v19.4s, v23.4s\n" 2690"scvtf v17.4s, v17.4s, #0x4\n" 2691"scvtf v16.4s, v16.4s, #0x4\n" 2692"fmla v10.4s, v18.4s, v21.4s\n" 2693"fmla v12.4s, v17.4s, v1.4s\n" 2694"fmla v28.4s, v16.4s, v20.4s\n" 2695"bgt 7b\n" 2696"mov x20, %x[res_ptr]\n" 2697"cmp x10, #0x1\n" 2698"str q2, [x20, #0x0]\n" 2699"add x20, x20, %x[res_stride]\n" 2700"ble 8f\n" 2701"cmp x10, #0x2\n" 2702"str q10, [x20, #0x0]\n" 2703"add x20, x20, %x[res_stride]\n" 2704"ble 8f\n" 2705"cmp x10, #0x3\n" 2706"str q12, [x20, #0x0]\n" 2707"add x20, x20, %x[res_stride]\n" 2708"ble 8f\n" 2709"str q28, [x20, #0x0]\n" 2710"8:" // Row tail: Accumulator store skip 2711"subs x23, x23, #0x4\n" 2712"add %x[res_ptr], %x[res_ptr], #0x10\n" 2713"bne 6b\n" 2714"subs x10, x10, #0x4\n" 2715"add %x[a_ptr], %x[a_ptr], x9\n" 2716"mov %x[res_ptr], x22\n" 2717"bgt 5b\n" 2718"9:" // Row tail: Row loop skip 2719 : [a_ptr ]"+&r" (a_ptr ), [res_ptr ]"+&r" (res_ptr ) 2720 : [b_ptr ]"r" (b_ptr ), [nr ]"r" (nr ), [nb ]"r" (nb ), [res_stride ]"r" (res_stride ), [nc ]"r" (nc ) 2721 :"cc" ,"memory" ,"v0" ,"v1" ,"v2" ,"v3" ,"v4" ,"v5" ,"v6" ,"v7" ,"v8" ,"v9" ,"v10" ,"v11" ,"v12" ,"v13" ,"v14" ,"v15" ,"v16" ,"v17" ,"v18" ,"v19" ,"v20" ,"v21" ,"v22" ,"v23" ,"v24" ,"v25" ,"v26" ,"v27" ,"v28" ,"v29" ,"v30" ,"v31" ,"x9" ,"x10" ,"x20" ,"x21" ,"x22" ,"x23" ,"x24" ,"x25" ,"x26" ,"x27" ,"x28" 2722 ); 2723return ; 2724#endif // #if ! ((defined(_MSC_VER)) && ! defined(__clang__)) && defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_MATMUL_INT8) 2725ggml_gemm_q4_0_4x8_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 2726} 2727 2728void ggml_gemm_q4_0_8x8_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 2729const int qk = QK8_0 ; 2730const int nb = n /qk ; 2731const int ncols_interleaved = 8 ; 2732const int blocklen = 8 ; 2733 2734assert (n %qk == 0 ); 2735assert (nr %4 == 0 ); 2736assert (nc %ncols_interleaved == 0 ); 2737 2738UNUSED (s ); 2739UNUSED (bs ); 2740UNUSED (vx ); 2741UNUSED (vy ); 2742UNUSED (nr ); 2743UNUSED (nc ); 2744UNUSED (nb ); 2745UNUSED (ncols_interleaved ); 2746UNUSED (blocklen ); 2747 2748#if ! ((defined(_MSC_VER ))&& ! defined(__clang__ ))&& defined(__aarch64__ ) 2749#if defined(__ARM_FEATURE_SVE )&& defined(__ARM_FEATURE_MATMUL_INT8 ) 2750if (ggml_cpu_get_sve_cnt ()== QK8_0 ) { 2751const void * b_ptr = vx ; 2752const void * a_ptr = vy ; 2753float * res_ptr = s ; 2754size_t res_stride = bs * sizeof (float ); 2755 2756 __asm__ __volatile__( 2757"mov x20, #0x4\n" 2758"mov x13, %x[nr]\n" 2759"mov z28.s, #-0x4\n" 2760"mov x12, #0x88\n" 2761"ptrue p1.b\n" 2762"whilelt p0.s, XZR, x20\n" 2763"cmp x13, #0x10\n" 2764"mul x12, %x[nb], x12\n" 2765"blt 4f\n" 2766"1:" // Row loop 2767"add x11, %x[b_ptr], #0x10\n" 2768"mov x10, %x[nc]\n" 2769"add x9, %x[res_ptr], %x[res_stride], LSL #4\n" 2770"2:" // Column loop 2771"add x28, %x[a_ptr], #0x8\n" 2772"mov z24.b, #0x0\n" 2773"mov z15.b, #0x0\n" 2774"mov x27, %x[nb]\n" 2775"add x26, x28, x12\n" 2776"mov z12.b, #0x0\n" 2777"mov z0.b, #0x0\n" 2778"add x25, x26, x12\n" 2779"mov z13.b, #0x0\n" 2780"mov z1.b, #0x0\n" 2781"add x24, x25, x12\n" 2782"mov z20.b, #0x0\n" 2783"mov z25.b, #0x0\n" 2784"mov z11.b, #0x0\n" 2785"mov z16.b, #0x0\n" 2786"mov z19.b, #0x0\n" 2787"mov z26.b, #0x0\n" 2788"mov z8.b, #0x0\n" 2789"mov z29.b, #0x0\n" 2790"mov z27.b, #0x0\n" 2791"mov z10.b, #0x0\n" 2792"3:" // Block loop 2793"ld1b { z30.b }, p1/Z, [x11]\n" 2794"ld1b { z21.b }, p1/Z, [x11, #1, MUL VL]\n" 2795"mov z18.s, #0x0\n" 2796"mov z7.s, #0x0\n" 2797"ld1rqb { z3.b }, p1/Z, [x28]\n" 2798"ld1rqb { z5.b }, p1/Z, [x28, #16]\n" 2799"mov z9.s, #0x0\n" 2800"mov z22.s, #0x0\n" 2801"ld1b { z4.b }, p1/Z, [x11, #2, MUL VL]\n" 2802"ld1b { z17.b }, p1/Z, [x11, #3, MUL VL]\n" 2803"sub x20, x11, #0x10\n" 2804"sub x23, x28, #0x8\n" 2805"lsl z31.b, z30.b, #0x4\n" 2806"lsl z6.b, z21.b, #0x4\n" 2807"ld1h { z23.s }, p1/Z, [x20]\n" 2808"sub x22, x26, #0x8\n" 2809"and z30.b, z30.b, #0xf0\n" 2810"and z21.b, z21.b, #0xf0\n" 2811"sub x21, x25, #0x8\n" 2812"sub x20, x24, #0x8\n" 2813"lsl z14.b, z4.b, #0x4\n" 2814"lsl z2.b, z17.b, #0x4\n" 2815"subs x27, x27, #0x1\n" 2816"add x11, x11, #0x90\n" 2817".inst 0x451f9872 // smmla z18.s, z3.b, z31.b\n" 2818".inst 0x45069867 // smmla z7.s, z3.b, z6.b\n" 2819"ld1rqb { z3.b }, p1/Z, [x28, #32]\n" 2820"and z4.b, z4.b, #0xf0\n" 2821".inst 0x451f98a9 // smmla z9.s, z5.b, z31.b\n" 2822".inst 0x450698b6 // smmla z22.s, z5.b, z6.b\n" 2823"ld1rqb { z5.b }, p1/Z, [x28, #48]\n" 2824"and z17.b, z17.b, #0xf0\n" 2825"fcvt z23.s, p1/m, z23.h\n" 2826".inst 0x450e9872 // smmla z18.s, z3.b, z14.b\n" 2827".inst 0x45029867 // smmla z7.s, z3.b, z2.b\n" 2828"ld1rqb { z3.b }, p1/Z, [x28, #64]\n" 2829".inst 0x450e98a9 // smmla z9.s, z5.b, z14.b\n" 2830".inst 0x450298b6 // smmla z22.s, z5.b, z2.b\n" 2831"ld1rqb { z5.b }, p1/Z, [x28, #80]\n" 2832"fscale z23.s, p1/m, z23.s, z28.s\n" 2833".inst 0x451e9872 // smmla z18.s, z3.b, z30.b\n" 2834".inst 0x45159867 // smmla z7.s, z3.b, z21.b\n" 2835"ld1rqb { z3.b }, p1/Z, [x28, #96]\n" 2836".inst 0x451e98a9 // smmla z9.s, z5.b, z30.b\n" 2837".inst 0x451598b6 // smmla z22.s, z5.b, z21.b\n" 2838"ld1rqb { z5.b }, p1/Z, [x28, #112]\n" 2839"add x28, x28, #0x88\n" 2840".inst 0x45049872 // smmla z18.s, z3.b, z4.b\n" 2841".inst 0x45119867 // smmla z7.s, z3.b, z17.b\n" 2842"ld1h { z3.s }, p0/Z, [x23]\n" 2843".inst 0x450498a9 // smmla z9.s, z5.b, z4.b\n" 2844".inst 0x451198b6 // smmla z22.s, z5.b, z17.b\n" 2845"fcvt z3.s, p1/m, z3.h\n" 2846"uzp1 z5.d, z18.d, z7.d\n" 2847"uzp2 z18.d, z18.d, z7.d\n" 2848"mov z3.q, z3.q[0]\n" 2849"uzp1 z7.d, z9.d, z22.d\n" 2850"uzp2 z22.d, z9.d, z22.d\n" 2851"fmul z9.s, z23.s, z3.s[0]\n" 2852"scvtf z5.s, p1/m, z5.s\n" 2853"scvtf z18.s, p1/m, z18.s\n" 2854"scvtf z7.s, p1/m, z7.s\n" 2855"scvtf z22.s, p1/m, z22.s\n" 2856"fmla z24.s, p1/M, z5.s, z9.s\n" 2857"ld1rqb { z5.b }, p1/Z, [x26]\n" 2858"fmul z9.s, z23.s, z3.s[1]\n" 2859"fmla z15.s, p1/M, z18.s, z9.s\n" 2860"ld1rqb { z18.b }, p1/Z, [x26, #16]\n" 2861"fmul z9.s, z23.s, z3.s[2]\n" 2862"fmul z3.s, z23.s, z3.s[3]\n" 2863"fmla z12.s, p1/M, z7.s, z9.s\n" 2864"mov z9.s, #0x0\n" 2865"ld1h { z7.s }, p0/Z, [x22]\n" 2866".inst 0x451f98a9 // smmla z9.s, z5.b, z31.b\n" 2867"fmla z0.s, p1/M, z22.s, z3.s\n" 2868"mov z22.s, #0x0\n" 2869"ld1h { z3.s }, p0/Z, [x21]\n" 2870".inst 0x450698b6 // smmla z22.s, z5.b, z6.b\n" 2871"ld1rqb { z5.b }, p1/Z, [x26, #32]\n" 2872"fcvt z7.s, p1/m, z7.h\n" 2873"fcvt z3.s, p1/m, z3.h\n" 2874".inst 0x450e98a9 // smmla z9.s, z5.b, z14.b\n" 2875".inst 0x450298b6 // smmla z22.s, z5.b, z2.b\n" 2876"ld1rqb { z5.b }, p1/Z, [x26, #64]\n" 2877"mov z7.q, z7.q[0]\n" 2878"mov z3.q, z3.q[0]\n" 2879".inst 0x451e98a9 // smmla z9.s, z5.b, z30.b\n" 2880".inst 0x451598b6 // smmla z22.s, z5.b, z21.b\n" 2881"ld1rqb { z5.b }, p1/Z, [x26, #96]\n" 2882".inst 0x450498a9 // smmla z9.s, z5.b, z4.b\n" 2883".inst 0x451198b6 // smmla z22.s, z5.b, z17.b\n" 2884"uzp1 z5.d, z9.d, z22.d\n" 2885"scvtf z5.s, p1/m, z5.s\n" 2886"uzp2 z22.d, z9.d, z22.d\n" 2887"fmul z9.s, z23.s, z7.s[0]\n" 2888"scvtf z22.s, p1/m, z22.s\n" 2889"fmla z13.s, p1/M, z5.s, z9.s\n" 2890"ld1rqb { z9.b }, p1/Z, [x25]\n" 2891"fmul z5.s, z23.s, z7.s[1]\n" 2892"fmla z1.s, p1/M, z22.s, z5.s\n" 2893"mov z5.s, #0x0\n" 2894"mov z22.s, #0x0\n" 2895".inst 0x451f9a45 // smmla z5.s, z18.b, z31.b\n" 2896".inst 0x45069a56 // smmla z22.s, z18.b, z6.b\n" 2897"ld1rqb { z18.b }, p1/Z, [x26, #48]\n" 2898".inst 0x450e9a45 // smmla z5.s, z18.b, z14.b\n" 2899".inst 0x45029a56 // smmla z22.s, z18.b, z2.b\n" 2900"ld1rqb { z18.b }, p1/Z, [x26, #80]\n" 2901".inst 0x451e9a45 // smmla z5.s, z18.b, z30.b\n" 2902".inst 0x45159a56 // smmla z22.s, z18.b, z21.b\n" 2903"ld1rqb { z18.b }, p1/Z, [x26, #112]\n" 2904"add x26, x26, #0x88\n" 2905".inst 0x45049a45 // smmla z5.s, z18.b, z4.b\n" 2906".inst 0x45119a56 // smmla z22.s, z18.b, z17.b\n" 2907"uzp1 z18.d, z5.d, z22.d\n" 2908"scvtf z18.s, p1/m, z18.s\n" 2909"uzp2 z22.d, z5.d, z22.d\n" 2910"fmul z5.s, z23.s, z7.s[2]\n" 2911"fmul z7.s, z23.s, z7.s[3]\n" 2912"scvtf z22.s, p1/m, z22.s\n" 2913"fmla z20.s, p1/M, z18.s, z5.s\n" 2914"ld1rqb { z18.b }, p1/Z, [x25, #16]\n" 2915"ld1h { z5.s }, p0/Z, [x20]\n" 2916"fcvt z5.s, p1/m, z5.h\n" 2917"fmla z25.s, p1/M, z22.s, z7.s\n" 2918"mov z22.s, #0x0\n" 2919"mov z7.s, #0x0\n" 2920".inst 0x451f9936 // smmla z22.s, z9.b, z31.b\n" 2921".inst 0x45069927 // smmla z7.s, z9.b, z6.b\n" 2922"ld1rqb { z9.b }, p1/Z, [x25, #32]\n" 2923"mov z5.q, z5.q[0]\n" 2924".inst 0x450e9936 // smmla z22.s, z9.b, z14.b\n" 2925".inst 0x45029927 // smmla z7.s, z9.b, z2.b\n" 2926"ld1rqb { z9.b }, p1/Z, [x25, #64]\n" 2927".inst 0x451e9936 // smmla z22.s, z9.b, z30.b\n" 2928".inst 0x45159927 // smmla z7.s, z9.b, z21.b\n" 2929"ld1rqb { z9.b }, p1/Z, [x25, #96]\n" 2930".inst 0x45049936 // smmla z22.s, z9.b, z4.b\n" 2931".inst 0x45119927 // smmla z7.s, z9.b, z17.b\n" 2932"uzp1 z9.d, z22.d, z7.d\n" 2933"scvtf z9.s, p1/m, z9.s\n" 2934"uzp2 z22.d, z22.d, z7.d\n" 2935"fmul z7.s, z23.s, z3.s[0]\n" 2936"scvtf z22.s, p1/m, z22.s\n" 2937"fmla z11.s, p1/M, z9.s, z7.s\n" 2938"ld1rqb { z9.b }, p1/Z, [x24]\n" 2939"fmul z7.s, z23.s, z3.s[1]\n" 2940"fmla z16.s, p1/M, z22.s, z7.s\n" 2941"mov z22.s, #0x0\n" 2942"mov z7.s, #0x0\n" 2943".inst 0x451f9a56 // smmla z22.s, z18.b, z31.b\n" 2944".inst 0x45069a47 // smmla z7.s, z18.b, z6.b\n" 2945"ld1rqb { z18.b }, p1/Z, [x25, #48]\n" 2946".inst 0x450e9a56 // smmla z22.s, z18.b, z14.b\n" 2947".inst 0x45029a47 // smmla z7.s, z18.b, z2.b\n" 2948"ld1rqb { z18.b }, p1/Z, [x25, #80]\n" 2949".inst 0x451e9a56 // smmla z22.s, z18.b, z30.b\n" 2950".inst 0x45159a47 // smmla z7.s, z18.b, z21.b\n" 2951"ld1rqb { z18.b }, p1/Z, [x25, #112]\n" 2952"add x25, x25, #0x88\n" 2953".inst 0x45049a56 // smmla z22.s, z18.b, z4.b\n" 2954".inst 0x45119a47 // smmla z7.s, z18.b, z17.b\n" 2955"uzp1 z18.d, z22.d, z7.d\n" 2956"scvtf z18.s, p1/m, z18.s\n" 2957"uzp2 z7.d, z22.d, z7.d\n" 2958"fmul z22.s, z23.s, z3.s[2]\n" 2959"fmul z3.s, z23.s, z3.s[3]\n" 2960"scvtf z7.s, p1/m, z7.s\n" 2961"fmla z19.s, p1/M, z18.s, z22.s\n" 2962"ld1rqb { z18.b }, p1/Z, [x24, #16]\n" 2963"fmul z22.s, z23.s, z5.s[0]\n" 2964"fmla z26.s, p1/M, z7.s, z3.s\n" 2965"mov z3.s, #0x0\n" 2966"mov z7.s, #0x0\n" 2967".inst 0x451f9923 // smmla z3.s, z9.b, z31.b\n" 2968".inst 0x45069927 // smmla z7.s, z9.b, z6.b\n" 2969"ld1rqb { z9.b }, p1/Z, [x24, #32]\n" 2970".inst 0x450e9923 // smmla z3.s, z9.b, z14.b\n" 2971".inst 0x45029927 // smmla z7.s, z9.b, z2.b\n" 2972"mov z9.s, #0x0\n" 2973".inst 0x451f9a49 // smmla z9.s, z18.b, z31.b\n" 2974"mov z31.s, #0x0\n" 2975".inst 0x45069a5f // smmla z31.s, z18.b, z6.b\n" 2976"ld1rqb { z6.b }, p1/Z, [x24, #48]\n" 2977"ld1rqb { z18.b }, p1/Z, [x24, #64]\n" 2978".inst 0x450e98c9 // smmla z9.s, z6.b, z14.b\n" 2979"fmul z14.s, z23.s, z5.s[1]\n" 2980".inst 0x450298df // smmla z31.s, z6.b, z2.b\n" 2981"ld1rqb { z6.b }, p1/Z, [x24, #80]\n" 2982"fmul z2.s, z23.s, z5.s[2]\n" 2983"fmul z23.s, z23.s, z5.s[3]\n" 2984".inst 0x451e9a43 // smmla z3.s, z18.b, z30.b\n" 2985".inst 0x45159a47 // smmla z7.s, z18.b, z21.b\n" 2986"ld1rqb { z5.b }, p1/Z, [x24, #96]\n" 2987".inst 0x451e98c9 // smmla z9.s, z6.b, z30.b\n" 2988".inst 0x451598df // smmla z31.s, z6.b, z21.b\n" 2989"ld1rqb { z18.b }, p1/Z, [x24, #112]\n" 2990"add x24, x24, #0x88\n" 2991".inst 0x450498a3 // smmla z3.s, z5.b, z4.b\n" 2992".inst 0x451198a7 // smmla z7.s, z5.b, z17.b\n" 2993".inst 0x45049a49 // smmla z9.s, z18.b, z4.b\n" 2994".inst 0x45119a5f // smmla z31.s, z18.b, z17.b\n" 2995"uzp1 z18.d, z3.d, z7.d\n" 2996"uzp2 z5.d, z3.d, z7.d\n" 2997"scvtf z18.s, p1/m, z18.s\n" 2998"uzp1 z6.d, z9.d, z31.d\n" 2999"uzp2 z9.d, z9.d, z31.d\n" 3000"scvtf z5.s, p1/m, z5.s\n" 3001"fmla z8.s, p1/M, z18.s, z22.s\n" 3002"scvtf z6.s, p1/m, z6.s\n" 3003"scvtf z9.s, p1/m, z9.s\n" 3004"fmla z29.s, p1/M, z5.s, z14.s\n" 3005"fmla z27.s, p1/M, z6.s, z2.s\n" 3006"fmla z10.s, p1/M, z9.s, z23.s\n" 3007"bgt 3b\n" 3008"mov x20, %x[res_ptr]\n" 3009"subs x10, x10, #0x8\n" 3010"add %x[res_ptr], %x[res_ptr], #0x20\n" 3011"st1w { z24.s }, p1, [x20]\n" 3012"add x20, x20, %x[res_stride]\n" 3013"st1w { z15.s }, p1, [x20]\n" 3014"add x20, x20, %x[res_stride]\n" 3015"st1w { z12.s }, p1, [x20]\n" 3016"add x20, x20, %x[res_stride]\n" 3017"st1w { z0.s }, p1, [x20]\n" 3018"add x20, x20, %x[res_stride]\n" 3019"st1w { z13.s }, p1, [x20]\n" 3020"add x20, x20, %x[res_stride]\n" 3021"st1w { z1.s }, p1, [x20]\n" 3022"add x20, x20, %x[res_stride]\n" 3023"st1w { z20.s }, p1, [x20]\n" 3024"add x20, x20, %x[res_stride]\n" 3025"st1w { z25.s }, p1, [x20]\n" 3026"add x20, x20, %x[res_stride]\n" 3027"st1w { z11.s }, p1, [x20]\n" 3028"add x20, x20, %x[res_stride]\n" 3029"st1w { z16.s }, p1, [x20]\n" 3030"add x20, x20, %x[res_stride]\n" 3031"st1w { z19.s }, p1, [x20]\n" 3032"add x20, x20, %x[res_stride]\n" 3033"st1w { z26.s }, p1, [x20]\n" 3034"add x20, x20, %x[res_stride]\n" 3035"st1w { z8.s }, p1, [x20]\n" 3036"add x20, x20, %x[res_stride]\n" 3037"st1w { z29.s }, p1, [x20]\n" 3038"add x20, x20, %x[res_stride]\n" 3039"st1w { z27.s }, p1, [x20]\n" 3040"add x20, x20, %x[res_stride]\n" 3041"st1w { z10.s }, p1, [x20]\n" 3042"bne 2b\n" 3043"mov x20, #0x4\n" 3044"sub x13, x13, #0x10\n" 3045"cmp x13, #0x10\n" 3046"mov %x[res_ptr], x9\n" 3047"madd %x[a_ptr], x20, x12, %x[a_ptr]\n" 3048"bge 1b\n" 3049"4:" // Row loop skip 3050"cbz x13, 9f\n" 3051"5:" // Row tail: Row loop 3052"add x25, %x[b_ptr], #0x10\n" 3053"mov x24, %x[nc]\n" 3054"add x23, %x[res_ptr], %x[res_stride], LSL #2\n" 3055"6:" // Row tail: Column loop 3056"mov z24.b, #0x0\n" 3057"mov z15.b, #0x0\n" 3058"add x28, %x[a_ptr], #0x8\n" 3059"mov x22, %x[nb]\n" 3060"mov z12.b, #0x0\n" 3061"mov z0.b, #0x0\n" 3062"7:" // Row tail: Block loop 3063"ld1b { z3.b }, p1/Z, [x25]\n" 3064"ld1b { z6.b }, p1/Z, [x25, #1, MUL VL]\n" 3065"mov z2.s, #0x0\n" 3066"mov z25.s, #0x0\n" 3067"ld1rqb { z26.b }, p1/Z, [x28]\n" 3068"ld1rqb { z21.b }, p1/Z, [x28, #16]\n" 3069"mov z27.s, #0x0\n" 3070"mov z19.s, #0x0\n" 3071"ld1b { z29.b }, p1/Z, [x25, #2, MUL VL]\n" 3072"ld1b { z16.b }, p1/Z, [x25, #3, MUL VL]\n" 3073"sub x21, x25, #0x10\n" 3074"sub x20, x28, #0x8\n" 3075"lsl z20.b, z3.b, #0x4\n" 3076"lsl z4.b, z6.b, #0x4\n" 3077"ld1rqb { z10.b }, p1/Z, [x28, #32]\n" 3078"ld1rqb { z23.b }, p1/Z, [x28, #48]\n" 3079"and z3.b, z3.b, #0xf0\n" 3080"and z6.b, z6.b, #0xf0\n" 3081"ld1rqb { z11.b }, p1/Z, [x28, #64]\n" 3082"ld1rqb { z7.b }, p1/Z, [x28, #80]\n" 3083"lsl z8.b, z29.b, #0x4\n" 3084"lsl z14.b, z16.b, #0x4\n" 3085"ld1rqb { z18.b }, p1/Z, [x28, #96]\n" 3086"ld1rqb { z30.b }, p1/Z, [x28, #112]\n" 3087".inst 0x45149b42 // smmla z2.s, z26.b, z20.b\n" 3088".inst 0x45049b59 // smmla z25.s, z26.b, z4.b\n" 3089"and z29.b, z29.b, #0xf0\n" 3090"ld1h { z17.s }, p1/Z, [x21]\n" 3091".inst 0x45149abb // smmla z27.s, z21.b, z20.b\n" 3092".inst 0x45049ab3 // smmla z19.s, z21.b, z4.b\n" 3093"and z16.b, z16.b, #0xf0\n" 3094"ld1h { z4.s }, p0/Z, [x20]\n" 3095"subs x22, x22, #0x1\n" 3096"add x28, x28, #0x88\n" 3097"fcvt z17.s, p1/m, z17.h\n" 3098"add x25, x25, #0x90\n" 3099".inst 0x45089942 // smmla z2.s, z10.b, z8.b\n" 3100".inst 0x450e9959 // smmla z25.s, z10.b, z14.b\n" 3101"fcvt z4.s, p1/m, z4.h\n" 3102".inst 0x45089afb // smmla z27.s, z23.b, z8.b\n" 3103".inst 0x450e9af3 // smmla z19.s, z23.b, z14.b\n" 3104"fscale z17.s, p1/m, z17.s, z28.s\n" 3105"mov z4.q, z4.q[0]\n" 3106".inst 0x45039962 // smmla z2.s, z11.b, z3.b\n" 3107".inst 0x45069979 // smmla z25.s, z11.b, z6.b\n" 3108"fmul z23.s, z17.s, z4.s[0]\n" 3109"fmul z9.s, z17.s, z4.s[1]\n" 3110"fmul z21.s, z17.s, z4.s[2]\n" 3111"fmul z4.s, z17.s, z4.s[3]\n" 3112".inst 0x450398fb // smmla z27.s, z7.b, z3.b\n" 3113".inst 0x450698f3 // smmla z19.s, z7.b, z6.b\n" 3114".inst 0x451d9a42 // smmla z2.s, z18.b, z29.b\n" 3115".inst 0x45109a59 // smmla z25.s, z18.b, z16.b\n" 3116".inst 0x451d9bdb // smmla z27.s, z30.b, z29.b\n" 3117".inst 0x45109bd3 // smmla z19.s, z30.b, z16.b\n" 3118"uzp1 z31.d, z2.d, z25.d\n" 3119"uzp2 z13.d, z2.d, z25.d\n" 3120"scvtf z31.s, p1/m, z31.s\n" 3121"uzp1 z17.d, z27.d, z19.d\n" 3122"uzp2 z18.d, z27.d, z19.d\n" 3123"scvtf z13.s, p1/m, z13.s\n" 3124"fmla z24.s, p1/M, z31.s, z23.s\n" 3125"scvtf z17.s, p1/m, z17.s\n" 3126"scvtf z18.s, p1/m, z18.s\n" 3127"fmla z15.s, p1/M, z13.s, z9.s\n" 3128"fmla z12.s, p1/M, z17.s, z21.s\n" 3129"fmla z0.s, p1/M, z18.s, z4.s\n" 3130"bgt 7b\n" 3131"mov x20, %x[res_ptr]\n" 3132"cmp x13, #0x1\n" 3133"st1w { z24.s }, p1, [x20]\n" 3134"add x20, x20, %x[res_stride]\n" 3135"ble 8f\n" 3136"cmp x13, #0x2\n" 3137"st1w { z15.s }, p1, [x20]\n" 3138"add x20, x20, %x[res_stride]\n" 3139"ble 8f\n" 3140"cmp x13, #0x3\n" 3141"st1w { z12.s }, p1, [x20]\n" 3142"add x20, x20, %x[res_stride]\n" 3143"ble 8f\n" 3144"st1w { z0.s }, p1, [x20]\n" 3145"8:" // Row tail: Accumulator store skip 3146"subs x24, x24, #0x8\n" 3147"add %x[res_ptr], %x[res_ptr], #0x20\n" 3148"bne 6b\n" 3149"subs x13, x13, #0x4\n" 3150"add %x[a_ptr], %x[a_ptr], x12\n" 3151"mov %x[res_ptr], x23\n" 3152"bgt 5b\n" 3153"9:" // Row tail: Row loop skip 3154 : [a_ptr ]"+&r" (a_ptr ), [res_ptr ]"+&r" (res_ptr ) 3155 : [b_ptr ]"r" (b_ptr ), [nr ]"r" (nr ), [nb ]"r" (nb ), [res_stride ]"r" (res_stride ), [nc ]"r" (nc ) 3156 :"cc" ,"memory" ,"p0" ,"p1" ,"x9" ,"x10" ,"x11" ,"x12" ,"x13" ,"x20" ,"x21" ,"x22" ,"x23" ,"x24" ,"x25" ,"x26" ,"x27" ,"x28" ,"z0" ,"z1" ,"z2" ,"z3" ,"z4" ,"z5" ,"z6" ,"z7" ,"z8" ,"z9" ,"z10" ,"z11" ,"z12" ,"z13" ,"z14" ,"z15" ,"z16" ,"z17" ,"z18" ,"z19" ,"z20" ,"z21" ,"z22" ,"z23" ,"z24" ,"z25" ,"z26" ,"z27" ,"z28" ,"z29" ,"z30" ,"z31" 3157 ); 3158return ; 3159 } 3160#endif // #if defined(__ARM_FEATURE_SVE) && defined(__ARM_FEATURE_MATMUL_INT8) 3161 3162#endif // #if ! ((defined(_MSC_VER)) && ! defined(__clang__)) && defined(__aarch64__) 3163ggml_gemm_q4_0_8x8_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 3164} 3165 3166void ggml_gemm_iq4_nl_4x4_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 3167const int qk = QK8_0 ; 3168const int nb = n /qk ; 3169const int ncols_interleaved = 4 ; 3170const int blocklen = 4 ; 3171 3172assert (n %qk == 0 ); 3173assert (nr %4 == 0 ); 3174assert (nc %ncols_interleaved == 0 ); 3175 3176UNUSED (s ); 3177UNUSED (bs ); 3178UNUSED (vx ); 3179UNUSED (vy ); 3180UNUSED (nr ); 3181UNUSED (nc ); 3182UNUSED (nb ); 3183UNUSED (ncols_interleaved ); 3184UNUSED (blocklen ); 3185 3186#if ! ((defined(_MSC_VER ))&& ! defined(__clang__ ))&& defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 3187const int8x16_t kvalues = vld1q_s8 (kvalues_iq4nl ); 3188 3189for (int y = 0 ;y < nr /4 ;y ++ ) { 3190const block_q8_0x4 * a_ptr = (const block_q8_0x4 * )vy + (y * nb ); 3191for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 3192const block_iq4_nlx4 * b_ptr = (const block_iq4_nlx4 * )vx + (x * nb ); 3193 3194float32x4_t sumf [4 ]; 3195for (int m = 0 ;m < 4 ;m ++ ) { 3196sumf [m ]= vdupq_n_f32 (0 ); 3197 } 3198 3199for (int l = 0 ;l < nb ;l ++ ) { 3200float32x4_t a_d = vcvt_f32_f16 (vld1_f16 ((const float16_t * )a_ptr [l ].d )); 3201float32x4_t b_d = vcvt_f32_f16 (vld1_f16 ((const float16_t * )b_ptr [l ].d )); 3202 3203int32x4_t sumi_0 = vdupq_n_s32 (0 ); 3204int32x4_t sumi_1 = vdupq_n_s32 (0 ); 3205int32x4_t sumi_2 = vdupq_n_s32 (0 ); 3206int32x4_t sumi_3 = vdupq_n_s32 (0 ); 3207 3208for (int k = 0 ;k < 4 ;k ++ ) { 3209int8x16_t a_0 = vld1q_s8 (a_ptr [l ].qs + 16 * k + 0 ); 3210int8x16_t a_1 = vld1q_s8 (a_ptr [l ].qs + 16 * k + 64 ); 3211 3212uint8x16_t b = vld1q_u8 (b_ptr [l ].qs + 16 * k ); 3213int8x16_t b_hi = vqtbl1q_s8 (kvalues ,b >>4 ); 3214int8x16_t b_lo = vqtbl1q_s8 (kvalues ,b & 0xF ); 3215 3216sumi_0 = vdotq_laneq_s32 (sumi_0 ,b_lo ,a_0 ,0 ); 3217sumi_1 = vdotq_laneq_s32 (sumi_1 ,b_lo ,a_0 ,1 ); 3218sumi_2 = vdotq_laneq_s32 (sumi_2 ,b_lo ,a_0 ,2 ); 3219sumi_3 = vdotq_laneq_s32 (sumi_3 ,b_lo ,a_0 ,3 ); 3220sumi_0 = vdotq_laneq_s32 (sumi_0 ,b_hi ,a_1 ,0 ); 3221sumi_1 = vdotq_laneq_s32 (sumi_1 ,b_hi ,a_1 ,1 ); 3222sumi_2 = vdotq_laneq_s32 (sumi_2 ,b_hi ,a_1 ,2 ); 3223sumi_3 = vdotq_laneq_s32 (sumi_3 ,b_hi ,a_1 ,3 ); 3224 } 3225 3226sumf [0 ]= vmlaq_f32 (sumf [0 ],vmulq_laneq_f32 (b_d ,a_d ,0 ),vcvtq_f32_s32 (sumi_0 )); 3227sumf [1 ]= vmlaq_f32 (sumf [1 ],vmulq_laneq_f32 (b_d ,a_d ,1 ),vcvtq_f32_s32 (sumi_1 )); 3228sumf [2 ]= vmlaq_f32 (sumf [2 ],vmulq_laneq_f32 (b_d ,a_d ,2 ),vcvtq_f32_s32 (sumi_2 )); 3229sumf [3 ]= vmlaq_f32 (sumf [3 ],vmulq_laneq_f32 (b_d ,a_d ,3 ),vcvtq_f32_s32 (sumi_3 )); 3230 } 3231 3232for (int m = 0 ;m < 4 ;m ++ ) { 3233vst1q_f32 (s + (y * 4 + m )* bs + x * 4 ,sumf [m ]); 3234 } 3235 } 3236 } 3237return ; 3238#endif // #if ! ((defined(_MSC_VER)) && ! defined(__clang__)) && defined(__aarch64__) && defined(__ARM_NEON) 3239ggml_gemm_iq4_nl_4x4_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 3240} 3241 3242void ggml_gemm_mxfp4_4x4_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 3243const int qk = QK8_0 ; 3244const int nb = n /qk ; 3245const int ncols_interleaved = 4 ; 3246const int blocklen = 4 ; 3247 3248assert (n %qk == 0 ); 3249assert (nr %4 == 0 ); 3250assert (nc %ncols_interleaved == 0 ); 3251 3252UNUSED (s ); 3253UNUSED (bs ); 3254UNUSED (vx ); 3255UNUSED (vy ); 3256UNUSED (nr ); 3257UNUSED (nc ); 3258UNUSED (nb ); 3259UNUSED (ncols_interleaved ); 3260UNUSED (blocklen ); 3261 3262#if ! ((defined(_MSC_VER ))&& ! defined(__clang__ ))&& defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 3263const int8x16_t kvalues = vld1q_s8 (kvalues_mxfp4 ); 3264 3265for (int y = 0 ;y < nr /4 ;y ++ ) { 3266const block_q8_0x4 * a_ptr = (const block_q8_0x4 * )vy + (y * nb ); 3267for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 3268const block_mxfp4x4 * b_ptr = (const block_mxfp4x4 * )vx + (x * nb ); 3269 3270float32x4_t sumf [4 ]; 3271for (int m = 0 ;m < 4 ;m ++ ) { 3272sumf [m ]= vdupq_n_f32 (0 ); 3273 } 3274 3275for (int l = 0 ;l < nb ;l ++ ) { 3276float32x4_t a_d = vcvt_f32_f16 (vld1_f16 ((const float16_t * )a_ptr [l ].d )); 3277float32x4_t b_d = { 3278GGML_CPU_E8M0_TO_FP32_HALF (b_ptr [l ].e [0 ]), 3279GGML_CPU_E8M0_TO_FP32_HALF (b_ptr [l ].e [1 ]), 3280GGML_CPU_E8M0_TO_FP32_HALF (b_ptr [l ].e [2 ]), 3281GGML_CPU_E8M0_TO_FP32_HALF (b_ptr [l ].e [3 ]), 3282 }; 3283 3284int32x4_t sumi_0 = vdupq_n_s32 (0 ); 3285int32x4_t sumi_1 = vdupq_n_s32 (0 ); 3286int32x4_t sumi_2 = vdupq_n_s32 (0 ); 3287int32x4_t sumi_3 = vdupq_n_s32 (0 ); 3288 3289for (int k = 0 ;k < 4 ;k ++ ) { 3290int8x16_t a_0 = vld1q_s8 (a_ptr [l ].qs + 16 * k + 0 ); 3291int8x16_t a_1 = vld1q_s8 (a_ptr [l ].qs + 16 * k + 64 ); 3292 3293uint8x16_t b = vld1q_u8 (b_ptr [l ].qs + 16 * k ); 3294int8x16_t b_hi = vqtbl1q_s8 (kvalues ,b >>4 ); 3295int8x16_t b_lo = vqtbl1q_s8 (kvalues ,b & 0xF ); 3296 3297sumi_0 = vdotq_laneq_s32 (sumi_0 ,b_lo ,a_0 ,0 ); 3298sumi_1 = vdotq_laneq_s32 (sumi_1 ,b_lo ,a_0 ,1 ); 3299sumi_2 = vdotq_laneq_s32 (sumi_2 ,b_lo ,a_0 ,2 ); 3300sumi_3 = vdotq_laneq_s32 (sumi_3 ,b_lo ,a_0 ,3 ); 3301sumi_0 = vdotq_laneq_s32 (sumi_0 ,b_hi ,a_1 ,0 ); 3302sumi_1 = vdotq_laneq_s32 (sumi_1 ,b_hi ,a_1 ,1 ); 3303sumi_2 = vdotq_laneq_s32 (sumi_2 ,b_hi ,a_1 ,2 ); 3304sumi_3 = vdotq_laneq_s32 (sumi_3 ,b_hi ,a_1 ,3 ); 3305 } 3306 3307sumf [0 ]= vmlaq_f32 (sumf [0 ],vmulq_laneq_f32 (b_d ,a_d ,0 ),vcvtq_f32_s32 (sumi_0 )); 3308sumf [1 ]= vmlaq_f32 (sumf [1 ],vmulq_laneq_f32 (b_d ,a_d ,1 ),vcvtq_f32_s32 (sumi_1 )); 3309sumf [2 ]= vmlaq_f32 (sumf [2 ],vmulq_laneq_f32 (b_d ,a_d ,2 ),vcvtq_f32_s32 (sumi_2 )); 3310sumf [3 ]= vmlaq_f32 (sumf [3 ],vmulq_laneq_f32 (b_d ,a_d ,3 ),vcvtq_f32_s32 (sumi_3 )); 3311 } 3312 3313for (int m = 0 ;m < 4 ;m ++ ) { 3314vst1q_f32 (s + (y * 4 + m )* bs + x * 4 ,sumf [m ]); 3315 } 3316 } 3317 } 3318return ; 3319#endif // #if ! ((defined(_MSC_VER)) && ! defined(__clang__)) && defined(__aarch64__) && defined(__ARM_NEON) 3320ggml_gemm_mxfp4_4x4_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 3321} 3322 3323void ggml_gemm_q4_K_8x4_q8_K (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,const void * GGML_RESTRICT vy ,int nr ,int nc ) { 3324constexpr int qk = QK_K ; 3325const int nb = n /qk ; 3326 3327constexpr int ncols_interleaved = 8 ; 3328constexpr int blocklen = 4 ; 3329 3330assert (n %qk == 0 ); 3331assert (nr %4 == 0 ); 3332assert (nc %ncols_interleaved == 0 ); 3333 3334UNUSED (nb ); 3335UNUSED (ncols_interleaved ); 3336UNUSED (blocklen ); 3337 3338#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 3339constexpr int q8_k_blocklen = 4 ; 3340constexpr int acc_size = 2 * 4 ;// 2 row pairs × 4 col pairs 3341const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 3342 3343// 8 accumulators: 2 row pairs × 4 col pairs 3344float32x4_t acc_f32 [acc_size ]; 3345 3346for (int y = 0 ;y < nr /q8_k_blocklen ;y ++ ) { 3347const block_q8_Kx4 * GGML_RESTRICT q8_ptr = (const block_q8_Kx4 * )vy + (y * nb ); 3348 3349for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 3350const block_q4_Kx8 * GGML_RESTRICT q4_ptr = (const block_q4_Kx8 * )vx + (x * nb ); 3351 3352for (int i = 0 ;i < acc_size ;i ++ ) { 3353acc_f32 [i ]= vdupq_n_f32 (0 ); 3354 } 3355 3356for (int b = 0 ;b < nb ;b ++ ) { 3357// d4 0 1 2 3, 4 5 6 7 3358float32x4_t q4_d_0123 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].d )); 3359float32x4_t q4_d_4567 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].d + 4 )); 3360// d8 0 1 2 3 3361float32x4_t q8_d_0123 = vld1q_f32 (q8_ptr [b ].d ); 3362// mins 3363float32x4_t q4_dmin_0123 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].dmin )); 3364float32x4_t q4_dmin_4567 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q4_ptr [b ].dmin + 4 )); 3365 3366// Precomputation of scales and mins 3367float32x4_t sbd_scale_0123 [q8_k_blocklen ]; 3368float32x4_t sbd_scale_4567 [q8_k_blocklen ]; 3369float32x4_t sbd_min_0123 [q8_k_blocklen ]; 3370float32x4_t sbd_min_4567 [q8_k_blocklen ]; 3371 3372sbd_scale_0123 [0 ]= vmulq_laneq_f32 (q4_d_0123 ,q8_d_0123 ,0 ); 3373sbd_scale_4567 [0 ]= vmulq_laneq_f32 (q4_d_4567 ,q8_d_0123 ,0 ); 3374sbd_min_0123 [0 ]= vmulq_laneq_f32 (q4_dmin_0123 ,q8_d_0123 ,0 ); 3375sbd_min_4567 [0 ]= vmulq_laneq_f32 (q4_dmin_4567 ,q8_d_0123 ,0 ); 3376 3377sbd_scale_0123 [1 ]= vmulq_laneq_f32 (q4_d_0123 ,q8_d_0123 ,1 ); 3378sbd_scale_4567 [1 ]= vmulq_laneq_f32 (q4_d_4567 ,q8_d_0123 ,1 ); 3379sbd_min_0123 [1 ]= vmulq_laneq_f32 (q4_dmin_0123 ,q8_d_0123 ,1 ); 3380sbd_min_4567 [1 ]= vmulq_laneq_f32 (q4_dmin_4567 ,q8_d_0123 ,1 ); 3381 3382sbd_scale_0123 [2 ]= vmulq_laneq_f32 (q4_d_0123 ,q8_d_0123 ,2 ); 3383sbd_scale_4567 [2 ]= vmulq_laneq_f32 (q4_d_4567 ,q8_d_0123 ,2 ); 3384sbd_min_0123 [2 ]= vmulq_laneq_f32 (q4_dmin_0123 ,q8_d_0123 ,2 ); 3385sbd_min_4567 [2 ]= vmulq_laneq_f32 (q4_dmin_4567 ,q8_d_0123 ,2 ); 3386 3387sbd_scale_0123 [3 ]= vmulq_laneq_f32 (q4_d_0123 ,q8_d_0123 ,3 ); 3388sbd_scale_4567 [3 ]= vmulq_laneq_f32 (q4_d_4567 ,q8_d_0123 ,3 ); 3389sbd_min_0123 [3 ]= vmulq_laneq_f32 (q4_dmin_0123 ,q8_d_0123 ,3 ); 3390sbd_min_4567 [3 ]= vmulq_laneq_f32 (q4_dmin_4567 ,q8_d_0123 ,3 ); 3391 3392// Precomputation of bsums, each vpaddq calcs all the bsums for each row 3393const int16x8_t bsums [q8_k_blocklen ]= { 3394vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 0 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 0 + 8 )), 3395vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 1 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 1 + 8 )), 3396vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 2 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 2 + 8 )), 3397vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 3 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 3 + 8 )), 3398 }; 3399int16_t bsums_arr [QK_K /64 ][8 ]; 3400for (int q8_row = 0 ;q8_row < 4 ;q8_row ++ ) { 3401vst1q_s16 (bsums_arr [q8_row ],bsums [q8_row ]); 3402 } 3403 3404// interleaved bias_acc: [0]->r0 0123, [1]->r1 0123, .., [4]->r0 4567, [5]->r1 4567 .. 3405int32x4_t bias_acc [acc_size ]; 3406for (int i = 0 ;i < acc_size ;i ++ ) { 3407bias_acc [i ]= vdupq_n_s32 (0 ); 3408 } 3409 3410for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 3411// Int accumulators for qs vecdot (4 row x 2 col quartets) 3412int32x4_t acc_lo [acc_size ]; 3413int32x4_t acc_hi [acc_size ]; 3414for (int i = 0 ;i < acc_size ;i ++ ) { 3415acc_lo [i ]= vdupq_n_s32 (0 ); 3416acc_hi [i ]= vdupq_n_s32 (0 ); 3417 } 3418// Need scales for the low and high nibbles 3419// 2 * 12 = 24 bytes per subblock, 4 sbs -> 4 * 24 = 96 bytes total 3420int16x8_t q4sb_scales [2 ]; 3421int16x8_t q4sb_mins [2 ]; 3422for (int i = 0 ;i < 2 ;i ++ ) { 3423int8_t aux_q4sb [8 ]; 3424const int offset = sb * 24 + i * 12 ; 3425decode_q_Kx8_6bit_scales (& q4_ptr [b ].scales [offset ],& q4sb_mins [i ],aux_q4sb ); 3426q4sb_scales [i ]= vmovl_s8 (vld1_s8 (aux_q4sb )); 3427 } 3428 3429constexpr int reads_per_sb = 8 ;// 8 * 16 bytes each => 32 qs * 4 rows 3430for (int k = 0 ;k < reads_per_sb ;k ++ ) { 3431const int8x16_t q8_blk0 = vld1q_s8 (q8_ptr [b ].qs + sb * 256 + 16 * k ); 3432const int8x16_t q8_blk1 = vld1q_s8 (q8_ptr [b ].qs + sb * 256 + 16 * k + 128 ); 3433 3434// 0..3 & 32..35 3435const uint8x16_t q4_0123 = vld1q_u8 (q4_ptr [b ].qs + sb * QK_K + 32 * k ); 3436const uint8x16_t q4_4567 = vld1q_u8 (q4_ptr [b ].qs + sb * QK_K + 32 * k + 16 ); 3437 3438const int8x16_t q4_0123_lo = vreinterpretq_s8_u8 (vandq_u8 (q4_0123 ,m4b )); 3439const int8x16_t q4_0123_hi = vreinterpretq_s8_u8 (vshrq_n_u8 (q4_0123 ,4 )); 3440 3441acc_lo [0 ]= vdotq_laneq_s32 (acc_lo [0 ],q4_0123_lo ,q8_blk0 ,0 );// 0..3 r0 c0123 3442acc_lo [1 ]= vdotq_laneq_s32 (acc_lo [1 ],q4_0123_lo ,q8_blk0 ,1 );// 0..3 r1 c0123 3443acc_lo [2 ]= vdotq_laneq_s32 (acc_lo [2 ],q4_0123_lo ,q8_blk0 ,2 );// 0..3 r2 c0123 3444acc_lo [3 ]= vdotq_laneq_s32 (acc_lo [3 ],q4_0123_lo ,q8_blk0 ,3 );// 0..3 r3 c0123 3445 3446acc_hi [0 ]= vdotq_laneq_s32 (acc_hi [0 ],q4_0123_hi ,q8_blk1 ,0 );// 32..35 r0 c0123 3447acc_hi [1 ]= vdotq_laneq_s32 (acc_hi [1 ],q4_0123_hi ,q8_blk1 ,1 );// 32..35 r1 c0123 3448acc_hi [2 ]= vdotq_laneq_s32 (acc_hi [2 ],q4_0123_hi ,q8_blk1 ,2 );// 32..35 r2 c0123 3449acc_hi [3 ]= vdotq_laneq_s32 (acc_hi [3 ],q4_0123_hi ,q8_blk1 ,3 );// 32..35 r3 c0123 3450 3451const int8x16_t q4_4567_lo = vreinterpretq_s8_u8 (vandq_u8 (q4_4567 ,m4b )); 3452const int8x16_t q4_4567_hi = vreinterpretq_s8_u8 (vshrq_n_u8 (q4_4567 ,4 )); 3453 3454acc_lo [4 ]= vdotq_laneq_s32 (acc_lo [4 ],q4_4567_lo ,q8_blk0 ,0 );// 0..3 r0 c4567 3455acc_lo [5 ]= vdotq_laneq_s32 (acc_lo [5 ],q4_4567_lo ,q8_blk0 ,1 );// 0..3 r1 c4567 3456acc_lo [6 ]= vdotq_laneq_s32 (acc_lo [6 ],q4_4567_lo ,q8_blk0 ,2 );// 0..3 r2 c4567 3457acc_lo [7 ]= vdotq_laneq_s32 (acc_lo [7 ],q4_4567_lo ,q8_blk0 ,3 );// 0..3 r3 c4567 3458 3459acc_hi [4 ]= vdotq_laneq_s32 (acc_hi [4 ],q4_4567_hi ,q8_blk1 ,0 );// 32..35 r0 c4567 3460acc_hi [5 ]= vdotq_laneq_s32 (acc_hi [5 ],q4_4567_hi ,q8_blk1 ,1 );// 32..35 r1 c4567 3461acc_hi [6 ]= vdotq_laneq_s32 (acc_hi [6 ],q4_4567_hi ,q8_blk1 ,2 );// 32..35 r2 c4567 3462acc_hi [7 ]= vdotq_laneq_s32 (acc_hi [7 ],q4_4567_hi ,q8_blk1 ,3 );// 32..35 r3 c4567 3463 } 3464 3465// Scale and bias application 3466// acc is stored interleaved to match output layout 3467const int16x4_t sc_0123_lo = vget_low_s16 (q4sb_scales [0 ]); 3468const int16x4_t sc_4567_lo = vget_high_s16 (q4sb_scales [0 ]); 3469const int16x4_t sc_0123_hi = vget_low_s16 (q4sb_scales [1 ]); 3470const int16x4_t sc_4567_hi = vget_high_s16 (q4sb_scales [1 ]); 3471for (int row = 0 ;row < q8_k_blocklen ;row ++ ) { 3472// Bias correction 3473// row c0123 blk0 and blk1 3474const float32x4_t sumf_0123 = 3475vcvtq_f32_s32 (vaddq_s32 (vmulq_s32 (vmovl_s16 (sc_0123_lo ),acc_lo [row ]), 3476vmulq_s32 (vmovl_s16 (sc_0123_hi ),acc_hi [row ]))); 3477acc_f32 [2 * row ]= vfmaq_f32 (acc_f32 [2 * row ],sbd_scale_0123 [row ],sumf_0123 ); 3478 3479// row c4567 blk0 and blk1 3480const float32x4_t sumf_4567 = 3481vcvtq_f32_s32 (vaddq_s32 (vmulq_s32 (vmovl_s16 (sc_4567_lo ),acc_lo [row + 4 ]), 3482vmulq_s32 (vmovl_s16 (sc_4567_hi ),acc_hi [row + 4 ]))); 3483acc_f32 [2 * row + 1 ]= vfmaq_f32 (acc_f32 [2 * row + 1 ],sbd_scale_4567 [row ],sumf_4567 ); 3484 3485// Bias 3486const int16x4_t bsums_vec_lo = vdup_n_s16 (bsums_arr [sb ][row * 2 ]); 3487const int16x4_t bsums_vec_hi = vdup_n_s16 (bsums_arr [sb ][row * 2 + 1 ]); 3488 3489// row c0123 blk0 and blk1 3490bias_acc [2 * row ]= vmlal_s16 (bias_acc [2 * row ],bsums_vec_lo ,vget_low_s16 (q4sb_mins [0 ])); 3491bias_acc [2 * row ]= vmlal_s16 (bias_acc [2 * row ],bsums_vec_hi ,vget_low_s16 (q4sb_mins [1 ])); 3492 3493// row c4567 blk0 and blk1 3494bias_acc [2 * row + 1 ]= 3495vmlal_s16 (bias_acc [2 * row + 1 ],bsums_vec_lo ,vget_high_s16 (q4sb_mins [0 ])); 3496bias_acc [2 * row + 1 ]= 3497vmlal_s16 (bias_acc [2 * row + 1 ],bsums_vec_hi ,vget_high_s16 (q4sb_mins [1 ])); 3498 } 3499 }// for sb 3500 3501for (int row = 0 ;row < q8_k_blocklen ;row ++ ) { 3502acc_f32 [2 * row ]= vmlsq_f32 (acc_f32 [2 * row ],vcvtq_f32_s32 (bias_acc [2 * row ]),sbd_min_0123 [row ]); 3503acc_f32 [2 * row + 1 ]= 3504vmlsq_f32 (acc_f32 [2 * row + 1 ],vcvtq_f32_s32 (bias_acc [2 * row + 1 ]),sbd_min_4567 [row ]); 3505 } 3506 }// for b 3507 3508for (int i = 0 ;i < q8_k_blocklen ;i ++ ) { 3509int row = y * q8_k_blocklen + i ; 3510for (int j = 0 ;j < 2 ;j ++ ) { 3511int col = x * ncols_interleaved + j * 4 ; 3512int offset = row * bs + col ; 3513vst1q_f32 (s + offset ,acc_f32 [2 * i + j ]); 3514 } 3515 } 3516 }// for x 3517 }// for y 3518return ; 3519#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 3520ggml_gemm_q4_K_8x4_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 3521} 3522 3523void ggml_gemm_q5_K_8x4_q8_K (int n , 3524float * GGML_RESTRICT s , 3525size_t bs , 3526const void * GGML_RESTRICT vx , 3527const void * GGML_RESTRICT vy , 3528int nr , 3529int nc ) { 3530constexpr int qk = QK_K ; 3531const int nb = n /qk ; 3532 3533constexpr int ncols_interleaved = 8 ; 3534constexpr int blocklen = 4 ; 3535 3536assert (n %qk == 0 ); 3537assert (nr %4 == 0 ); 3538assert (nc %ncols_interleaved == 0 ); 3539 3540UNUSED (nb ); 3541UNUSED (ncols_interleaved ); 3542UNUSED (blocklen ); 3543 3544#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 3545constexpr int q8_k_blocklen = 4 ; 3546constexpr int acc_size = 2 * 4 ;// 2 row pairs, 4 col pairs 3547constexpr int col_groups = ncols_interleaved /4 ; 3548const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 3549const uint8x16_t mone = vdupq_n_u8 (1 ); 3550const uint8x16_t mtwo = vdupq_n_u8 (2 ); 3551 3552// 8 accumulators: 2 row pairs, 4 col pairs 3553float32x4_t acc_f32 [acc_size ]; 3554 3555for (int y = 0 ;y < nr /q8_k_blocklen ;y ++ ) { 3556const block_q8_Kx4 * GGML_RESTRICT q8_ptr = (const block_q8_Kx4 * )vy + (y * nb ); 3557 3558for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 3559const block_q5_Kx8 * GGML_RESTRICT q5_ptr = (const block_q5_Kx8 * )vx + (x * nb ); 3560 3561for (int i = 0 ;i < acc_size ;i ++ ) { 3562acc_f32 [i ]= vdupq_n_f32 (0 ); 3563 } 3564 3565for (int b = 0 ;b < nb ;b ++ ) { 3566// d5 0 1 2 3, 4 5 6 7 3567float32x4_t q5_d_0123 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].d )); 3568float32x4_t q5_d_4567 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].d + 4 )); 3569// d8 0 1 2 3 3570float32x4_t q8_d_0123 = vld1q_f32 (q8_ptr [b ].d ); 3571// mins 3572float32x4_t q5_dmin_0123 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].dmin )); 3573float32x4_t q5_dmin_4567 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q5_ptr [b ].dmin + 4 )); 3574 3575// Precomputation of scales and mins 3576float32x4_t sbd_scale_0123 [q8_k_blocklen ]; 3577float32x4_t sbd_scale_4567 [q8_k_blocklen ]; 3578float32x4_t sbd_min_0123 [q8_k_blocklen ]; 3579float32x4_t sbd_min_4567 [q8_k_blocklen ]; 3580 3581sbd_scale_0123 [0 ]= vmulq_laneq_f32 (q5_d_0123 ,q8_d_0123 ,0 ); 3582sbd_scale_4567 [0 ]= vmulq_laneq_f32 (q5_d_4567 ,q8_d_0123 ,0 ); 3583sbd_min_0123 [0 ]= vmulq_laneq_f32 (q5_dmin_0123 ,q8_d_0123 ,0 ); 3584sbd_min_4567 [0 ]= vmulq_laneq_f32 (q5_dmin_4567 ,q8_d_0123 ,0 ); 3585 3586sbd_scale_0123 [1 ]= vmulq_laneq_f32 (q5_d_0123 ,q8_d_0123 ,1 ); 3587sbd_scale_4567 [1 ]= vmulq_laneq_f32 (q5_d_4567 ,q8_d_0123 ,1 ); 3588sbd_min_0123 [1 ]= vmulq_laneq_f32 (q5_dmin_0123 ,q8_d_0123 ,1 ); 3589sbd_min_4567 [1 ]= vmulq_laneq_f32 (q5_dmin_4567 ,q8_d_0123 ,1 ); 3590 3591sbd_scale_0123 [2 ]= vmulq_laneq_f32 (q5_d_0123 ,q8_d_0123 ,2 ); 3592sbd_scale_4567 [2 ]= vmulq_laneq_f32 (q5_d_4567 ,q8_d_0123 ,2 ); 3593sbd_min_0123 [2 ]= vmulq_laneq_f32 (q5_dmin_0123 ,q8_d_0123 ,2 ); 3594sbd_min_4567 [2 ]= vmulq_laneq_f32 (q5_dmin_4567 ,q8_d_0123 ,2 ); 3595 3596sbd_scale_0123 [3 ]= vmulq_laneq_f32 (q5_d_0123 ,q8_d_0123 ,3 ); 3597sbd_scale_4567 [3 ]= vmulq_laneq_f32 (q5_d_4567 ,q8_d_0123 ,3 ); 3598sbd_min_0123 [3 ]= vmulq_laneq_f32 (q5_dmin_0123 ,q8_d_0123 ,3 ); 3599sbd_min_4567 [3 ]= vmulq_laneq_f32 (q5_dmin_4567 ,q8_d_0123 ,3 ); 3600 3601// Precomputation of bsums, each vpaddq calcs all the bsums for each row 3602const int16x8_t bsums [q8_k_blocklen ]= { 3603vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 0 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 0 + 8 )), 3604vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 1 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 1 + 8 )), 3605vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 2 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 2 + 8 )), 3606vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 3 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 3 + 8 )), 3607 }; 3608int16_t bsums_arr [QK_K /64 ][8 ]; 3609for (int q8_row = 0 ;q8_row < 4 ;q8_row ++ ) { 3610vst1q_s16 (bsums_arr [q8_row ],bsums [q8_row ]); 3611 } 3612 3613// interleaved bias_acc: [0]->r0 0123, [1]->r1 0123, .., [4]->r0 4567, [5]->r1 4567 .. 3614int32x4_t bias_acc [acc_size ]; 3615for (int i = 0 ;i < acc_size ;i ++ ) { 3616bias_acc [i ]= vdupq_n_s32 (0 ); 3617 } 3618 3619uint8x16_t qh [col_groups ][8 ]; 3620for (int c = 0 ;c < col_groups ;c ++ ) { 3621for (int i = 0 ;i < 8 ;i ++ ) { 3622qh [c ][i ]= vld1q_u8 (q5_ptr [b ].qh + i * 32 + 16 * c ); 3623 } 3624 } 3625 3626for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 3627// Int accumulators for qs vecdot (4 row * 2 col quartets) 3628int32x4_t acc_lo [acc_size ]; 3629int32x4_t acc_hi [acc_size ]; 3630for (int i = 0 ;i < acc_size ;i ++ ) { 3631acc_lo [i ]= vdupq_n_s32 (0 ); 3632acc_hi [i ]= vdupq_n_s32 (0 ); 3633 } 3634// Need scales for the low and high nibbles 3635// 2 * 12 = 24 bytes per subblock, 4 sbs -> 4 * 24 = 96 bytes total 3636int16x8_t q5sb_scales [2 ]; 3637int16x8_t q5sb_mins [2 ]; 3638for (int i = 0 ;i < 2 ;i ++ ) { 3639int8_t aux_q5sb [8 ]; 3640const int offset = sb * 24 + i * 12 ; 3641decode_q_Kx8_6bit_scales (& q5_ptr [b ].scales [offset ],& q5sb_mins [i ],aux_q5sb ); 3642q5sb_scales [i ]= vmovl_s8 (vld1_s8 (aux_q5sb )); 3643 } 3644 3645constexpr int reads_per_sb = 8 ;// 8 * 16 bytes each => 32 qs * 4 rows 3646for (int k = 0 ;k < reads_per_sb ;k ++ ) { 3647const int8x16_t q8_blk0 = vld1q_s8 (q8_ptr [b ].qs + sb * 256 + 16 * k ); 3648const int8x16_t q8_blk1 = vld1q_s8 (q8_ptr [b ].qs + sb * 256 + 16 * k + 128 ); 3649 3650// 0..3 & 32..35 3651const uint8x16_t q5_0123 = vld1q_u8 (q5_ptr [b ].qs + sb * QK_K + 32 * k ); 3652const uint8x16_t q5_4567 = vld1q_u8 (q5_ptr [b ].qs + sb * QK_K + 32 * k + 16 ); 3653 3654// NOTE: This is the only difference with q4_K 3655const uint8x16_t hbit_lo_0123 = vandq_u8 (qh [0 ][k ],mone ); 3656const uint8x16_t hbit_hi_0123 = vshlq_n_u8 (vandq_u8 (qh [0 ][k ],mtwo ),3 ); 3657qh [0 ][k ]= vshrq_n_u8 (qh [0 ][k ],2 ); 3658const uint8x16_t hbit_lo_4567 = vandq_u8 (qh [1 ][k ],mone ); 3659const uint8x16_t hbit_hi_4567 = vshlq_n_u8 (vandq_u8 (qh [1 ][k ],mtwo ),3 ); 3660qh [1 ][k ]= vshrq_n_u8 (qh [1 ][k ],2 ); 3661// From here, same as q4_K 3662 3663const int8x16_t q5_0123_lo = 3664vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (q5_0123 ,m4b ),hbit_lo_0123 ,4 )); 3665const int8x16_t q5_0123_hi = 3666vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (q5_0123 ,4 ),hbit_hi_0123 )); 3667 3668acc_lo [0 ]= vdotq_laneq_s32 (acc_lo [0 ],q5_0123_lo ,q8_blk0 ,0 );// 0..3 r0 c0123 3669acc_lo [1 ]= vdotq_laneq_s32 (acc_lo [1 ],q5_0123_lo ,q8_blk0 ,1 );// 0..3 r1 c0123 3670acc_lo [2 ]= vdotq_laneq_s32 (acc_lo [2 ],q5_0123_lo ,q8_blk0 ,2 );// 0..3 r2 c0123 3671acc_lo [3 ]= vdotq_laneq_s32 (acc_lo [3 ],q5_0123_lo ,q8_blk0 ,3 );// 0..3 r3 c0123 3672 3673acc_hi [0 ]= vdotq_laneq_s32 (acc_hi [0 ],q5_0123_hi ,q8_blk1 ,0 );// 32..35 r0 c0123 3674acc_hi [1 ]= vdotq_laneq_s32 (acc_hi [1 ],q5_0123_hi ,q8_blk1 ,1 );// 32..35 r1 c0123 3675acc_hi [2 ]= vdotq_laneq_s32 (acc_hi [2 ],q5_0123_hi ,q8_blk1 ,2 );// 32..35 r2 c0123 3676acc_hi [3 ]= vdotq_laneq_s32 (acc_hi [3 ],q5_0123_hi ,q8_blk1 ,3 );// 32..35 r3 c0123 3677 3678const int8x16_t q5_4567_lo = 3679vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (q5_4567 ,m4b ),hbit_lo_4567 ,4 )); 3680const int8x16_t q5_4567_hi = 3681vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (q5_4567 ,4 ),hbit_hi_4567 )); 3682 3683acc_lo [4 ]= vdotq_laneq_s32 (acc_lo [4 ],q5_4567_lo ,q8_blk0 ,0 );// 0..3 r0 c4567 3684acc_lo [5 ]= vdotq_laneq_s32 (acc_lo [5 ],q5_4567_lo ,q8_blk0 ,1 );// 0..3 r1 c4567 3685acc_lo [6 ]= vdotq_laneq_s32 (acc_lo [6 ],q5_4567_lo ,q8_blk0 ,2 );// 0..3 r2 c4567 3686acc_lo [7 ]= vdotq_laneq_s32 (acc_lo [7 ],q5_4567_lo ,q8_blk0 ,3 );// 0..3 r3 c4567 3687 3688acc_hi [4 ]= vdotq_laneq_s32 (acc_hi [4 ],q5_4567_hi ,q8_blk1 ,0 );// 32..35 r0 c4567 3689acc_hi [5 ]= vdotq_laneq_s32 (acc_hi [5 ],q5_4567_hi ,q8_blk1 ,1 );// 32..35 r1 c4567 3690acc_hi [6 ]= vdotq_laneq_s32 (acc_hi [6 ],q5_4567_hi ,q8_blk1 ,2 );// 32..35 r2 c4567 3691acc_hi [7 ]= vdotq_laneq_s32 (acc_hi [7 ],q5_4567_hi ,q8_blk1 ,3 );// 32..35 r3 c4567 3692 } 3693 3694// Scale and bias application 3695// acc is stored interleaved to match output layout 3696const int16x4_t sc_0123_lo = vget_low_s16 (q5sb_scales [0 ]); 3697const int16x4_t sc_4567_lo = vget_high_s16 (q5sb_scales [0 ]); 3698const int16x4_t sc_0123_hi = vget_low_s16 (q5sb_scales [1 ]); 3699const int16x4_t sc_4567_hi = vget_high_s16 (q5sb_scales [1 ]); 3700for (int row = 0 ;row < q8_k_blocklen ;row ++ ) { 3701// Bias correction 3702// row c0123 blk0 and blk1 3703const float32x4_t sumf_0123 = 3704vcvtq_f32_s32 (vaddq_s32 (vmulq_s32 (vmovl_s16 (sc_0123_lo ),acc_lo [row ]), 3705vmulq_s32 (vmovl_s16 (sc_0123_hi ),acc_hi [row ]))); 3706acc_f32 [2 * row ]= vfmaq_f32 (acc_f32 [2 * row ],sbd_scale_0123 [row ],sumf_0123 ); 3707 3708// row c4567 blk0 and blk1 3709const float32x4_t sumf_4567 = 3710vcvtq_f32_s32 (vaddq_s32 (vmulq_s32 (vmovl_s16 (sc_4567_lo ),acc_lo [row + 4 ]), 3711vmulq_s32 (vmovl_s16 (sc_4567_hi ),acc_hi [row + 4 ]))); 3712acc_f32 [2 * row + 1 ]= vfmaq_f32 (acc_f32 [2 * row + 1 ],sbd_scale_4567 [row ],sumf_4567 ); 3713 3714// Bias 3715const int16x4_t bsums_vec_lo = vdup_n_s16 (bsums_arr [sb ][row * 2 ]); 3716const int16x4_t bsums_vec_hi = vdup_n_s16 (bsums_arr [sb ][row * 2 + 1 ]); 3717 3718// row c0123 blk0 and blk1 3719bias_acc [2 * row ]= vmlal_s16 (bias_acc [2 * row ],bsums_vec_lo ,vget_low_s16 (q5sb_mins [0 ])); 3720bias_acc [2 * row ]= vmlal_s16 (bias_acc [2 * row ],bsums_vec_hi ,vget_low_s16 (q5sb_mins [1 ])); 3721 3722// row c4567 blk0 and blk1 3723bias_acc [2 * row + 1 ]= 3724vmlal_s16 (bias_acc [2 * row + 1 ],bsums_vec_lo ,vget_high_s16 (q5sb_mins [0 ])); 3725bias_acc [2 * row + 1 ]= 3726vmlal_s16 (bias_acc [2 * row + 1 ],bsums_vec_hi ,vget_high_s16 (q5sb_mins [1 ])); 3727 } 3728 }// for sb 3729 3730for (int row = 0 ;row < q8_k_blocklen ;row ++ ) { 3731acc_f32 [2 * row ]= vmlsq_f32 (acc_f32 [2 * row ],vcvtq_f32_s32 (bias_acc [2 * row ]),sbd_min_0123 [row ]); 3732acc_f32 [2 * row + 1 ]= 3733vmlsq_f32 (acc_f32 [2 * row + 1 ],vcvtq_f32_s32 (bias_acc [2 * row + 1 ]),sbd_min_4567 [row ]); 3734 } 3735 }// for b 3736 3737for (int i = 0 ;i < q8_k_blocklen ;i ++ ) { 3738int row = y * q8_k_blocklen + i ; 3739for (int j = 0 ;j < 2 ;j ++ ) { 3740int col = x * ncols_interleaved + j * 4 ; 3741int offset = row * bs + col ; 3742vst1q_f32 (s + offset ,acc_f32 [2 * i + j ]); 3743 } 3744 } 3745 }// for x 3746 }// for y 3747return ; 3748#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 3749ggml_gemm_q5_K_8x4_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 3750} 3751 3752void ggml_gemm_q4_K_8x8_q8_K (int n , 3753float * GGML_RESTRICT s , 3754size_t bs , 3755const void * GGML_RESTRICT vx , 3756const void * GGML_RESTRICT vy , 3757int nr , 3758int nc ) { 3759constexpr int qk = QK_K ; 3760const int nb = n /qk ; 3761 3762constexpr int ncols_interleaved = 8 ; 3763constexpr int blocklen = 8 ; 3764 3765assert (n %qk == 0 ); 3766assert (nr %4 == 0 ); 3767assert (nc %ncols_interleaved == 0 ); 3768 3769UNUSED (nb ); 3770UNUSED (ncols_interleaved ); 3771UNUSED (blocklen ); 3772 3773#if defined(__aarch64__ )&& defined(__ARM_FEATURE_SVE )&& defined(__ARM_FEATURE_MATMUL_INT8 ) 3774if (svcntb ()* 8 == 256 ) { 3775constexpr int q8_k_blocklen = 4 ; 3776const svuint8_t m4b_1 = svdup_n_u8 (0x0f ); 3777// 8 accumulators: 2 row pairs × 4 col pairs 3778svfloat32_t acc_f32_01 ,acc_f32_23 ,acc_f32_45 ,acc_f32_67 ; 3779uint32_t idx_arr [8 ]= {0 ,2 ,4 ,6 ,1 ,3 ,5 ,7 }; 3780svbool_t pg = svptrue_pat_b32 (SV_VL8 ); 3781svuint32_t idx = svld1 (pg ,idx_arr ); 3782 3783static const uint32_t idx_data [8 ]= {0 ,4 ,2 ,6 ,1 ,5 ,3 ,7 }; 3784svuint32_t idx1 = svld1_u32 (svptrue_b32 (),idx_data ); 3785 3786for (int y = 0 ;y < nr /q8_k_blocklen ;y ++ ) { 3787const block_q8_Kx4 * GGML_RESTRICT q8_ptr = (const block_q8_Kx4 * )vy + (y * nb ); 3788 3789for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 3790const block_q4_Kx8 * GGML_RESTRICT q4_ptr = (const block_q4_Kx8 * )vx + (x * nb ); 3791 3792acc_f32_01 = svdup_n_f32 (0 ); 3793acc_f32_23 = svdup_n_f32 (0 ); 3794acc_f32_45 = svdup_n_f32 (0 ); 3795acc_f32_67 = svdup_n_f32 (0 ); 3796 3797for (int b = 0 ;b < nb ;b ++ ) { 3798// bsums pairs belongs to the same q8_k subblock 3799// 64 elements loaded and made sum of 0-7 and 8-15 sum || 16-23 and 24 - 31 sum 3800const int16x8_t bsums [4 ]{ 3801vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 0 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 0 + 8 )), 3802vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 1 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 1 + 8 )), 3803vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 2 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 2 + 8 )), 3804vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 3 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 3 + 8 )), 3805 }; 3806 3807int32_t bsums_arr32 [4 ][8 ]; 3808 3809for (int q8_row = 0 ;q8_row < 4 ;q8_row ++ ) { 3810int16x8_t v16 = bsums [q8_row ]; 3811 3812// low 4 3813int32x4_t v32_lo = vmovl_s16 (vget_low_s16 (v16 )); 3814vst1q_s32 (& bsums_arr32 [q8_row ][0 ],v32_lo ); 3815 3816// high 4 3817int32x4_t v32_hi = vmovl_s16 (vget_high_s16 (v16 )); 3818vst1q_s32 (& bsums_arr32 [q8_row ][4 ],v32_hi ); 3819 } 3820 3821svint32_t sb_acc_0 = svdup_n_s32 (0 ); 3822svint32_t sb_acc_2 = svdup_n_s32 (0 ); 3823 3824svint32_t acc_00 = svdup_n_s32 (0 ); 3825svint32_t acc_11 = svdup_n_s32 (0 ); 3826svint32_t acc_22 = svdup_n_s32 (0 ); 3827svint32_t acc_33 = svdup_n_s32 (0 ); 3828svint32_t acc_44 = svdup_n_s32 (0 ); 3829svint32_t acc_55 = svdup_n_s32 (0 ); 3830svint32_t acc_66 = svdup_n_s32 (0 ); 3831svint32_t acc_77 = svdup_n_s32 (0 ); 3832 3833svint32_t bias_acc_00 = svdup_n_s32 (0 ); 3834svint32_t bias_acc_22 = svdup_n_s32 (0 ); 3835svint32_t bias_acc_44 = svdup_n_s32 (0 ); 3836svint32_t bias_acc_66 = svdup_n_s32 (0 ); 3837 3838for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 3839// Need scales for the low and high nibbles 3840// 2 * 12 = 24 bytes per subblock, 4 sbs -> 4 * 24 = 96 bytes total 3841svint32_t block_scale_0 ,block_scale_1 ,block_scale_2 ,block_scale_3 ; 3842svint32_t q4sb_mins_0 ,q4sb_mins_1 ; 3843 { 3844// 2-superblock I am working on 3845const int offset = sb * 24 + 0 * 12 ; 3846const uint8_t * scales_in = & q4_ptr [b ].scales [offset ]; 3847 3848const int offset1 = sb * 24 + 12 ; 3849const uint8_t * scales_in1 = & q4_ptr [b ].scales [offset1 ]; 3850 3851constexpr uint32_t kmask1 = 0x3f3f3f3f ; 3852constexpr uint32_t kmask2 = 0x0f0f0f0f ; 3853constexpr uint32_t kmask3 = 0x03030303 ; 3854constexpr uint8_t scales_size = 12 ; 3855 3856uint32_t sm [3 ]; 3857memcpy (sm ,scales_in ,scales_size ); 3858 3859uint32_t sm1 [3 ]; 3860memcpy (sm1 ,scales_in1 ,scales_size ); 3861 3862const uint32_t mins_0_3 = sm [1 ]& kmask1 ; 3863const uint32_t mins_4_7 = ((sm [2 ] >>4 )& kmask2 ) | (((sm [1 ] >>6 )& kmask3 ) <<4 ); 3864 3865const uint32_t mins_0_3_1 = sm1 [1 ]& kmask1 ; 3866const uint32_t mins_4_7_1 = ((sm1 [2 ] >>4 )& kmask2 ) | (((sm1 [1 ] >>6 )& kmask3 ) <<4 ); 3867 3868svuint32_t mins_u32_temp = svzip1_u32 (svdup_n_u32 (mins_0_3 ),svdup_n_u32 (mins_4_7 )); 3869svuint32_t mins_u32_temp_1 = svzip1_u32 (svdup_n_u32 (mins_0_3_1 ),svdup_n_u32 (mins_4_7_1 )); 3870 3871/* reinterpret u32 → u8 */ 3872svuint8_t mins_u8 = svreinterpret_u8_u32 (mins_u32_temp ); 3873svuint8_t mins_u8_1 = svreinterpret_u8_u32 (mins_u32_temp_1 ); 3874 3875/* widen u8 → u16->u32 (lower half only) */ 3876svuint32_t mins_u16 = svunpklo_u32 (svunpklo_u16 (mins_u8 )); 3877svuint32_t mins_u16_1 = svunpklo_u32 (svunpklo_u16 (mins_u8_1 )); 3878 3879q4sb_mins_0 = svreinterpret_s32_u32 (mins_u16 ); 3880q4sb_mins_1 = svreinterpret_s32_u32 (mins_u16_1 ); 3881 3882uint32_t scales_u32_0 = sm [0 ]& kmask1 ; 3883uint32_t scales_u32_1 = (sm [2 ]& kmask2 ) | (((sm [0 ] >>6 )& kmask3 ) <<4 ); 3884uint32_t scales_u32_2 = sm1 [0 ]& kmask1 ; 3885uint32_t scales_u32_3 = (sm1 [2 ]& kmask2 ) | (((sm1 [0 ] >>6 )& kmask3 ) <<4 ); 3886 3887svuint32_t S01 = svdup_n_u32 (scales_u32_0 ); 3888svuint32_t S23 = svdup_n_u32 (scales_u32_1 ); 3889svuint32_t R01 = svdup_n_u32 (scales_u32_2 ); 3890svuint32_t R23 = svdup_n_u32 (scales_u32_3 ); 3891 3892svint8_t S01_b = svreinterpret_s8_u32 (S01 ); 3893svint8_t S23_b = svreinterpret_s8_u32 (S23 ); 3894svint8_t R01_b = svreinterpret_s8_u32 (R01 ); 3895svint8_t R23_b = svreinterpret_s8_u32 (R23 ); 3896 3897svint32_t S01_d = svunpklo_s32 (svunpklo_s16 (svzip1_s8 (S01_b ,S01_b ))); 3898svint32_t R01_d = svunpklo_s32 (svunpklo_s16 (svzip1_s8 (R01_b ,R01_b ))); 3899svint32_t S23_d = svunpklo_s32 (svunpklo_s16 (svzip1_s8 (S23_b ,S23_b ))); 3900svint32_t R23_d = svunpklo_s32 (svunpklo_s16 (svzip1_s8 (R23_b ,R23_b ))); 3901 3902block_scale_0 = svtbl_s32 (svzip1_s32 (S01_d ,R01_d ),idx ); 3903block_scale_1 = svtbl_s32 (svzip2_s32 (S01_d ,R01_d ),idx ); 3904block_scale_2 = svtbl_s32 (svzip1_s32 (S23_d ,R23_d ),idx ); 3905block_scale_3 = svtbl_s32 (svzip2_s32 (S23_d ,R23_d ),idx ); 3906 } 3907 3908const int8_t * q8_base_1 = q8_ptr [b ].qs + sb * 256 ; 3909 3910// Load 32-byte per row pair, 1 subblock each time 3911// predicate for activating higher lanes for 16 int8 elements 3912const svbool_t ph16 = svptrue_pat_b8 (SV_VL16 ); 3913// predicate for activating lower lanes for 16 int8 elements 3914const svbool_t pl16 = svnot_b_z (svptrue_b8 (),ph16 ); 3915 3916svint8_t q8_qs_0 = svadd_s8_x (svptrue_b8 (),svld1_s8 (ph16 ,q8_base_1 + 0 ),svld1_s8 (pl16 ,q8_base_1 + 112 )); 3917svint8_t q8_qs_2 = svadd_s8_x (svptrue_b8 (),svld1_s8 (ph16 ,q8_base_1 + 32 ),svld1_s8 (pl16 ,q8_base_1 + 144 )); 3918svint8_t q8_qs_4 = svadd_s8_x (svptrue_b8 (),svld1_s8 (ph16 ,q8_base_1 + 64 ),svld1_s8 (pl16 ,q8_base_1 + 176 )); 3919svint8_t q8_qs_6 = svadd_s8_x (svptrue_b8 (),svld1_s8 (ph16 ,q8_base_1 + 96 ),svld1_s8 (pl16 ,q8_base_1 + 208 )); 3920 3921svint8_t q8_qs_1 = svadd_s8_x (svptrue_b8 (),svld1_s8 (ph16 ,q8_base_1 + 16 ),svld1_s8 (pl16 ,q8_base_1 + 128 )); 3922svint8_t q8_qs_3 = svadd_s8_x (svptrue_b8 (),svld1_s8 (ph16 ,q8_base_1 + 48 ),svld1_s8 (pl16 ,q8_base_1 + 160 )); 3923svint8_t q8_qs_5 = svadd_s8_x (svptrue_b8 (),svld1_s8 (ph16 ,q8_base_1 + 80 ),svld1_s8 (pl16 ,q8_base_1 + 192 )); 3924svint8_t q8_qs_7 = svadd_s8_x (svptrue_b8 (),svld1_s8 (ph16 ,q8_base_1 + 112 ),svld1_s8 (pl16 ,q8_base_1 + 224 )); 3925 3926// Q4s columns iterated in pairs (01, 23, 45, 67) 3927for (int cp = 0 ;cp < ncols_interleaved /2 ;cp ++ ) { 3928 3929sb_acc_0 = svdup_n_s32 (0 ); 3930sb_acc_2 = svdup_n_s32 (0 ); 3931 3932svuint8_t q4_qs_cp_00 = svld1rq_u8 (svptrue_b8 (),q4_ptr [b ].qs + sb * QK_K + 16 * cp + 0 ); 3933svuint8_t q4_qs_cp_01 = svld1rq_u8 (svptrue_b8 (),q4_ptr [b ].qs + sb * QK_K + 16 * cp + 64 ); 3934svuint8_t q4_qs_cp_02 = svld1rq_u8 (svptrue_b8 (),q4_ptr [b ].qs + sb * QK_K + 16 * cp + 128 ); 3935svuint8_t q4_qs_cp_03 = svld1rq_u8 (svptrue_b8 (),q4_ptr [b ].qs + sb * QK_K + 16 * cp + 192 ); 3936 3937svint8_t q4_nibbles_00 = svreinterpret_s8_u8 (svlsr_n_u8_m (pl16 ,svand_u8_m (ph16 ,q4_qs_cp_00 ,m4b_1 ),4 )); 3938svint8_t q4_nibbles_01 = svreinterpret_s8_u8 (svlsr_n_u8_m (pl16 ,svand_u8_m (ph16 ,q4_qs_cp_01 ,m4b_1 ),4 )); 3939svint8_t q4_nibbles_02 = svreinterpret_s8_u8 (svlsr_n_u8_m (pl16 ,svand_u8_m (ph16 ,q4_qs_cp_02 ,m4b_1 ),4 )); 3940svint8_t q4_nibbles_03 = svreinterpret_s8_u8 (svlsr_n_u8_m (pl16 ,svand_u8_m (ph16 ,q4_qs_cp_03 ,m4b_1 ),4 )); 3941 3942sb_acc_0 = svmmla_s32 (sb_acc_0 ,q4_nibbles_00 ,q8_qs_0 ); 3943sb_acc_0 = svmmla_s32 (sb_acc_0 ,q4_nibbles_01 ,q8_qs_2 ); 3944 3945sb_acc_0 = svmmla_s32 (sb_acc_0 ,q4_nibbles_02 ,q8_qs_4 ); 3946sb_acc_0 = svmmla_s32 (sb_acc_0 ,q4_nibbles_03 ,q8_qs_6 ); 3947 3948sb_acc_2 = svmmla_s32 (sb_acc_2 ,q4_nibbles_00 ,q8_qs_1 ); 3949sb_acc_2 = svmmla_s32 (sb_acc_2 ,q4_nibbles_01 ,q8_qs_3 ); 3950 3951sb_acc_2 = svmmla_s32 (sb_acc_2 ,q4_nibbles_02 ,q8_qs_5 ); 3952sb_acc_2 = svmmla_s32 (sb_acc_2 ,q4_nibbles_03 ,q8_qs_7 ); 3953 3954if (cp == 0 ) { 3955acc_00 = svmla_s32_m (svptrue_b32 (),acc_00 ,sb_acc_0 ,block_scale_0 ); 3956acc_44 = svmla_s32_m (svptrue_b32 (),acc_44 ,sb_acc_2 ,block_scale_0 ); 3957 } 3958if (cp == 1 ) { 3959acc_11 = svmla_s32_m (svptrue_b32 (),acc_11 ,sb_acc_0 ,block_scale_1 ); 3960acc_55 = svmla_s32_m (svptrue_b32 (),acc_55 ,sb_acc_2 ,block_scale_1 ); 3961 } 3962if (cp == 2 ) { 3963acc_22 = svmla_s32_m (svptrue_b32 (),acc_22 ,sb_acc_0 ,block_scale_2 ); 3964acc_66 = svmla_s32_m (svptrue_b32 (),acc_66 ,sb_acc_2 ,block_scale_2 ); 3965 } 3966if (cp == 3 ) { 3967acc_33 = svmla_s32_m (svptrue_b32 (),acc_33 ,sb_acc_0 ,block_scale_3 ); 3968acc_77 = svmla_s32_m (svptrue_b32 (),acc_77 ,sb_acc_2 ,block_scale_3 ); 3969 } 3970 } 3971 3972bias_acc_00 = svmla_s32_m (svptrue_pat_b32 (SV_VL8 ),bias_acc_00 ,svdup_n_s32 (bsums_arr32 [sb ][0 ]),q4sb_mins_0 ); 3973bias_acc_00 = svmla_s32_m (svptrue_pat_b32 (SV_VL8 ),bias_acc_00 ,svdup_n_s32 (bsums_arr32 [sb ][1 ]),q4sb_mins_1 ); 3974 3975bias_acc_22 = svmla_s32_m (svptrue_pat_b32 (SV_VL8 ),bias_acc_22 ,svdup_n_s32 (bsums_arr32 [sb ][2 ]),q4sb_mins_0 ); 3976bias_acc_22 = svmla_s32_m (svptrue_pat_b32 (SV_VL8 ),bias_acc_22 ,svdup_n_s32 (bsums_arr32 [sb ][3 ]),q4sb_mins_1 ); 3977 3978bias_acc_44 = svmla_s32_m (svptrue_pat_b32 (SV_VL8 ),bias_acc_44 ,svdup_n_s32 (bsums_arr32 [sb ][4 ]),q4sb_mins_0 ); 3979bias_acc_44 = svmla_s32_m (svptrue_pat_b32 (SV_VL8 ),bias_acc_44 ,svdup_n_s32 (bsums_arr32 [sb ][5 ]),q4sb_mins_1 ); 3980 3981bias_acc_66 = svmla_s32_m (svptrue_pat_b32 (SV_VL8 ),bias_acc_66 ,svdup_n_s32 (bsums_arr32 [sb ][6 ]),q4sb_mins_0 ); 3982bias_acc_66 = svmla_s32_m (svptrue_pat_b32 (SV_VL8 ),bias_acc_66 ,svdup_n_s32 (bsums_arr32 [sb ][7 ]),q4sb_mins_1 ); 3983 }// for sb 3984 3985 3986acc_00 = svadd_s32_z (svptrue_pat_b32 (SV_VL4 ),acc_00 ,svext_s32 (acc_00 ,acc_00 ,4 )); 3987acc_11 = svadd_s32_z (svptrue_pat_b32 (SV_VL4 ),acc_11 ,svext_s32 (acc_11 ,acc_11 ,4 )); 3988acc_22 = svadd_s32_z (svptrue_pat_b32 (SV_VL4 ),acc_22 ,svext_s32 (acc_22 ,acc_22 ,4 )); 3989acc_33 = svadd_s32_z (svptrue_pat_b32 (SV_VL4 ),acc_33 ,svext_s32 (acc_33 ,acc_33 ,4 )); 3990acc_44 = svadd_s32_z (svptrue_pat_b32 (SV_VL4 ),acc_44 ,svext_s32 (acc_44 ,acc_44 ,4 )); 3991acc_55 = svadd_s32_z (svptrue_pat_b32 (SV_VL4 ),acc_55 ,svext_s32 (acc_55 ,acc_55 ,4 )); 3992acc_66 = svadd_s32_z (svptrue_pat_b32 (SV_VL4 ),acc_66 ,svext_s32 (acc_66 ,acc_66 ,4 )); 3993acc_77 = svadd_s32_z (svptrue_pat_b32 (SV_VL4 ),acc_77 ,svext_s32 (acc_77 ,acc_77 ,4 )); 3994 3995svint32_t reorder_acc_01 = svtbl_s32 (svzip1_s32 (svtrn1_s32 (acc_00 ,acc_11 ),svtrn1_s32 (acc_22 ,acc_33 )),idx1 ); 3996svint32_t reorder_acc_23 = svtbl_s32 (svzip1_s32 (svtrn2_s32 (acc_00 ,acc_11 ),svtrn2_s32 (acc_22 ,acc_33 )),idx1 ); 3997 3998svint32_t reorder_acc_45 = svtbl_s32 (svzip1_s32 (svtrn1_s32 (acc_44 ,acc_55 ),svtrn1_s32 (acc_66 ,acc_77 )),idx1 ); 3999svint32_t reorder_acc_67 = svtbl_s32 (svzip1_s32 (svtrn2_s32 (acc_44 ,acc_55 ),svtrn2_s32 (acc_66 ,acc_77 )),idx1 ); 4000 4001// Broadcast q8 scalar 4002svfloat32_t q8_d = svdup_f32 (q8_ptr [b ].d [0 ]); 4003 4004svfloat32_t q4_dmin_temp = svcvt_f32_f16_x (svptrue_b32 (),svzip1_f16 (svld1_f16 (svptrue_pat_b16 (SV_VL8 ), (const __fp16 * )q4_ptr [b ].dmin ),svdup_f16 (0 ))); 4005 4006svfloat32_t q4_d_temp = svcvt_f32_f16_x (svptrue_b32 (),svzip1_f16 (svld1_f16 (svptrue_pat_b16 (SV_VL8 ), (const __fp16 * )q4_ptr [b ].d ),svdup_f16 (0 ))); 4007 4008svfloat32_t scale1 = svmul_f32_x (svptrue_b32 (),q4_d_temp ,q8_d ); 4009svfloat32_t dmins1 = svmul_f32_x (svptrue_b32 (),q4_dmin_temp ,q8_d ); 4010 4011acc_f32_01 = svmls_f32_m (svptrue_b32 (),acc_f32_01 ,svcvt_f32_s32_m (svdup_n_f32 (0 ),svptrue_b32 (),bias_acc_00 ),dmins1 ); 4012acc_f32_01 = svmla_f32_m (svptrue_b32 (),acc_f32_01 ,svcvt_f32_s32_m (svdup_n_f32 (0 ),svptrue_b32 (),reorder_acc_01 ),scale1 ); 4013 4014q8_d = svdup_f32 (q8_ptr [b ].d [1 ]); 4015 4016scale1 = svmul_f32_x (svptrue_b32 (),q4_d_temp ,q8_d ); 4017dmins1 = svmul_f32_x (svptrue_b32 (),q4_dmin_temp ,q8_d ); 4018 4019acc_f32_23 = svmls_f32_m (svptrue_b32 (),acc_f32_23 ,svcvt_f32_s32_m (svdup_n_f32 (0 ),svptrue_b32 (),bias_acc_22 ),dmins1 ); 4020acc_f32_23 = svmla_f32_m (svptrue_b32 (),acc_f32_23 ,svcvt_f32_s32_m (svdup_n_f32 (0 ),svptrue_b32 (),reorder_acc_23 ),scale1 ); 4021 4022q8_d = svdup_f32 (q8_ptr [b ].d [2 ]); 4023 4024 4025scale1 = svmul_f32_x (svptrue_b32 (),q4_d_temp ,q8_d ); 4026dmins1 = svmul_f32_x (svptrue_b32 (),q4_dmin_temp ,q8_d ); 4027 4028acc_f32_45 = svmls_f32_m (svptrue_b32 (),acc_f32_45 ,svcvt_f32_s32_m (svdup_n_f32 (0 ),svptrue_b32 (),bias_acc_44 ),dmins1 ); 4029acc_f32_45 = svmla_f32_m (svptrue_b32 (),acc_f32_45 ,svcvt_f32_s32_m (svdup_n_f32 (0 ),svptrue_b32 (),reorder_acc_45 ),scale1 ); 4030 4031q8_d = svdup_f32 (q8_ptr [b ].d [3 ]); 4032 4033scale1 = svmul_f32_x (svptrue_b32 (),q4_d_temp ,q8_d ); 4034dmins1 = svmul_f32_x (svptrue_b32 (),q4_dmin_temp ,q8_d ); 4035 4036acc_f32_67 = svmls_f32_m (svptrue_b32 (),acc_f32_67 ,svcvt_f32_s32_m (svdup_n_f32 (0 ),svptrue_b32 (),bias_acc_66 ),dmins1 ); 4037acc_f32_67 = svmla_f32_m (svptrue_b32 (),acc_f32_67 ,svcvt_f32_s32_m (svdup_n_f32 (0 ),svptrue_b32 (),reorder_acc_67 ),scale1 ); 4038 4039 }// for b 4040 4041// With the previous reorder, the tile is already in the correct memory layout. 4042// Predicate for exactly 4 lanes 4043svbool_t pg4 = svptrue_pat_b32 (SV_VL4 ); 4044for (int i = 0 ;i < q8_k_blocklen ;i ++ ) { 4045int row = y * q8_k_blocklen + i ; 4046for (int j = 0 ;j < 2 ;j ++ ) { 4047int col = x * ncols_interleaved + j * 4 ; 4048int offset = row * bs + col ; 4049 4050if (i == 0 && j == 0 ) { 4051// acc_f32_0 → lower half of acc_f32_01 4052svst1_f32 (pg4 ,s + offset ,acc_f32_01 ); 4053 }else if (i == 0 && j == 1 ) { 4054// acc_f32_1 → upper half of acc_f32_01 4055svst1_f32 (pg4 ,s + offset ,svext_f32 (acc_f32_01 ,acc_f32_01 ,4 )); 4056 }else if (i == 1 && j == 0 ) { 4057// acc_f32_2 4058svst1_f32 (pg4 ,s + offset ,acc_f32_23 ); 4059 }else if (i == 1 && j == 1 ) { 4060// acc_f32_3 4061svst1_f32 (pg4 ,s + offset ,svext_f32 (acc_f32_23 ,acc_f32_23 ,4 )); 4062 }else if (i == 2 && j == 0 ) { 4063// acc_f32_4 4064svst1_f32 (pg4 ,s + offset ,acc_f32_45 ); 4065 }else if (i == 2 && j == 1 ) { 4066// acc_f32_5 4067svst1_f32 (pg4 ,s + offset ,svext_f32 (acc_f32_45 ,acc_f32_45 ,4 )); 4068 }else if (i == 3 && j == 0 ) { 4069// acc_f32_6 4070svst1_f32 (pg4 ,s + offset ,acc_f32_67 ); 4071 }else if (i == 3 && j == 1 ) { 4072// acc_f32_7 4073svst1_f32 (pg4 ,s + offset ,svext_f32 (acc_f32_67 ,acc_f32_67 ,4 )); 4074 } 4075 } 4076 } 4077 }// for x 4078 }// for y 4079return ; 4080 } 4081#endif // SVE compile-time end 4082 4083#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_MATMUL_INT8 ) 4084constexpr int q8_k_blocklen = 4 ; 4085const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 4086 4087// 8 accumulators: 2 row pairs × 4 col pairs 4088float32x4_t acc_f32 [blocklen ]; 4089 4090for (int y = 0 ;y < nr /q8_k_blocklen ;y ++ ) { 4091const block_q8_Kx4 * GGML_RESTRICT q8_ptr = (const block_q8_Kx4 * )vy + (y * nb ); 4092 4093for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 4094const block_q4_Kx8 * GGML_RESTRICT q4_ptr = (const block_q4_Kx8 * )vx + (x * nb ); 4095 4096for (int i = 0 ;i < blocklen ;i ++ ) { 4097acc_f32 [i ]= vdupq_n_f32 (0 ); 4098 } 4099 4100for (int b = 0 ;b < nb ;b ++ ) { 4101// bsums pairs belongs to the same q8_k subblock 4102const int16x8_t bsums [4 ]{ 4103vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 0 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 0 + 8 )), 4104vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 1 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 1 + 8 )), 4105vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 2 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 2 + 8 )), 4106vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 3 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 3 + 8 )), 4107 }; 4108int16_t bsums_arr [4 ][8 ]; 4109for (int q8_row = 0 ;q8_row < 4 ;q8_row ++ ) { 4110vst1q_s16 (bsums_arr [q8_row ],bsums [q8_row ]); 4111 } 4112 4113int32x4_t sb_acc [4 ];// Aux accumulators to store subblock (partial) results 4114int32x4_t acc [8 ];// rows 01 stored in [0][1][2][3] rows 23 stored in [4][5][6][7] 4115int32x4_t bias_acc [8 ];// interleaved bias_acc: [0]->r0 0123, [1]->r0 4567, [2]->r1 0123 ... 4116for (int i = 0 ;i < 8 ;i ++ ) { 4117acc [i ]= vdupq_n_s32 (0 ); 4118bias_acc [i ]= vdupq_n_s32 (0 ); 4119 } 4120 4121for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 4122// Need scales for the low and high nibbles 4123// 2 * 12 = 24 bytes per subblock, 4 sbs -> 4 * 24 = 96 bytes total 4124int8_t q4sb_scales [2 ][8 ]; 4125int16x8_t q4sb_mins [2 ];// int16 as its needed for bias_acc later 4126for (int i = 0 ;i < 2 ;i ++ ) { 4127const int offset = sb * 24 + i * 12 ; 4128decode_q_Kx8_6bit_scales (& q4_ptr [b ].scales [offset ],& q4sb_mins [i ],q4sb_scales [i ]); 4129 } 4130 4131// q8_ptr[b].qs has interleaved Q8 rows (01, 23) 4132const int8_t * q8_base = q8_ptr [b ].qs + sb * 256 ; 4133 4134int8x16_t q8_qs_01 [8 ]; 4135int8x16_t q8_qs_23 [8 ]; 4136 4137// Load 32-byte per row pair, 1 subblock each time 4138for (int i = 0 ;i < 8 ;i ++ ) { 4139const int offset = i * 32 ;// 16 for row 01, 16 for row 23 4140q8_qs_01 [i ]= vld1q_s8 (q8_base + offset ); 4141q8_qs_23 [i ]= vld1q_s8 (q8_base + offset + 16 ); 4142 } 4143 4144const int8x16_t q8s [2 ][8 ]= { 4145 {q8_qs_01 [0 ],q8_qs_01 [1 ],q8_qs_01 [2 ],q8_qs_01 [3 ], 4146q8_qs_01 [4 ],q8_qs_01 [5 ],q8_qs_01 [6 ],q8_qs_01 [7 ] }, 4147 {q8_qs_23 [0 ],q8_qs_23 [1 ],q8_qs_23 [2 ],q8_qs_23 [3 ], 4148q8_qs_23 [4 ],q8_qs_23 [5 ],q8_qs_23 [6 ],q8_qs_23 [7 ] }, 4149 }; 4150 4151// Q4s columns iterated in pairs (01, 23, 45, 67) 4152for (int cp = 0 ;cp < ncols_interleaved /2 ;cp ++ ) { 4153for (int i = 0 ;i < 4 ;i ++ ) { 4154sb_acc [i ]= vdupq_n_s32 (0 ); 4155 } 4156 4157uint8x16_t q4_qs_cp_0 = vld1q_u8 (q4_ptr [b ].qs + sb * QK_K + 16 * cp + 0 );// 0 .. 7 & 32..39 4158uint8x16_t q4_qs_cp_1 = vld1q_u8 (q4_ptr [b ].qs + sb * QK_K + 16 * cp + 64 );// 8 ..15 & 40..47 4159uint8x16_t q4_qs_cp_2 = vld1q_u8 (q4_ptr [b ].qs + sb * QK_K + 16 * cp + 128 );// 16..23 & 48..55 4160uint8x16_t q4_qs_cp_3 = vld1q_u8 (q4_ptr [b ].qs + sb * QK_K + 16 * cp + 192 );// 24..31 & 56..63 4161const int8x16_t q4_nibbles [2 ][4 ]= { 4162 { 4163vreinterpretq_s8_u8 (vandq_u8 (q4_qs_cp_0 ,m4b )), 4164vreinterpretq_s8_u8 (vandq_u8 (q4_qs_cp_1 ,m4b )), 4165vreinterpretq_s8_u8 (vandq_u8 (q4_qs_cp_2 ,m4b )), 4166vreinterpretq_s8_u8 (vandq_u8 (q4_qs_cp_3 ,m4b )), 4167 }, 4168 { 4169vreinterpretq_s8_u8 (vshrq_n_u8 (q4_qs_cp_0 ,4 )), 4170vreinterpretq_s8_u8 (vshrq_n_u8 (q4_qs_cp_1 ,4 )), 4171vreinterpretq_s8_u8 (vshrq_n_u8 (q4_qs_cp_2 ,4 )), 4172vreinterpretq_s8_u8 (vshrq_n_u8 (q4_qs_cp_3 ,4 )), 4173 } 4174 }; 4175 4176// Calculates the Qs muladd of every row pair (rp) rows 01 and 23 of q8 4177// for each of the internal 32 qs subblock (blk) 4178for (int rp = 0 ;rp < 2 ;rp ++ ) { 4179for (int blk = 0 ;blk < 2 ;blk ++ ) { 4180const int8x16_t * q8 = & q8s [rp ][4 * blk ]; 4181const int8x16_t * q4 = q4_nibbles [blk ]; 4182int32x4_t acc = sb_acc [2 * rp + blk ]; 4183// mul add for each qs in the same subblock 4184for (int qs_offset = 0 ;qs_offset < 4 ;qs_offset ++ ) { 4185acc = vmmlaq_s32 (acc ,q4 [qs_offset ],q8 [qs_offset ]); 4186 } 4187sb_acc [2 * rp + blk ]= acc ; 4188 } 4189 } 4190 4191// Scales[i] corresponds to column i 4192const int scale_offset = cp * 2 ; 4193const int32_t scale_00 = q4sb_scales [0 ][scale_offset ]; 4194const int32_t scale_01 = q4sb_scales [0 ][scale_offset + 1 ]; 4195const int32_t scale_10 = q4sb_scales [1 ][scale_offset ]; 4196const int32_t scale_11 = q4sb_scales [1 ][scale_offset + 1 ]; 4197const int32x4_t block_scale_0 = vcombine_s32 (vdup_n_s32 (scale_00 ),vdup_n_s32 (scale_01 )); 4198const int32x4_t block_scale_1 = vcombine_s32 (vdup_n_s32 (scale_10 ),vdup_n_s32 (scale_11 )); 4199 4200acc [cp ]= vmlaq_s32 (acc [cp ],sb_acc [0 ],block_scale_0 ); 4201acc [cp + 4 ]= vmlaq_s32 (acc [cp + 4 ],sb_acc [2 ],block_scale_0 ); 4202acc [cp ]= vmlaq_s32 (acc [cp ],sb_acc [1 ],block_scale_1 ); 4203acc [cp + 4 ]= vmlaq_s32 (acc [cp + 4 ],sb_acc [3 ],block_scale_1 ); 4204 } 4205 4206// Multiply Acc bsum + mins 4207for (int q8_row = 0 ;q8_row < 4 ;q8_row ++ ) { 4208// Each pair of subblocks share the same bsums 4209// Load scalar bsum → broadcast to a vector (vdupq_n_s16(s)). 4210int16x4_t bsums_vec_lo = vdup_n_s16 (bsums_arr [sb ][q8_row * 2 ]); 4211int16x4_t bsums_vec_hi = vdup_n_s16 (bsums_arr [sb ][q8_row * 2 + 1 ]); 4212 4213bias_acc [2 * q8_row ]= 4214vmlal_s16 (bias_acc [2 * q8_row ],bsums_vec_lo ,vget_low_s16 (q4sb_mins [0 ])); 4215bias_acc [2 * q8_row ]= 4216vmlal_s16 (bias_acc [2 * q8_row ],bsums_vec_hi ,vget_low_s16 (q4sb_mins [1 ])); 4217bias_acc [2 * q8_row + 1 ]= 4218vmlal_s16 (bias_acc [2 * q8_row + 1 ],bsums_vec_lo ,vget_high_s16 (q4sb_mins [0 ])); 4219bias_acc [2 * q8_row + 1 ]= 4220vmlal_s16 (bias_acc [2 * q8_row + 1 ],bsums_vec_hi ,vget_high_s16 (q4sb_mins [1 ])); 4221 } 4222 }// for sb 4223 4224// Reorder of i8mm output with bias and output layout 4225for (int i = 0 ;i < 8 ;i ++ ) { 4226int32x2x2_t aux = vzip_s32 (vget_low_s32 (acc [i ]),vget_high_s32 (acc [i ])); 4227acc [i ]= vcombine_s32 (aux .val [0 ],aux .val [1 ]); 4228 } 4229int32x4_t reorder_acc [8 ]= { 4230vcombine_s32 (vget_low_s32 (acc [0 ]),vget_low_s32 (acc [1 ])), 4231vcombine_s32 (vget_low_s32 (acc [2 ]),vget_low_s32 (acc [3 ])), 4232vcombine_s32 (vget_high_s32 (acc [0 ]),vget_high_s32 (acc [1 ])), 4233vcombine_s32 (vget_high_s32 (acc [2 ]),vget_high_s32 (acc [3 ])), 4234vcombine_s32 (vget_low_s32 (acc [4 ]),vget_low_s32 (acc [5 ])), 4235vcombine_s32 (vget_low_s32 (acc [6 ]),vget_low_s32 (acc [7 ])), 4236vcombine_s32 (vget_high_s32 (acc [4 ]),vget_high_s32 (acc [5 ])), 4237vcombine_s32 (vget_high_s32 (acc [6 ]),vget_high_s32 (acc [7 ])), 4238 }; 4239 4240for (int i = 0 ;i < q8_k_blocklen ;i ++ ) { 4241for (int j = 0 ;j < 2 ;j ++ ) { 4242float32x4_t q8_d = vdupq_n_f32 (q8_ptr [b ].d [i ]); 4243float32x4_t q4_dmin = vcvt_f32_f16 (vld1_f16 ((const __fp16 * ) (q4_ptr [b ].dmin + j * 4 ))); 4244const float32x4_t dmins = vmulq_f32 (q4_dmin ,q8_d ); 4245 4246float32x4_t q4_d = vcvt_f32_f16 (vld1_f16 ((const __fp16 * ) (q4_ptr [b ].d + j * 4 ))); 4247const float32x4_t scale = vmulq_f32 (q4_d ,q8_d ); 4248 4249acc_f32 [2 * i + j ]= vmlsq_f32 (acc_f32 [2 * i + j ],vcvtq_f32_s32 (bias_acc [2 * i + j ]),dmins ); 4250acc_f32 [2 * i + j ]= 4251vmlaq_f32 (acc_f32 [2 * i + j ],vcvtq_f32_s32 (reorder_acc [2 * i + j ]),scale ); 4252 } 4253 } 4254 }// for b 4255 4256// With the previous reorder, the tile is already in the correct memory layout. 4257for (int i = 0 ;i < q8_k_blocklen ;i ++ ) { 4258int row = y * q8_k_blocklen + i ; 4259for (int j = 0 ;j < 2 ;j ++ ) { 4260int col = x * ncols_interleaved + j * 4 ; 4261int offset = row * bs + col ; 4262vst1q_f32 (s + offset ,acc_f32 [2 * i + j ]); 4263 } 4264 } 4265 }// for x 4266 }// for y 4267return ; 4268#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_MATMUL_INT8) 4269ggml_gemm_q4_K_8x8_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 4270} 4271 4272void ggml_gemm_q5_K_8x8_q8_K (int n , 4273float * GGML_RESTRICT s , 4274size_t bs , 4275const void * GGML_RESTRICT vx , 4276const void * GGML_RESTRICT vy , 4277int nr , 4278int nc ) { 4279constexpr int qk = QK_K ; 4280const int nb = n /qk ; 4281 4282constexpr int ncols_interleaved = 8 ; 4283constexpr int blocklen = 8 ; 4284 4285assert (n %qk == 0 ); 4286assert (nr %4 == 0 ); 4287assert (nc %ncols_interleaved == 0 ); 4288 4289UNUSED (nb ); 4290UNUSED (ncols_interleaved ); 4291UNUSED (blocklen ); 4292 4293#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_MATMUL_INT8 ) 4294constexpr int q8_k_blocklen = 4 ; 4295constexpr int col_pairs = ncols_interleaved /2 ; 4296const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 4297const uint8x16_t mone = vdupq_n_u8 (1 ); 4298const uint8x16_t mtwo = vdupq_n_u8 (2 ); 4299 4300// 8 accumulators: 2 row pairs × 4 col pairs 4301float32x4_t acc_f32 [blocklen ]; 4302 4303for (int y = 0 ;y < nr /q8_k_blocklen ;y ++ ) { 4304const block_q8_Kx4 * GGML_RESTRICT q8_ptr = (const block_q8_Kx4 * )vy + (y * nb ); 4305 4306for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 4307const block_q5_Kx8 * GGML_RESTRICT q5_ptr = (const block_q5_Kx8 * )vx + (x * nb ); 4308 4309for (int i = 0 ;i < blocklen ;i ++ ) { 4310acc_f32 [i ]= vdupq_n_f32 (0 ); 4311 } 4312 4313for (int b = 0 ;b < nb ;b ++ ) { 4314// bsums pairs belongs to the same q8_k subblock 4315const int16x8_t bsums [4 ]{ 4316vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 0 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 0 + 8 )), 4317vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 1 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 1 + 8 )), 4318vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 2 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 2 + 8 )), 4319vpaddq_s16 (vld1q_s16 (q8_ptr [b ].bsums + 16 * 3 ),vld1q_s16 (q8_ptr [b ].bsums + 16 * 3 + 8 )), 4320 }; 4321int16_t bsums_arr [4 ][8 ]; 4322for (int q8_row = 0 ;q8_row < 4 ;q8_row ++ ) { 4323vst1q_s16 (bsums_arr [q8_row ],bsums [q8_row ]); 4324 } 4325 4326int32x4_t sb_acc [4 ];// Aux accumulators to store subblock (partial) results 4327int32x4_t acc [8 ];// rows 01 stored in [0][1][2][3] rows 23 stored in [4][5][6][7] 4328int32x4_t bias_acc [8 ];// interleaved bias_acc: [0]->r0 0123, [1]->r0 4567, [2]->r1 0123 ... 4329for (int i = 0 ;i < 8 ;i ++ ) { 4330acc [i ]= vdupq_n_s32 (0 ); 4331bias_acc [i ]= vdupq_n_s32 (0 ); 4332 } 4333 4334// Load qh once per block and shift after each subblock 4335const uint8_t * qh_base = q5_ptr [b ].qh ; 4336uint8x16_t qh [col_pairs ][4 ]; 4337for (int cp = 0 ;cp < col_pairs ;cp ++ ) { 4338qh [cp ][0 ]= vld1q_u8 (qh_base + 16 * cp ); 4339qh [cp ][1 ]= vld1q_u8 (qh_base + 16 * cp + 64 ); 4340qh [cp ][2 ]= vld1q_u8 (qh_base + 16 * cp + 128 ); 4341qh [cp ][3 ]= vld1q_u8 (qh_base + 16 * cp + 192 ); 4342 } 4343 4344for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 4345// Need scales for the low and high nibbles 4346// 2 * 12 = 24 bytes per subblock, 4 sbs -> 4 * 24 = 96 bytes total 4347int8_t q5sb_scales [2 ][8 ]; 4348int16x8_t q5sb_mins [2 ];// int16 as its needed for bias_acc later 4349for (int i = 0 ;i < 2 ;i ++ ) { 4350const int offset = sb * 24 + i * 12 ; 4351decode_q_Kx8_6bit_scales (& q5_ptr [b ].scales [offset ],& q5sb_mins [i ],q5sb_scales [i ]); 4352 } 4353 4354// q8_ptr[b].qs has interleaved Q8 rows (01, 23) 4355const int8_t * q8_base = q8_ptr [b ].qs + sb * 256 ; 4356 4357int8x16_t q8_qs_01 [8 ]; 4358int8x16_t q8_qs_23 [8 ]; 4359 4360// Load 32-byte per row pair, 1 subblock each time 4361for (int i = 0 ;i < 8 ;i ++ ) { 4362const int offset = i * 32 ;// 16 for row 01, 16 for row 23 4363q8_qs_01 [i ]= vld1q_s8 (q8_base + offset ); 4364q8_qs_23 [i ]= vld1q_s8 (q8_base + offset + 16 ); 4365 } 4366 4367const int8x16_t q8s [2 ][8 ]= { 4368 {q8_qs_01 [0 ],q8_qs_01 [1 ],q8_qs_01 [2 ],q8_qs_01 [3 ],q8_qs_01 [4 ],q8_qs_01 [5 ],q8_qs_01 [6 ], 4369q8_qs_01 [7 ] }, 4370 {q8_qs_23 [0 ],q8_qs_23 [1 ],q8_qs_23 [2 ],q8_qs_23 [3 ],q8_qs_23 [4 ],q8_qs_23 [5 ],q8_qs_23 [6 ], 4371q8_qs_23 [7 ] }, 4372 }; 4373 4374// Q5s columns iterated in pairs (01, 23, 45, 67) 4375for (int cp = 0 ;cp < col_pairs ;cp ++ ) { 4376for (int i = 0 ;i < 4 ;i ++ ) { 4377sb_acc [i ]= vdupq_n_s32 (0 ); 4378 } 4379 4380uint8x16_t qs_cp_0 = vld1q_u8 (q5_ptr [b ].qs + sb * QK_K + 16 * cp + 0 );// 0 .. 7 & 32..39 4381uint8x16_t qs_cp_1 = vld1q_u8 (q5_ptr [b ].qs + sb * QK_K + 16 * cp + 64 );// 8 ..15 & 40..47 4382uint8x16_t qs_cp_2 = vld1q_u8 (q5_ptr [b ].qs + sb * QK_K + 16 * cp + 128 );// 16..23 & 48..55 4383uint8x16_t qs_cp_3 = vld1q_u8 (q5_ptr [b ].qs + sb * QK_K + 16 * cp + 192 );// 24..31 & 56..63 4384 4385// This is the only part of the algorithm that differs with Q4_K 4386// Extract High bits and pack into 5 bit weights 4387uint8x16_t hbit_lo_0 = vandq_u8 (qh [cp ][0 ],mone ); 4388uint8x16_t hbit_hi_0 = vshlq_n_u8 (vandq_u8 (qh [cp ][0 ],mtwo ),3 ); 4389qh [cp ][0 ]= vshrq_n_u8 (qh [cp ][0 ],2 ); 4390// Same as Q4_K, i8mm to dequantize the weights. 4391const int8x16_t qs_lo_0 = vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_cp_0 ,m4b ),hbit_lo_0 ,4 )); 4392int32x4_t acc_0 = sb_acc [0 ]; 4393acc_0 = vmmlaq_s32 (acc_0 ,qs_lo_0 ,q8s [0 ][0 ]); 4394int32x4_t acc_2 = sb_acc [2 ]; 4395acc_2 = vmmlaq_s32 (acc_2 ,qs_lo_0 ,q8s [1 ][0 ]); 4396const int8x16_t qs_hi_0 = vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_cp_0 ,4 ),hbit_hi_0 )); 4397int32x4_t acc_1 = sb_acc [1 ]; 4398acc_1 = vmmlaq_s32 (acc_1 ,qs_hi_0 ,q8s [0 ][4 ]); 4399int32x4_t acc_3 = sb_acc [3 ]; 4400acc_3 = vmmlaq_s32 (acc_3 ,qs_hi_0 ,q8s [1 ][4 ]); 4401 4402// Repeat for the other 3 columns (8..15, 16..23, 24..31) 4403uint8x16_t hbit_hi_1 = vshlq_n_u8 (vandq_u8 (qh [cp ][1 ],mtwo ),3 ); 4404uint8x16_t hbit_lo_1 = vandq_u8 (qh [cp ][1 ],mone ); 4405qh [cp ][1 ]= vshrq_n_u8 (qh [cp ][1 ],2 ); 4406const int8x16_t qs_lo_1 = vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_cp_1 ,m4b ),hbit_lo_1 ,4 )); 4407acc_0 = vmmlaq_s32 (acc_0 ,qs_lo_1 ,q8s [0 ][1 ]); 4408acc_2 = vmmlaq_s32 (acc_2 ,qs_lo_1 ,q8s [1 ][1 ]); 4409const int8x16_t qs_hi_1 = vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_cp_1 ,4 ),hbit_hi_1 )); 4410acc_1 = vmmlaq_s32 (acc_1 ,qs_hi_1 ,q8s [0 ][5 ]); 4411acc_3 = vmmlaq_s32 (acc_3 ,qs_hi_1 ,q8s [1 ][5 ]); 4412 4413uint8x16_t hbit_hi_2 = vshlq_n_u8 (vandq_u8 (qh [cp ][2 ],mtwo ),3 ); 4414uint8x16_t hbit_lo_2 = vandq_u8 (qh [cp ][2 ],mone ); 4415qh [cp ][2 ]= vshrq_n_u8 (qh [cp ][2 ],2 ); 4416const int8x16_t qs_lo_2 = vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_cp_2 ,m4b ),hbit_lo_2 ,4 )); 4417acc_0 = vmmlaq_s32 (acc_0 ,qs_lo_2 ,q8s [0 ][2 ]); 4418acc_2 = vmmlaq_s32 (acc_2 ,qs_lo_2 ,q8s [1 ][2 ]); 4419const int8x16_t qs_hi_2 = vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_cp_2 ,4 ),hbit_hi_2 )); 4420acc_1 = vmmlaq_s32 (acc_1 ,qs_hi_2 ,q8s [0 ][6 ]); 4421acc_3 = vmmlaq_s32 (acc_3 ,qs_hi_2 ,q8s [1 ][6 ]); 4422 4423uint8x16_t hbit_lo_3 = vandq_u8 (qh [cp ][3 ],mone ); 4424uint8x16_t hbit_hi_3 = vshlq_n_u8 (vandq_u8 (qh [cp ][3 ],mtwo ),3 ); 4425qh [cp ][3 ]= vshrq_n_u8 (qh [cp ][3 ],2 ); 4426const int8x16_t qs_lo_3 = vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (qs_cp_3 ,m4b ),hbit_lo_3 ,4 )); 4427acc_0 = vmmlaq_s32 (acc_0 ,qs_lo_3 ,q8s [0 ][3 ]); 4428sb_acc [0 ]= acc_0 ; 4429acc_2 = vmmlaq_s32 (acc_2 ,qs_lo_3 ,q8s [1 ][3 ]); 4430sb_acc [2 ]= acc_2 ; 4431 4432// Scales[i] corresponds to column i 4433const int scale_offset = cp * 2 ; 4434const int32_t s0 = q5sb_scales [0 ][scale_offset ]; 4435const int32_t s1 = q5sb_scales [0 ][scale_offset + 1 ]; 4436const int32x4_t block_scale = vcombine_s32 (vdup_n_s32 (s0 ),vdup_n_s32 (s1 )); 4437acc [cp ]= vmlaq_s32 (acc [cp ],sb_acc [0 ],block_scale ); 4438acc [cp + 4 ]= vmlaq_s32 (acc [cp + 4 ],sb_acc [2 ],block_scale ); 4439 4440const int8x16_t qs_hi_3 = vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (qs_cp_3 ,4 ),hbit_hi_3 )); 4441acc_1 = vmmlaq_s32 (acc_1 ,qs_hi_3 ,q8s [0 ][7 ]); 4442sb_acc [1 ]= acc_1 ; 4443acc_3 = vmmlaq_s32 (acc_3 ,qs_hi_3 ,q8s [1 ][7 ]); 4444sb_acc [3 ]= acc_3 ; 4445 4446const int32_t s2 = q5sb_scales [1 ][scale_offset ]; 4447const int32_t s3 = q5sb_scales [1 ][scale_offset + 1 ]; 4448const int32x4_t block_scale2 = vcombine_s32 (vdup_n_s32 (s2 ),vdup_n_s32 (s3 )); 4449acc [cp ]= vmlaq_s32 (acc [cp ],sb_acc [1 ],block_scale2 ); 4450acc [cp + 4 ]= vmlaq_s32 (acc [cp + 4 ],sb_acc [3 ],block_scale2 ); 4451 } 4452 4453// Multiply Acc bsum + mins 4454for (int q8_row = 0 ;q8_row < 4 ;q8_row ++ ) { 4455// Each pair of subblocks share the same bsums 4456// Load scalar bsum → broadcast to a vector (vdupq_n_s16(s)). 4457int16x4_t bsums_vec_lo = vdup_n_s16 (bsums_arr [sb ][q8_row * 2 ]); 4458int16x4_t bsums_vec_hi = vdup_n_s16 (bsums_arr [sb ][q8_row * 2 + 1 ]); 4459 4460bias_acc [2 * q8_row ]= 4461vmlal_s16 (bias_acc [2 * q8_row ],bsums_vec_lo ,vget_low_s16 (q5sb_mins [0 ])); 4462bias_acc [2 * q8_row ]= 4463vmlal_s16 (bias_acc [2 * q8_row ],bsums_vec_hi ,vget_low_s16 (q5sb_mins [1 ])); 4464bias_acc [2 * q8_row + 1 ]= 4465vmlal_s16 (bias_acc [2 * q8_row + 1 ],bsums_vec_lo ,vget_high_s16 (q5sb_mins [0 ])); 4466bias_acc [2 * q8_row + 1 ]= 4467vmlal_s16 (bias_acc [2 * q8_row + 1 ],bsums_vec_hi ,vget_high_s16 (q5sb_mins [1 ])); 4468 } 4469 }// for sb 4470 4471// Reorder of i8mm output with bias and output layout 4472for (int i = 0 ;i < 8 ;i ++ ) { 4473int32x2x2_t aux = vzip_s32 (vget_low_s32 (acc [i ]),vget_high_s32 (acc [i ])); 4474acc [i ]= vcombine_s32 (aux .val [0 ],aux .val [1 ]); 4475 } 4476int32x4_t reorder_acc [8 ]= { 4477vcombine_s32 (vget_low_s32 (acc [0 ]),vget_low_s32 (acc [1 ])), 4478vcombine_s32 (vget_low_s32 (acc [2 ]),vget_low_s32 (acc [3 ])), 4479vcombine_s32 (vget_high_s32 (acc [0 ]),vget_high_s32 (acc [1 ])), 4480vcombine_s32 (vget_high_s32 (acc [2 ]),vget_high_s32 (acc [3 ])), 4481vcombine_s32 (vget_low_s32 (acc [4 ]),vget_low_s32 (acc [5 ])), 4482vcombine_s32 (vget_low_s32 (acc [6 ]),vget_low_s32 (acc [7 ])), 4483vcombine_s32 (vget_high_s32 (acc [4 ]),vget_high_s32 (acc [5 ])), 4484vcombine_s32 (vget_high_s32 (acc [6 ]),vget_high_s32 (acc [7 ])), 4485 }; 4486 4487for (int i = 0 ;i < q8_k_blocklen ;i ++ ) { 4488for (int j = 0 ;j < 2 ;j ++ ) { 4489float32x4_t q8_d = vdupq_n_f32 (q8_ptr [b ].d [i ]); 4490float32x4_t q5_dmin = vcvt_f32_f16 (vld1_f16 ((const __fp16 * ) (q5_ptr [b ].dmin + j * 4 ))); 4491const float32x4_t dmins = vmulq_f32 (q5_dmin ,q8_d ); 4492 4493float32x4_t q5_d = vcvt_f32_f16 (vld1_f16 ((const __fp16 * ) (q5_ptr [b ].d + j * 4 ))); 4494const float32x4_t scale = vmulq_f32 (q5_d ,q8_d ); 4495 4496acc_f32 [2 * i + j ]= vmlsq_f32 (acc_f32 [2 * i + j ],vcvtq_f32_s32 (bias_acc [2 * i + j ]),dmins ); 4497acc_f32 [2 * i + j ]= 4498vmlaq_f32 (acc_f32 [2 * i + j ],vcvtq_f32_s32 (reorder_acc [2 * i + j ]),scale ); 4499 } 4500 } 4501 }// for b 4502 4503// With the previous reorder, the tile is already in the correct memory layout. 4504for (int i = 0 ;i < q8_k_blocklen ;i ++ ) { 4505int row = y * q8_k_blocklen + i ; 4506for (int j = 0 ;j < 2 ;j ++ ) { 4507int col = x * ncols_interleaved + j * 4 ; 4508int offset = row * bs + col ; 4509vst1q_f32 (s + offset ,acc_f32 [2 * i + j ]); 4510 } 4511 } 4512 }// for x 4513 }// for y 4514return ; 4515#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_MATMUL_INT8) 4516ggml_gemm_q5_K_8x8_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 4517} 4518 4519void ggml_gemm_q6_K_8x4_q8_K (int n , 4520float * GGML_RESTRICT s , 4521size_t bs , 4522const void * GGML_RESTRICT vx , 4523const void * GGML_RESTRICT vy , 4524int nr , 4525int nc ) { 4526constexpr int qk = QK_K ; 4527const int nb = n /qk ; 4528 4529constexpr int ncols_interleaved = 8 ; 4530constexpr int blocklen = 4 ; 4531 4532assert (n %qk == 0 ); 4533assert (nr %4 == 0 ); 4534assert (nc %ncols_interleaved == 0 ); 4535 4536UNUSED (nb ); 4537UNUSED (ncols_interleaved ); 4538UNUSED (blocklen ); 4539 4540#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 4541constexpr int q8_k_blocklen = 4 ; 4542constexpr int col_groups = ncols_interleaved /4 ; 4543constexpr int acc_size = q8_k_blocklen * col_groups ;// 4 rows, 2 column groups 4544const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 4545const uint8x16_t mask_lo = vdupq_n_u8 (0x03 ); 4546const uint8x16_t mask_hi = vdupq_n_u8 (0x30 ); 4547const int8x16_t m32s = vdupq_n_s8 (32 ); 4548 4549float32x4_t acc_f32 [acc_size ]; 4550 4551for (int y = 0 ;y < nr /q8_k_blocklen ;y ++ ) { 4552const block_q8_Kx4 * GGML_RESTRICT q8_ptr = (const block_q8_Kx4 * )vy + (y * nb ); 4553 4554for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 4555const block_q6_Kx8 * GGML_RESTRICT q6_ptr = (const block_q6_Kx8 * )vx + (x * nb ); 4556 4557for (int i = 0 ;i < acc_size ;i ++ ) { 4558acc_f32 [i ]= vdupq_n_f32 (0 ); 4559 } 4560 4561for (int b = 0 ;b < nb ;b ++ ) { 4562float32x4_t q6_d_0123 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q6_ptr [b ].d )); 4563float32x4_t q6_d_4567 = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )q6_ptr [b ].d + 4 )); 4564float32x4_t q8_d_0123 = vld1q_f32 (q8_ptr [b ].d ); 4565 4566float32x4_t sbd_scale_0123 [q8_k_blocklen ]; 4567float32x4_t sbd_scale_4567 [q8_k_blocklen ]; 4568 4569sbd_scale_0123 [0 ]= vmulq_laneq_f32 (q6_d_0123 ,q8_d_0123 ,0 ); 4570sbd_scale_4567 [0 ]= vmulq_laneq_f32 (q6_d_4567 ,q8_d_0123 ,0 ); 4571sbd_scale_0123 [1 ]= vmulq_laneq_f32 (q6_d_0123 ,q8_d_0123 ,1 ); 4572sbd_scale_4567 [1 ]= vmulq_laneq_f32 (q6_d_4567 ,q8_d_0123 ,1 ); 4573sbd_scale_0123 [2 ]= vmulq_laneq_f32 (q6_d_0123 ,q8_d_0123 ,2 ); 4574sbd_scale_4567 [2 ]= vmulq_laneq_f32 (q6_d_4567 ,q8_d_0123 ,2 ); 4575sbd_scale_0123 [3 ]= vmulq_laneq_f32 (q6_d_0123 ,q8_d_0123 ,3 ); 4576sbd_scale_4567 [3 ]= vmulq_laneq_f32 (q6_d_4567 ,q8_d_0123 ,3 ); 4577 4578int32x4_t acc_s32 [acc_size ]; 4579for (int i = 0 ;i < acc_size ;i ++ ) { 4580acc_s32 [i ]= vdupq_n_s32 (0 ); 4581 } 4582 4583int16_t q6_scales [8 * 16 ]; 4584for (int i = 0 ;i < 16 ;i ++ ) { 4585int16x8_t scales = vmovl_s8 (vld1_s8 (q6_ptr [b ].scales + i * 8 )); 4586vst1q_s16 (q6_scales + i * 8 ,scales ); 4587 } 4588 4589for (int half = 0 ;half < 2 ;half ++ ) { 4590const uint8_t * ql_base = q6_ptr [b ].ql + half * 512 ; 4591const uint8_t * qh_base = q6_ptr [b ].qh + half * 256 ; 4592 4593for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 4594int32x4_t acc_lo [acc_size ]; 4595int32x4_t acc_hi [acc_size ]; 4596for (int i = 0 ;i < acc_size ;i ++ ) { 4597acc_lo [i ]= vdupq_n_s32 (0 ); 4598acc_hi [i ]= vdupq_n_s32 (0 ); 4599 } 4600 4601const int8_t * q8_base_l = q8_ptr [b ].qs + half * 512 + sb * 64 ; 4602const int8_t * q8_base_h = q8_ptr [b ].qs + half * 512 + 256 + sb * 64 ; 4603 4604// 4 rows * 16 elements per scale 4605// 4 reads of 16 bytes each 4606constexpr int reads_per_sb = 4 ; 4607int8x16_t q8_l [reads_per_sb ]; 4608int8x16_t q8_h [reads_per_sb ]; 4609for (int k = 0 ;k < reads_per_sb ;k ++ ) { 4610q8_l [k ]= vld1q_s8 (q8_base_l + 16 * k ); 4611q8_h [k ]= vld1q_s8 (q8_base_h + 16 * k ); 4612 } 4613 4614const int ql_off_base = sb * QK_K /2 ; 4615const int qh_off_base = ql_off_base & 255 ; 4616 4617uint8x16_t q6_ql_0123 [reads_per_sb ]; 4618uint8x16_t q6_ql_4567 [reads_per_sb ]; 4619uint8x16_t q6_qh_0123 [reads_per_sb ]; 4620uint8x16_t q6_qh_4567 [reads_per_sb ]; 4621 4622for (int k = 0 ;k < reads_per_sb ;k ++ ) { 4623q6_ql_0123 [k ]= vld1q_u8 (ql_base + ql_off_base + k * 32 ); 4624q6_ql_4567 [k ]= vld1q_u8 (ql_base + ql_off_base + k * 32 + 16 ); 4625q6_qh_0123 [k ]= vld1q_u8 (qh_base + qh_off_base + k * 32 ); 4626q6_qh_4567 [k ]= vld1q_u8 (qh_base + qh_off_base + k * 32 + 16 ); 4627 } 4628 4629if (sb > 1 ) { 4630for (int k = 0 ;k < reads_per_sb ;k ++ ) { 4631q6_qh_0123 [k ]= vshrq_n_u8 (q6_qh_0123 [k ],2 ); 4632q6_qh_4567 [k ]= vshrq_n_u8 (q6_qh_4567 [k ],2 ); 4633 } 4634 } 4635 4636for (int k = 0 ;k < reads_per_sb ;k ++ ) { 4637// q = (ql | qh) - 32 4638const uint8x16_t hbit_lo_0123 = vandq_u8 (q6_qh_0123 [k ],mask_lo ); 4639const uint8x16_t hbit_hi_0123 = vandq_u8 (q6_qh_0123 [k ],mask_hi ); 4640const uint8x16_t hbit_lo_4567 = vandq_u8 (q6_qh_4567 [k ],mask_lo ); 4641const uint8x16_t hbit_hi_4567 = vandq_u8 (q6_qh_4567 [k ],mask_hi ); 4642 4643const int8x16_t q6_0123_lo = vsubq_s8 ( 4644vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (q6_ql_0123 [k ],m4b ),hbit_lo_0123 ,4 )),m32s ); 4645const int8x16_t q6_0123_hi = vsubq_s8 ( 4646vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (q6_ql_0123 [k ],4 ),hbit_hi_0123 )),m32s ); 4647 4648acc_lo [0 ]= vdotq_laneq_s32 (acc_lo [0 ],q6_0123_lo ,q8_l [k ],0 );// 0..3 r0 c0123 4649acc_lo [1 ]= vdotq_laneq_s32 (acc_lo [1 ],q6_0123_lo ,q8_l [k ],1 );// 0..3 r1 c0123 4650acc_lo [2 ]= vdotq_laneq_s32 (acc_lo [2 ],q6_0123_lo ,q8_l [k ],2 );// 0..3 r2 c0123 4651acc_lo [3 ]= vdotq_laneq_s32 (acc_lo [3 ],q6_0123_lo ,q8_l [k ],3 );// 0..3 r3 c0123 4652 4653acc_hi [0 ]= vdotq_laneq_s32 (acc_hi [0 ],q6_0123_hi ,q8_h [k ],0 );// 64..67 r0 c0123 4654acc_hi [1 ]= vdotq_laneq_s32 (acc_hi [1 ],q6_0123_hi ,q8_h [k ],1 );// 64..67 r1 c0123 4655acc_hi [2 ]= vdotq_laneq_s32 (acc_hi [2 ],q6_0123_hi ,q8_h [k ],2 );// 64..67 r2 c0123 4656acc_hi [3 ]= vdotq_laneq_s32 (acc_hi [3 ],q6_0123_hi ,q8_h [k ],3 );// 64..67 r3 c0123 4657 4658const int8x16_t q6_4567_lo = vsubq_s8 ( 4659vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (q6_ql_4567 [k ],m4b ),hbit_lo_4567 ,4 )),m32s ); 4660const int8x16_t q6_4567_hi = vsubq_s8 ( 4661vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (q6_ql_4567 [k ],4 ),hbit_hi_4567 )),m32s ); 4662 4663acc_lo [4 ]= vdotq_laneq_s32 (acc_lo [4 ],q6_4567_lo ,q8_l [k ],0 );// 0..3 r0 c4567 4664acc_lo [5 ]= vdotq_laneq_s32 (acc_lo [5 ],q6_4567_lo ,q8_l [k ],1 );// 0..3 r1 c4567 4665acc_lo [6 ]= vdotq_laneq_s32 (acc_lo [6 ],q6_4567_lo ,q8_l [k ],2 );// 0..3 r2 c4567 4666acc_lo [7 ]= vdotq_laneq_s32 (acc_lo [7 ],q6_4567_lo ,q8_l [k ],3 );// 0..3 r3 c4567 4667 4668acc_hi [4 ]= vdotq_laneq_s32 (acc_hi [4 ],q6_4567_hi ,q8_h [k ],0 );// 64..67 r0 c4567 4669acc_hi [5 ]= vdotq_laneq_s32 (acc_hi [5 ],q6_4567_hi ,q8_h [k ],1 );// 64..67 r1 c4567 4670acc_hi [6 ]= vdotq_laneq_s32 (acc_hi [6 ],q6_4567_hi ,q8_h [k ],2 );// 64..67 r2 c4567 4671acc_hi [7 ]= vdotq_laneq_s32 (acc_hi [7 ],q6_4567_hi ,q8_h [k ],3 );// 64..67 r3 c4567 4672 } 4673 4674// Scale and bias 4675const int scale_idx_l = half * 8 + sb ; 4676const int scale_idx_h = half * 8 + sb + 4 ; 4677 4678for (int g = 0 ;g < col_groups ;g ++ ) { 4679const int16x4_t scales_l16 = vld1_s16 (q6_scales + scale_idx_l * 8 + g * 4 ); 4680const int16x4_t scales_h16 = vld1_s16 (q6_scales + scale_idx_h * 8 + g * 4 ); 4681const int32x4_t scale_vec_l = vmovl_s16 (scales_l16 ); 4682const int32x4_t scale_vec_h = vmovl_s16 (scales_h16 ); 4683const int acc_offset = g * q8_k_blocklen ; 4684 4685for (int row = 0 ;row < q8_k_blocklen ;row ++ ) { 4686const int idx = row * 2 + g ; 4687acc_s32 [idx ]= vmlaq_s32 (acc_s32 [idx ],acc_lo [acc_offset + row ],scale_vec_l ); 4688acc_s32 [idx ]= vmlaq_s32 (acc_s32 [idx ],acc_hi [acc_offset + row ],scale_vec_h ); 4689 } 4690 } 4691 } 4692 } 4693 4694// Finally we apply the superblock scales 4695for (int row = 0 ;row < q8_k_blocklen ;row ++ ) { 4696const int idx0 = 2 * row ; 4697const int idx1 = 2 * row + 1 ; 4698const int32x4_t acc_0123 = acc_s32 [idx0 ]; 4699const int32x4_t acc_4567 = acc_s32 [idx1 ]; 4700 4701acc_f32 [idx0 ]= vmlaq_f32 (acc_f32 [idx0 ],vcvtq_f32_s32 (acc_0123 ),sbd_scale_0123 [row ]); 4702acc_f32 [idx1 ]= vmlaq_f32 (acc_f32 [idx1 ],vcvtq_f32_s32 (acc_4567 ),sbd_scale_4567 [row ]); 4703 } 4704 }// for b 4705 4706for (int i = 0 ;i < q8_k_blocklen ;i ++ ) { 4707int row = y * q8_k_blocklen + i ; 4708for (int j = 0 ;j < 2 ;j ++ ) { 4709int col = x * ncols_interleaved + j * 4 ; 4710int offset = row * bs + col ; 4711vst1q_f32 (s + offset ,acc_f32 [2 * i + j ]); 4712 } 4713 } 4714 }// for x 4715 }// for y 4716return ; 4717#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 4718ggml_gemm_q6_K_8x4_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 4719} 4720 4721void ggml_gemm_q6_K_8x8_q8_K (int n , 4722float * GGML_RESTRICT s , 4723size_t bs , 4724const void * GGML_RESTRICT vx , 4725const void * GGML_RESTRICT vy , 4726int nr , 4727int nc ) { 4728constexpr int qk = QK_K ; 4729const int nb = n /qk ; 4730 4731constexpr int ncols_interleaved = 8 ; 4732constexpr int blocklen = 8 ; 4733 4734assert (n %qk == 0 ); 4735assert (nr %4 == 0 ); 4736assert (nc %ncols_interleaved == 0 ); 4737 4738UNUSED (nb ); 4739UNUSED (ncols_interleaved ); 4740UNUSED (blocklen ); 4741 4742#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_MATMUL_INT8 ) 4743constexpr int q8_k_blocklen = 4 ; 4744const uint8x16_t m4b = vdupq_n_u8 (0x0f ); 4745const uint8x16_t mask_lo = vdupq_n_u8 (0x03 ); 4746const uint8x16_t mask_hi = vdupq_n_u8 (0x30 ); 4747const int8x16_t m32s = vdupq_n_s8 (32 ); 4748 4749// 8 accumulators: 4 q8 rows × 2 col groups (0-3, 4-7) 4750float32x4_t acc_f32 [blocklen ]; 4751 4752for (int y = 0 ;y < nr /q8_k_blocklen ;y ++ ) { 4753const block_q8_Kx4 * GGML_RESTRICT q8_ptr = (const block_q8_Kx4 * )vy + (y * nb ); 4754 4755for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 4756const block_q6_Kx8 * GGML_RESTRICT q6_ptr = (const block_q6_Kx8 * )vx + (x * nb ); 4757 4758for (int i = 0 ;i < blocklen ;i ++ ) { 4759acc_f32 [i ]= vdupq_n_f32 (0 ); 4760 } 4761 4762for (int b = 0 ;b < nb ;b ++ ) { 4763int32x4_t acc [8 ];// rows 01 stored in [0][1][2][3], rows 23 stored in [4][5][6][7] 4764for (int i = 0 ;i < 8 ;i ++ ) { 4765acc [i ]= vdupq_n_s32 (0 ); 4766 } 4767 4768// Q6_K has simple 8-bit scales, 16 per block (one per 16 values) 4769// Reused for bias and dequantization later 4770int16_t q6_scales [16 * 8 ]; 4771for (int i = 0 ;i < 16 ;++ i ) { 4772int16x8_t s16 = vmovl_s8 (vld1_s8 (q6_ptr [b ].scales + i * 8 )); 4773vst1q_s16 (q6_scales + i * 8 ,s16 ); 4774 } 4775 4776// Process two 128-value halves per superblock 4777for (int half = 0 ;half < 2 ;half ++ ) { 4778 4779const uint8_t * ql_base = q6_ptr [b ].ql + half * 512 ; 4780const uint8_t * qh_base = q6_ptr [b ].qh + half * 256 ; 4781 4782// A subblock (sb) is a set of weights that share the scale 4783// Since q6_K scales are per 16 elements 4784// num sbs -> 256 elements / (16 elements/scale * 2 elements/byte * 2 halves) 4785for (int sb = 0 ;sb < QK_K /64 ;sb ++ ) { 4786// Q6_K weight index increasing by 64 instead of 32 requires 4787// loading various q8 memory regions 4788const int8_t * q8_base_l = q8_ptr [b ].qs + half * 512 + sb * 64 ; 4789const int8_t * q8_base_h = q8_ptr [b ].qs + half * 512 + 256 + sb * 64 ; 4790 4791int8x16_t q8_l_01 [2 ]; 4792int8x16_t q8_l_23 [2 ]; 4793for (int i = 0 ;i < 2 ;i ++ ) { 4794const int offset = i * 32 ; 4795q8_l_01 [i ]= vld1q_s8 (q8_base_l + offset );// 0..7 & 8..15 (r01) 4796q8_l_23 [i ]= vld1q_s8 (q8_base_l + offset + 16 );// 0..7 & 8..15 (r23) 4797 } 4798 4799int8x16_t q8_h_01 [2 ]; 4800int8x16_t q8_h_23 [2 ]; 4801for (int i = 0 ;i < 2 ;i ++ ) { 4802const int offset = i * 32 ; 4803q8_h_01 [i ]= vld1q_s8 (q8_base_h + offset ); 4804q8_h_23 [i ]= vld1q_s8 (q8_base_h + offset + 16 ); 4805 } 4806 4807const int ql_off_base = sb * QK_K /2 ; 4808 4809uint8x16_t q6_ql_0 [4 ]; 4810uint8x16_t q6_ql_1 [4 ]; 4811for (int k = 0 ;k < 4 ;k ++ ) { 4812q6_ql_0 [k ]= vld1q_u8 (ql_base + ql_off_base + 16 * k ); 4813q6_ql_1 [k ]= vld1q_u8 (ql_base + ql_off_base + 64 + 16 * k ); 4814 } 4815 4816const int qh_off_base = (sb * QK_K /2 )& 255 ;// wrap after 256 bytes 4817uint8x16_t q6_qh_0 [4 ]; 4818uint8x16_t q6_qh_1 [4 ]; 4819for (int k = 0 ;k < 4 ;k ++ ) { 4820q6_qh_0 [k ]= vld1q_u8 (qh_base + qh_off_base + 16 * k ); 4821q6_qh_1 [k ]= vld1q_u8 (qh_base + qh_off_base + 64 + 16 * k ); 4822 } 4823 4824// Adjust for the proper high bits (Sb 2 and 3) 4825if (sb > 1 ) { 4826for (int k = 0 ;k < 4 ;k ++ ) { 4827q6_qh_0 [k ]= vshrq_n_u8 (q6_qh_0 [k ],2 ); 4828q6_qh_1 [k ]= vshrq_n_u8 (q6_qh_1 [k ],2 ); 4829 } 4830 } 4831 4832// Process column pairs (0-1, 2-3, 4-5, 6-7) 4833for (int cp = 0 ;cp < ncols_interleaved /2 ;cp ++ ) { 4834const uint8x16_t q6_qs_cp_0_l = q6_ql_0 [cp ]; 4835const uint8x16_t q6_qs_cp_1_l = q6_ql_1 [cp ]; 4836const uint8x16_t q6_qs_cp_0_h = q6_qh_0 [cp ]; 4837const uint8x16_t q6_qs_cp_1_h = q6_qh_1 [cp ]; 4838 4839// Extract high 2 bits for upper nibble reconstruction 4840const uint8x16_t q6_qs_cp_0_hh = vandq_u8 (q6_qs_cp_0_h ,mask_hi ); 4841const uint8x16_t q6_qs_cp_1_hh = vandq_u8 (q6_qs_cp_1_h ,mask_hi ); 4842 4843// q6 = (low4 | high2<<4) - 32 4844// Use vsliq_n_u8 to combine shift-left-insert in one instruction (like Q5_K) 4845const int8x16_t q6_l0 = vsubq_s8 ( 4846vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (q6_qs_cp_0_l ,m4b ),vandq_u8 (q6_qs_cp_0_h ,mask_lo ),4 )), 4847m32s ); 4848const int8x16_t q6_l1 = vsubq_s8 ( 4849vreinterpretq_s8_u8 (vsliq_n_u8 (vandq_u8 (q6_qs_cp_1_l ,m4b ),vandq_u8 (q6_qs_cp_1_h ,mask_lo ),4 )), 4850m32s ); 4851const int8x16_t q6_h0 = vsubq_s8 ( 4852vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (q6_qs_cp_0_l ,4 ),q6_qs_cp_0_hh )),m32s ); 4853const int8x16_t q6_h1 = vsubq_s8 ( 4854vreinterpretq_s8_u8 (vorrq_u8 (vshrq_n_u8 (q6_qs_cp_1_l ,4 ),q6_qs_cp_1_hh )),m32s ); 4855 4856// row pair 0, base_l 4857int32x4_t sb_acc_0l = vmmlaq_s32 (vdupq_n_s32 (0 ),q6_l0 ,q8_l_01 [0 ]); 4858sb_acc_0l = vmmlaq_s32 (sb_acc_0l ,q6_l1 ,q8_l_01 [1 ]); 4859// row pair 0, base_h 4860int32x4_t sb_acc_0h = vmmlaq_s32 (vdupq_n_s32 (0 ),q6_h0 ,q8_h_01 [0 ]); 4861sb_acc_0h = vmmlaq_s32 (sb_acc_0h ,q6_h1 ,q8_h_01 [1 ]); 4862// row pair 1, base_l 4863int32x4_t sb_acc_1l = vmmlaq_s32 (vdupq_n_s32 (0 ),q6_l0 ,q8_l_23 [0 ]); 4864sb_acc_1l = vmmlaq_s32 (sb_acc_1l ,q6_l1 ,q8_l_23 [1 ]); 4865// row pair 1, base_h 4866int32x4_t sb_acc_1h = vmmlaq_s32 (vdupq_n_s32 (0 ),q6_h0 ,q8_h_23 [0 ]); 4867sb_acc_1h = vmmlaq_s32 (sb_acc_1h ,q6_h1 ,q8_h_23 [1 ]); 4868 4869const int scale_idx_l = half * 8 + sb ; 4870const int scale_idx_h = half * 8 + sb + 4 ; 4871 4872const int32x4_t scale_vec_l = { 4873q6_scales [scale_idx_l * 8 + cp * 2 + 0 ], 4874q6_scales [scale_idx_l * 8 + cp * 2 + 0 ], 4875q6_scales [scale_idx_l * 8 + cp * 2 + 1 ], 4876q6_scales [scale_idx_l * 8 + cp * 2 + 1 ], 4877 }; 4878const int32x4_t scale_vec_h = { 4879q6_scales [scale_idx_h * 8 + cp * 2 + 0 ], 4880q6_scales [scale_idx_h * 8 + cp * 2 + 0 ], 4881q6_scales [scale_idx_h * 8 + cp * 2 + 1 ], 4882q6_scales [scale_idx_h * 8 + cp * 2 + 1 ], 4883 }; 4884 4885acc [cp ]= vmlaq_s32 (acc [cp ],sb_acc_0l ,scale_vec_l ); 4886acc [cp ]= vmlaq_s32 (acc [cp ],sb_acc_0h ,scale_vec_h ); 4887acc [cp + 4 ]= vmlaq_s32 (acc [cp + 4 ],sb_acc_1l ,scale_vec_l ); 4888acc [cp + 4 ]= vmlaq_s32 (acc [cp + 4 ],sb_acc_1h ,scale_vec_h ); 4889 } 4890 } 4891 }// for half 4892 4893// Reorder i8mm output to match memory layout 4894for (int i = 0 ;i < 8 ;i ++ ) { 4895int32x2x2_t aux = vzip_s32 (vget_low_s32 (acc [i ]),vget_high_s32 (acc [i ])); 4896acc [i ]= vcombine_s32 (aux .val [0 ],aux .val [1 ]); 4897 } 4898int32x4_t reorder_acc [8 ]= { 4899vcombine_s32 (vget_low_s32 (acc [0 ]),vget_low_s32 (acc [1 ])), 4900vcombine_s32 (vget_low_s32 (acc [2 ]),vget_low_s32 (acc [3 ])), 4901vcombine_s32 (vget_high_s32 (acc [0 ]),vget_high_s32 (acc [1 ])), 4902vcombine_s32 (vget_high_s32 (acc [2 ]),vget_high_s32 (acc [3 ])), 4903vcombine_s32 (vget_low_s32 (acc [4 ]),vget_low_s32 (acc [5 ])), 4904vcombine_s32 (vget_low_s32 (acc [6 ]),vget_low_s32 (acc [7 ])), 4905vcombine_s32 (vget_high_s32 (acc [4 ]),vget_high_s32 (acc [5 ])), 4906vcombine_s32 (vget_high_s32 (acc [6 ]),vget_high_s32 (acc [7 ])), 4907 }; 4908 4909// Apply superblock scale (no mins for q6_K) 4910for (int i = 0 ;i < q8_k_blocklen ;i ++ ) { 4911for (int j = 0 ;j < 2 ;j ++ ) { 4912float32x4_t q8_d = vdupq_n_f32 (q8_ptr [b ].d [i ]); 4913float32x4_t q6_d = vcvt_f32_f16 (vld1_f16 ((const __fp16 * ) (q6_ptr [b ].d + j * 4 ))); 4914const float32x4_t scale = vmulq_f32 (q6_d ,q8_d ); 4915 4916acc_f32 [2 * i + j ]= 4917vmlaq_f32 (acc_f32 [2 * i + j ],vcvtq_f32_s32 (reorder_acc [2 * i + j ]),scale ); 4918 } 4919 } 4920 }// for b 4921 4922// Store results 4923for (int i = 0 ;i < q8_k_blocklen ;i ++ ) { 4924int row = y * q8_k_blocklen + i ; 4925for (int j = 0 ;j < 2 ;j ++ ) { 4926int col = x * ncols_interleaved + j * 4 ; 4927int offset = row * bs + col ; 4928vst1q_f32 (s + offset ,acc_f32 [2 * i + j ]); 4929 } 4930 } 4931 }// for x 4932 }// for y 4933return ; 4934#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_MATMUL_INT8) 4935ggml_gemm_q6_K_8x8_q8_K_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 4936} 4937 4938void ggml_gemm_q8_0_4x4_q8_0 (int n , 4939float * GGML_RESTRICT s , 4940size_t bs , 4941const void * GGML_RESTRICT vx , 4942const void * GGML_RESTRICT vy , 4943int nr , 4944int nc ) { 4945const int qk = QK8_0 ; 4946const int nb = n /qk ; 4947const int ncols_interleaved = 4 ; 4948const int blocklen = 4 ; 4949 4950assert (n %qk == 0 ); 4951assert (nr %4 == 0 ); 4952assert (nc %ncols_interleaved == 0 ); 4953 4954UNUSED (nb ); 4955UNUSED (ncols_interleaved ); 4956UNUSED (blocklen ); 4957 4958#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_DOTPROD ) 4959for (int y = 0 ;y < nr /4 ;y ++ ) { 4960const block_q8_0x4 * a_ptr = (const block_q8_0x4 * )vy + (y * nb ); 4961for (int x = 0 ;x < nc /ncols_interleaved ;x ++ ) { 4962const block_q8_0x4 * b_ptr = (const block_q8_0x4 * )vx + (x * nb ); 4963 4964float32x4_t sumf [4 ]; 4965for (int m = 0 ;m < 4 ;m ++ ) { 4966sumf [m ]= vdupq_n_f32 (0 ); 4967 } 4968 4969for (int l = 0 ;l < nb ;l ++ ) { 4970float32x4_t a_d = vcvt_f32_f16 (vld1_f16 ((const float16_t * )a_ptr [l ].d )); 4971float32x4_t b_d = vcvt_f32_f16 (vld1_f16 ((const float16_t * )b_ptr [l ].d )); 4972 4973int32x4_t sumi_0 = vdupq_n_s32 (0 ); 4974int32x4_t sumi_1 = vdupq_n_s32 (0 ); 4975int32x4_t sumi_2 = vdupq_n_s32 (0 ); 4976int32x4_t sumi_3 = vdupq_n_s32 (0 ); 4977 4978for (int k_group = 0 ;k_group < 8 ;k_group += 4 ) { 4979int8x16x4_t a = vld1q_s8_x4 (a_ptr [l ].qs + 16 * k_group ); 4980int8x16x4_t b = vld1q_s8_x4 (b_ptr [l ].qs + 16 * k_group ); 4981 4982for (int k = 0 ;k < 4 ;k ++ ) { 4983sumi_0 = vdotq_laneq_s32 (sumi_0 ,b .val [k ],a .val [k ],0 ); 4984sumi_1 = vdotq_laneq_s32 (sumi_1 ,b .val [k ],a .val [k ],1 ); 4985sumi_2 = vdotq_laneq_s32 (sumi_2 ,b .val [k ],a .val [k ],2 ); 4986sumi_3 = vdotq_laneq_s32 (sumi_3 ,b .val [k ],a .val [k ],3 ); 4987 } 4988 } 4989 4990sumf [0 ]= vmlaq_f32 (sumf [0 ],vmulq_laneq_f32 (b_d ,a_d ,0 ),vcvtq_f32_s32 (sumi_0 )); 4991sumf [1 ]= vmlaq_f32 (sumf [1 ],vmulq_laneq_f32 (b_d ,a_d ,1 ),vcvtq_f32_s32 (sumi_1 )); 4992sumf [2 ]= vmlaq_f32 (sumf [2 ],vmulq_laneq_f32 (b_d ,a_d ,2 ),vcvtq_f32_s32 (sumi_2 )); 4993sumf [3 ]= vmlaq_f32 (sumf [3 ],vmulq_laneq_f32 (b_d ,a_d ,3 ),vcvtq_f32_s32 (sumi_3 )); 4994 } 4995 4996for (int m = 0 ;m < 4 ;m ++ ) { 4997vst1q_f32 (s + (y * 4 + m )* bs + x * 4 ,sumf [m ]); 4998 } 4999 } 5000 } 5001return ; 5002#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) 5003ggml_gemm_q8_0_4x4_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 5004} 5005 5006void ggml_gemm_q8_0_4x8_q8_0 (int n , 5007float * GGML_RESTRICT s , 5008size_t bs , 5009const void * GGML_RESTRICT vx , 5010const void * GGML_RESTRICT vy , 5011int nr , 5012int nc ) { 5013const int qk = QK8_0 ; 5014const int nb = n /qk ; 5015const int ncols_interleaved = 4 ; 5016const int blocklen = 8 ; 5017 5018assert (n %qk == 0 ); 5019assert (nr %4 == 0 ); 5020assert (nc %ncols_interleaved == 0 ); 5021 5022UNUSED (nb ); 5023UNUSED (ncols_interleaved ); 5024UNUSED (blocklen ); 5025 5026#if defined(__aarch64__ )&& defined(__ARM_FEATURE_SVE )&& defined(__ARM_FEATURE_MATMUL_INT8 ) 5027if (svcntb ()* 8 == 256 ) { 5028const block_q8_0x4 * b_ptr_base = (const block_q8_0x4 * )vx ; 5029 5030static const uint32_t idx_arr [8 ]= {0 ,1 ,4 ,5 ,2 ,3 ,6 ,7 }; 5031svuint32_t idx = svld1 (svptrue_b32 (),idx_arr ); 5032static const uint32_t idx_arr1 [8 ]= {0 ,1 ,2 ,3 ,1 ,2 ,3 ,0 }; 5033svuint32_t idx_sc1 = svld1 (svptrue_b32 (),idx_arr1 ); 5034static const uint32_t idx_arr2 [8 ]= {0 ,1 ,2 ,3 ,0 ,1 ,2 ,3 }; 5035svuint32_t idx_sc2 = svld1 (svptrue_b32 (),idx_arr2 ); 5036 5037for (int y = 0 ;y < nr ;y += 4 ) { 5038const block_q8_0x4 * a_ptr_base = (const block_q8_0x4 * )vy + (y /4 )* nb ; 5039 5040for (int x = 0 ;x < nc ;x += ncols_interleaved ) { 5041const block_q8_0x4 * b_ptr = b_ptr_base + (x /4 )* nb ; 5042const block_q8_0x4 * a_ptr = a_ptr_base ; 5043 5044svfloat32_t acc_f32_01 = svdup_f32 (0 ); 5045svfloat32_t acc_f32_23 = svdup_f32 (0 ); 5046 5047for (int b = 0 ;b < nb ;b ++ ) { 5048 5049svint32_t acc_01 = svdup_s32 (0 ); 5050svint32_t acc_23 = svdup_s32 (0 ); 5051 5052// Process 4 chunks of 8 positions each 5053for (int chunk = 0 ;chunk < 4 ;chunk ++ ) { 5054svint8_t s_a01 = svld1rq_s8 (svptrue_b8 (),a_ptr -> qs + chunk * 32 ); 5055svint8_t s_a23 = svld1rq_s8 (svptrue_b8 (),a_ptr -> qs + chunk * 32 + 16 ); 5056svint8_t s_b0123 = svld1_s8 (svptrue_b8 (),b_ptr -> qs + chunk * 32 ); 5057 5058acc_01 = svmmla_s32 (acc_01 ,s_a01 ,s_b0123 ); 5059acc_23 = svmmla_s32 (acc_23 ,s_a23 ,s_b0123 ); 5060 } 5061 5062// Reorder outputs from 2×2 tiles to row-major 5063// acc[01] = [r0c0, r0c1, r1c0, r1c1, r0c2, r0c3, r1c2, r1c3] 5064// acc[23] = [r2c0, r2c1, r3c0, r3c1, r2c2, r2c3, r3c2, r3c3] 5065 5066svint32_t row01 = svtbl_s32 (acc_01 ,idx ); 5067svint32_t row23 = svtbl_s32 (acc_23 ,idx ); 5068 5069svfloat16_t temp1 = svld1_f16 (svptrue_pat_b16 (SV_VL4 ), (const __fp16 * )a_ptr -> d ); 5070svfloat16_t temp2 = svld1_f16 (svptrue_pat_b16 (SV_VL4 ), (const __fp16 * )b_ptr -> d ); 5071svfloat32_t sv_a_d = svtbl_f32 (svcvt_f32_f16_x (svptrue_b32 (),svzip1_f16 (temp1 ,temp1 )),idx_sc1 ); 5072svfloat32_t sv_b_d = svtbl_f32 (svcvt_f32_f16_x (svptrue_b32 (),svzip1_f16 (temp2 ,temp2 )),idx_sc2 ); 5073 5074acc_f32_01 = svmla_f32_x (svptrue_b32 (),acc_f32_01 ,svcvt_f32_s32_x (svptrue_b32 (),row01 ),svmul_lane_f32 (sv_b_d ,sv_a_d ,0 )); 5075acc_f32_23 = svmla_f32_x (svptrue_b32 (),acc_f32_23 ,svcvt_f32_s32_x (svptrue_b32 (),row23 ),svmul_lane_f32 (sv_b_d ,sv_a_d ,2 )); 5076a_ptr ++ ; 5077b_ptr ++ ; 5078 } 5079 5080svbool_t pg4 = svptrue_pat_b32 (SV_VL4 ); 5081svst1_f32 (pg4 ,s + (y + 0 )* bs + x ,acc_f32_01 ); 5082svst1_f32 (pg4 ,s + (y + 1 )* bs + x ,svext_f32 (acc_f32_01 ,acc_f32_01 ,4 )); 5083svst1_f32 (pg4 ,s + (y + 2 )* bs + x ,acc_f32_23 ); 5084svst1_f32 (pg4 ,s + (y + 3 )* bs + x ,svext_f32 (acc_f32_23 ,acc_f32_23 ,4 )); 5085 } 5086 } 5087return ; 5088 } 5089#endif // SVE compile-time end 5090 5091#if defined(__aarch64__ )&& defined(__ARM_NEON )&& defined(__ARM_FEATURE_MATMUL_INT8 ) 5092const block_q8_0x4 * b_ptr_base = (const block_q8_0x4 * )vx ; 5093 5094for (int y = 0 ;y < nr ;y += 4 ) { 5095const block_q8_0x4 * a_ptr_base = (const block_q8_0x4 * )vy + (y /4 )* nb ; 5096 5097for (int x = 0 ;x < nc ;x += ncols_interleaved ) { 5098const block_q8_0x4 * b_ptr = b_ptr_base + (x /4 )* nb ; 5099const block_q8_0x4 * a_ptr = a_ptr_base ; 5100 5101float32x4_t acc_f32 [4 ]; 5102for (int i = 0 ;i < 4 ;i ++ ) { 5103acc_f32 [i ]= vdupq_n_f32 (0 ); 5104 } 5105 5106for (int b = 0 ;b < nb ;b ++ ) { 5107int32x4_t acc [4 ]; 5108for (int i = 0 ;i < 4 ;i ++ ) { 5109acc [i ]= vdupq_n_s32 (0 ); 5110 } 5111 5112// Process 4 chunks of 8 positions each 5113for (int chunk = 0 ;chunk < 4 ;chunk ++ ) { 5114int8x16_t a01 = vld1q_s8 (a_ptr -> qs + chunk * 32 ); 5115int8x16_t a23 = vld1q_s8 (a_ptr -> qs + chunk * 32 + 16 ); 5116int8x16_t b01 = vld1q_s8 (b_ptr -> qs + chunk * 32 ); 5117int8x16_t b23 = vld1q_s8 (b_ptr -> qs + chunk * 32 + 16 ); 5118 5119acc [0 ]= vmmlaq_s32 (acc [0 ],a01 ,b01 ); 5120acc [1 ]= vmmlaq_s32 (acc [1 ],a01 ,b23 ); 5121acc [2 ]= vmmlaq_s32 (acc [2 ],a23 ,b01 ); 5122acc [3 ]= vmmlaq_s32 (acc [3 ],a23 ,b23 ); 5123 } 5124 5125// Reorder outputs from 2×2 tiles to row-major 5126// acc[0] = [r0c0, r0c1, r1c0, r1c1] 5127// acc[1] = [r0c2, r0c3, r1c2, r1c3] 5128// acc[2] = [r2c0, r2c1, r3c0, r3c1] 5129// acc[3] = [r2c2, r2c3, r3c2, r3c3] 5130int32x4_t row0 = vcombine_s32 (vget_low_s32 (acc [0 ]),vget_low_s32 (acc [1 ])); 5131int32x4_t row1 = vcombine_s32 (vget_high_s32 (acc [0 ]),vget_high_s32 (acc [1 ])); 5132int32x4_t row2 = vcombine_s32 (vget_low_s32 (acc [2 ]),vget_low_s32 (acc [3 ])); 5133int32x4_t row3 = vcombine_s32 (vget_high_s32 (acc [2 ]),vget_high_s32 (acc [3 ])); 5134 5135// Scales 5136float32x4_t a_d = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )a_ptr -> d )); 5137float32x4_t b_d = vcvt_f32_f16 (vld1_f16 ((const __fp16 * )b_ptr -> d )); 5138 5139acc_f32 [0 ]= vfmaq_f32 (acc_f32 [0 ],vcvtq_f32_s32 (row0 ),vmulq_laneq_f32 (b_d ,a_d ,0 )); 5140acc_f32 [1 ]= vfmaq_f32 (acc_f32 [1 ],vcvtq_f32_s32 (row1 ),vmulq_laneq_f32 (b_d ,a_d ,1 )); 5141acc_f32 [2 ]= vfmaq_f32 (acc_f32 [2 ],vcvtq_f32_s32 (row2 ),vmulq_laneq_f32 (b_d ,a_d ,2 )); 5142acc_f32 [3 ]= vfmaq_f32 (acc_f32 [3 ],vcvtq_f32_s32 (row3 ),vmulq_laneq_f32 (b_d ,a_d ,3 )); 5143 5144a_ptr ++ ; 5145b_ptr ++ ; 5146 } 5147 5148for (int row = 0 ;row < 4 ;row ++ ) { 5149vst1q_f32 (s + (y + row )* bs + x ,acc_f32 [row ]); 5150 } 5151 } 5152 } 5153return ; 5154#endif // defined(__aarch64__) && defined(__ARM_NEON) && defined(__ARM_FEATURE_MATMUL_INT8) 5155ggml_gemm_q8_0_4x8_q8_0_generic (n ,s ,bs ,vx ,vy ,nr ,nc ); 5156}