char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
4c5130961
char/aliceai-t5-moe
1#define GGML_COMMON_IMPL_C 2#include "ggml-common.h" 3#include "ggml-quants.h" 4#include "ggml-impl.h" 5#include "ggml-cpu.h" 6#include "simd-mappings.h" 7 8#include "../../quants.h" 9#include "../../ggml-cpu-impl.h" 10 11#include <math.h> 12#include <string.h> 13#include <assert.h> 14#include <float.h> 15#include <stdlib.h> // for qsort 16#include <stdio.h> // for GGML_ASSERT 17 18#define GROUP_MAX_EPS 1e-15f 19#define GROUP_MAX_EPS_IQ3_XXS 1e-8f 20#define GROUP_MAX_EPS_IQ2_S 1e-8f 21#define GROUP_MAX_EPS_IQ1_M 1e-7f 22#define GROUP_MAX_EPS_IQ1_S 1e-12f 23 24#define UNUSED GGML_UNUSED 25 26#if defined(__wasm_simd128__ ) 27#define B1 (c ,s ,n ) 0x ## n ## c , 0x ## n ## s 28#define B2 (c ,s ,n ) B1(c,s,n ## c), B1(c,s,n ## s) 29#define B3 (c ,s ,n ) B2(c,s,n ## c), B2(c,s,n ## s) 30#define B4 (c ,s ,n ) B3(c,s,n ## c), B3(c,s,n ## s) 31#define B5 (c ,s ,n ) B4(c,s,n ## c), B4(c,s,n ## s) 32#define B6 (c ,s ,n ) B5(c,s,n ## c), B5(c,s,n ## s) 33#define B7 (c ,s ,n ) B6(c,s,n ## c), B6(c,s,n ## s) 34#define B8 (c ,s ) B7(c,s, c), B7(c,s, s) 35 36// precomputed tables for expanding 8bits to 8 bytes: 37static const uint64_t table_b2b_0 [1 <<8 ]= {B8 (00 ,10 ) };// ( b) << 4 38static const uint64_t table_b2b_1 [1 <<8 ]= {B8 (10 ,00 ) };// (!b) << 4 39#endif 40 41void quantize_row_q8_0 (const float * GGML_RESTRICT x ,void * GGML_RESTRICT vy ,int64_t k ) { 42assert (QK8_0 == 32 ); 43assert (k %QK8_0 == 0 ); 44const int nb = k /QK8_0 ; 45 46block_q8_0 * GGML_RESTRICT y = vy ; 47 48#if defined__wasm_simd128__ 49for (int i = 0 ;i < nb ;i ++ ) { 50v128_t srcv [8 ]; 51v128_t asrcv [8 ]; 52v128_t amaxv [8 ]; 53 54for (int j = 0 ;j < 8 ;j ++ )srcv [j ]= wasm_v128_load (x + i * 32 + 4 * j ); 55for (int j = 0 ;j < 8 ;j ++ )asrcv [j ]= wasm_f32x4_abs (srcv [j ]); 56 57for (int j = 0 ;j < 4 ;j ++ )amaxv [2 * j ]= wasm_f32x4_max (asrcv [2 * j ],asrcv [2 * j + 1 ]); 58for (int j = 0 ;j < 2 ;j ++ )amaxv [4 * j ]= wasm_f32x4_max (amaxv [4 * j ],amaxv [4 * j + 2 ]); 59for (int j = 0 ;j < 1 ;j ++ )amaxv [8 * j ]= wasm_f32x4_max (amaxv [8 * j ],amaxv [8 * j + 4 ]); 60 61const float amax = MAX (MAX (wasm_f32x4_extract_lane (amaxv [0 ],0 ), 62wasm_f32x4_extract_lane (amaxv [0 ],1 )), 63MAX (wasm_f32x4_extract_lane (amaxv [0 ],2 ), 64wasm_f32x4_extract_lane (amaxv [0 ],3 ))); 65 66const float d = amax / ((1 <<7 )- 1 ); 67const float id = d ?1.0f /d :0.0f ; 68 69y [i ].d = GGML_CPU_FP32_TO_FP16 (d ); 70 71for (int j = 0 ;j < 8 ;j ++ ) { 72const v128_t v = wasm_f32x4_mul (srcv [j ],wasm_f32x4_splat (id )); 73const v128_t vi = wasm_i32x4_trunc_sat_f32x4 (v ); 74 75y [i ].qs [4 * j + 0 ]= wasm_i32x4_extract_lane (vi ,0 ); 76y [i ].qs [4 * j + 1 ]= wasm_i32x4_extract_lane (vi ,1 ); 77y [i ].qs [4 * j + 2 ]= wasm_i32x4_extract_lane (vi ,2 ); 78y [i ].qs [4 * j + 3 ]= wasm_i32x4_extract_lane (vi ,3 ); 79 } 80 } 81#else 82GGML_UNUSED (nb ); 83// scalar 84quantize_row_q8_0_ref (x ,y ,k ); 85#endif 86} 87 88void quantize_row_q8_1 (const float * GGML_RESTRICT x ,void * GGML_RESTRICT vy ,int64_t k ) { 89assert (k %QK8_1 == 0 ); 90const int nb = k /QK8_1 ; 91 92block_q8_1 * GGML_RESTRICT y = vy ; 93#if defined__wasm_simd128__ 94for (int i = 0 ;i < nb ;i ++ ) { 95v128_t srcv [8 ]; 96v128_t asrcv [8 ]; 97v128_t amaxv [8 ]; 98 99for (int j = 0 ;j < 8 ;j ++ )srcv [j ]= wasm_v128_load (x + i * 32 + 4 * j ); 100for (int j = 0 ;j < 8 ;j ++ )asrcv [j ]= wasm_f32x4_abs (srcv [j ]); 101 102for (int j = 0 ;j < 4 ;j ++ )amaxv [2 * j ]= wasm_f32x4_max (asrcv [2 * j ],asrcv [2 * j + 1 ]); 103for (int j = 0 ;j < 2 ;j ++ )amaxv [4 * j ]= wasm_f32x4_max (amaxv [4 * j ],amaxv [4 * j + 2 ]); 104for (int j = 0 ;j < 1 ;j ++ )amaxv [8 * j ]= wasm_f32x4_max (amaxv [8 * j ],amaxv [8 * j + 4 ]); 105 106const float amax = MAX (MAX (wasm_f32x4_extract_lane (amaxv [0 ],0 ), 107wasm_f32x4_extract_lane (amaxv [0 ],1 )), 108MAX (wasm_f32x4_extract_lane (amaxv [0 ],2 ), 109wasm_f32x4_extract_lane (amaxv [0 ],3 ))); 110 111const float d = amax / ((1 <<7 )- 1 ); 112const float id = d ?1.0f /d :0.0f ; 113 114y [i ].d = GGML_CPU_FP32_TO_FP16 (d ); 115 116v128_t accv = wasm_i32x4_splat (0 ); 117 118for (int j = 0 ;j < 8 ;j ++ ) { 119const v128_t v = wasm_f32x4_mul (srcv [j ],wasm_f32x4_splat (id )); 120const v128_t vi = wasm_i32x4_trunc_sat_f32x4 (v ); 121 122y [i ].qs [4 * j + 0 ]= wasm_i32x4_extract_lane (vi ,0 ); 123y [i ].qs [4 * j + 1 ]= wasm_i32x4_extract_lane (vi ,1 ); 124y [i ].qs [4 * j + 2 ]= wasm_i32x4_extract_lane (vi ,2 ); 125y [i ].qs [4 * j + 3 ]= wasm_i32x4_extract_lane (vi ,3 ); 126 127accv = wasm_i32x4_add (accv ,vi ); 128 } 129 130y [i ].s = GGML_CPU_FP32_TO_FP16 ( 131d * (wasm_i32x4_extract_lane (accv ,0 )+ 132wasm_i32x4_extract_lane (accv ,1 )+ 133wasm_i32x4_extract_lane (accv ,2 )+ 134wasm_i32x4_extract_lane (accv ,3 ))); 135 } 136#else 137GGML_UNUSED (nb ); 138// scalar 139quantize_row_q8_1_ref (x ,y ,k ); 140#endif 141} 142 143//===================================== Q8_K ============================================== 144 145void quantize_row_q8_K (const float * GGML_RESTRICT x ,void * GGML_RESTRICT y ,int64_t k ) { 146#ifdef __wasm_simd128__ 147assert (k %QK_K == 0 ); 148const int64_t nb = k /QK_K ; 149block_q8_K * GGML_RESTRICT yc = y ;// Cast to proper type 150 151for (int i = 0 ;i < nb ;i ++ ) { 152const float * x_block = x + i * QK_K ; 153 154v128_t min_vec = wasm_v128_load (x_block ); 155v128_t max_vec = min_vec ; 156 157for (int j = 4 ;j < QK_K ;j += 4 ) { 158v128_t x_vec = wasm_v128_load (x_block + j ); 159max_vec = wasm_f32x4_pmax (max_vec ,x_vec ); 160min_vec = wasm_f32x4_pmin (min_vec ,x_vec ); 161 } 162max_vec = wasm_f32x4_pmax (max_vec ,wasm_i32x4_shuffle (max_vec ,max_vec ,2 ,3 ,0 ,1 )); 163max_vec = wasm_f32x4_pmax (max_vec ,wasm_i32x4_shuffle (max_vec ,max_vec ,1 ,0 ,3 ,2 )); 164min_vec = wasm_f32x4_pmin (min_vec ,wasm_i32x4_shuffle (min_vec ,min_vec ,2 ,3 ,0 ,1 )); 165min_vec = wasm_f32x4_pmin (min_vec ,wasm_i32x4_shuffle (min_vec ,min_vec ,1 ,0 ,3 ,2 )); 166float max = wasm_f32x4_extract_lane (max_vec ,0 ); 167float min = wasm_f32x4_extract_lane (min_vec ,0 ); 168float amax = - min > max ?min :max ; 169 170if (amax == 0.0f ) { 171yc [i ].d = 0.0f ; 172const v128_t zero = wasm_i8x16_splat (0 ); 173for (int j = 0 ;j < QK_K ;j += 16 ) { 174wasm_v128_store (yc [i ].qs + j ,zero ); 175 } 176continue ; 177 } 178 179const float iscale = -127.0f /amax ; 180const v128_t scale_vec = wasm_f32x4_splat (iscale ); 181 182// Process 16 elements per iteration 183for (int j = 0 ,jb = 0 ;j < QK_K ;j += 16 ,jb ++ ) { 184// Load and quantize 16 floats 185v128_t x0 = wasm_v128_load (x_block + j ); 186v128_t x1 = wasm_v128_load (x_block + j + 4 ); 187v128_t x2 = wasm_v128_load (x_block + j + 8 ); 188v128_t x3 = wasm_v128_load (x_block + j + 12 ); 189 190v128_t q0 = wasm_f32x4_nearest (wasm_f32x4_mul (x0 ,scale_vec )); 191v128_t q1 = wasm_f32x4_nearest (wasm_f32x4_mul (x1 ,scale_vec )); 192v128_t q2 = wasm_f32x4_nearest (wasm_f32x4_mul (x2 ,scale_vec )); 193v128_t q3 = wasm_f32x4_nearest (wasm_f32x4_mul (x3 ,scale_vec )); 194 195// Convert to i32 with saturation 196v128_t i0 = wasm_i32x4_trunc_sat_f32x4 (q0 ); 197v128_t i1 = wasm_i32x4_trunc_sat_f32x4 (q1 ); 198v128_t i2 = wasm_i32x4_trunc_sat_f32x4 (q2 ); 199v128_t i3 = wasm_i32x4_trunc_sat_f32x4 (q3 ); 200 201// Pack into 16 i8 values 202v128_t i8 = wasm_i8x16_narrow_i16x8 ( 203wasm_i16x8_narrow_i32x4 (i0 ,i1 ), 204wasm_i16x8_narrow_i32x4 (i2 ,i3 ) 205 ); 206wasm_v128_store (yc [i ].qs + j ,i8 ); 207 208// Calculate bsums using SIMD 209v128_t sum16 = wasm_i16x8_add ( 210wasm_i16x8_extend_low_i8x16 (i8 ), 211wasm_i16x8_extend_high_i8x16 (i8 ) 212 ); 213v128_t sum32 = wasm_i32x4_add ( 214wasm_i32x4_extend_low_i16x8 (sum16 ), 215wasm_i32x4_extend_high_i16x8 (sum16 ) 216 ); 217sum32 = wasm_i32x4_add (sum32 ,wasm_i32x4_shuffle (sum32 ,sum32 ,2 ,3 ,0 ,1 )); 218sum32 = wasm_i32x4_add (sum32 ,wasm_i32x4_shuffle (sum32 ,sum32 ,1 ,0 ,3 ,2 )); 219yc [i ].bsums [jb ]= wasm_i32x4_extract_lane (sum32 ,0 ); 220 } 221 222yc [i ].d = 1.0f /iscale ; 223 } 224#else 225quantize_row_q8_K_ref (x ,y ,k ); 226#endif 227} 228 229 230//===================================== Dot products ================================= 231 232void ggml_vec_dot_q4_0_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,size_t bx ,const void * GGML_RESTRICT vy ,size_t by ,int nrc ) { 233const int qk = QK8_0 ; 234const int nb = n /qk ; 235 236assert (n %qk == 0 ); 237assert (nrc == 1 ); 238UNUSED (nrc ); 239UNUSED (bx ); 240UNUSED (by ); 241UNUSED (bs ); 242 243const block_q4_0 * GGML_RESTRICT x = vx ; 244const block_q8_0 * GGML_RESTRICT y = vy ; 245 246int ib = 0 ; 247float sumf = 0 ; 248 249#if defined__wasm_simd128__ 250v128_t sumv = wasm_f32x4_splat (0.0f ); 251 252const v128_t m4b = wasm_i8x16_splat (0x0F ); 253const v128_t s8b = wasm_i8x16_splat (0x8 ); 254 255for (;ib + 1 < nb ;ib += 2 ) { 256const block_q4_0 * GGML_RESTRICT x0 = & x [ib ]; 257const block_q4_0 * GGML_RESTRICT x1 = & x [ib + 1 ]; 258const block_q8_0 * GGML_RESTRICT y0 = & y [ib ]; 259const block_q8_0 * GGML_RESTRICT y1 = & y [ib + 1 ]; 260 261// Load and process x0 262v128_t v0_0 = wasm_v128_load (x0 -> qs ); 263v128_t v0_0l = wasm_v128_and (v0_0 ,m4b ); 264v128_t v0_0h = wasm_u8x16_shr (v0_0 ,4 ); 265v128_t v0_0ls = wasm_i8x16_sub (v0_0l ,s8b ); 266v128_t v0_0hs = wasm_i8x16_sub (v0_0h ,s8b ); 267 268// Load y0 vectors 269v128_t y0_l = wasm_v128_load (y0 -> qs ); 270v128_t y0_h = wasm_v128_load (y0 -> qs + 16 ); 271 272// Extend to i16x8 and compute dot products 273v128_t dx0l = wasm_i16x8_extend_low_i8x16 (v0_0ls ); 274v128_t dx0h = wasm_i16x8_extend_high_i8x16 (v0_0ls ); 275v128_t dx0hl = wasm_i16x8_extend_low_i8x16 (v0_0hs ); 276v128_t dx0hh = wasm_i16x8_extend_high_i8x16 (v0_0hs ); 277 278v128_t dy0ll = wasm_i16x8_extend_low_i8x16 (y0_l ); 279v128_t dy0lh = wasm_i16x8_extend_high_i8x16 (y0_l ); 280v128_t dy0hl = wasm_i16x8_extend_low_i8x16 (y0_h ); 281v128_t dy0hh = wasm_i16x8_extend_high_i8x16 (y0_h ); 282 283v128_t dp0 = wasm_i32x4_add ( 284wasm_i32x4_add ( 285wasm_i32x4_dot_i16x8 (dx0l ,dy0ll ), 286wasm_i32x4_dot_i16x8 (dx0h ,dy0lh ) 287 ), 288wasm_i32x4_add ( 289wasm_i32x4_dot_i16x8 (dx0hl ,dy0hl ), 290wasm_i32x4_dot_i16x8 (dx0hh ,dy0hh ) 291 ) 292 ); 293 294// Load and process x1 295v128_t v0_1 = wasm_v128_load (x1 -> qs ); 296v128_t v0_1l = wasm_v128_and (v0_1 ,m4b ); 297v128_t v0_1h = wasm_u8x16_shr (v0_1 ,4 ); 298v128_t v0_1ls = wasm_i8x16_sub (v0_1l ,s8b ); 299v128_t v0_1hs = wasm_i8x16_sub (v0_1h ,s8b ); 300 301// Load y1 vectors 302v128_t y1_l = wasm_v128_load (y1 -> qs ); 303v128_t y1_h = wasm_v128_load (y1 -> qs + 16 ); 304 305// Extend to i16x8 and compute dot products 306v128_t dx1l = wasm_i16x8_extend_low_i8x16 (v0_1ls ); 307v128_t dx1h = wasm_i16x8_extend_high_i8x16 (v0_1ls ); 308v128_t dx1hl = wasm_i16x8_extend_low_i8x16 (v0_1hs ); 309v128_t dx1hh = wasm_i16x8_extend_high_i8x16 (v0_1hs ); 310 311v128_t dy1ll = wasm_i16x8_extend_low_i8x16 (y1_l ); 312v128_t dy1lh = wasm_i16x8_extend_high_i8x16 (y1_l ); 313v128_t dy1hl = wasm_i16x8_extend_low_i8x16 (y1_h ); 314v128_t dy1hh = wasm_i16x8_extend_high_i8x16 (y1_h ); 315 316v128_t dp1 = wasm_i32x4_add ( 317wasm_i32x4_add ( 318wasm_i32x4_dot_i16x8 (dx1l ,dy1ll ), 319wasm_i32x4_dot_i16x8 (dx1h ,dy1lh ) 320 ), 321wasm_i32x4_add ( 322wasm_i32x4_dot_i16x8 (dx1hl ,dy1hl ), 323wasm_i32x4_dot_i16x8 (dx1hh ,dy1hh ) 324 ) 325 ); 326 327// Accumulate results with scaling 328float scale0 = GGML_CPU_FP16_TO_FP32 (x0 -> d )* GGML_CPU_FP16_TO_FP32 (y0 -> d ); 329float scale1 = GGML_CPU_FP16_TO_FP32 (x1 -> d )* GGML_CPU_FP16_TO_FP32 (y1 -> d ); 330 331sumv = wasm_f32x4_add (sumv ,wasm_f32x4_mul (wasm_f32x4_convert_i32x4 (dp0 ),wasm_f32x4_splat (scale0 ))); 332sumv = wasm_f32x4_add (sumv ,wasm_f32x4_mul (wasm_f32x4_convert_i32x4 (dp1 ),wasm_f32x4_splat (scale1 ))); 333 } 334 335sumf = wasm_f32x4_extract_lane (sumv ,0 )+ wasm_f32x4_extract_lane (sumv ,1 )+ 336wasm_f32x4_extract_lane (sumv ,2 )+ wasm_f32x4_extract_lane (sumv ,3 ); 337 338#endif 339for (;ib < nb ;++ ib ) { 340int sumi0 = 0 ; 341int sumi1 = 0 ; 342 343for (int j = 0 ;j < qk /2 ;++ j ) { 344const int v0 = (x [ib ].qs [j ]& 0x0F )- 8 ; 345const int v1 = (x [ib ].qs [j ] >>4 )- 8 ; 346 347sumi0 += (v0 * y [ib ].qs [j ]); 348sumi1 += (v1 * y [ib ].qs [j + qk /2 ]); 349 } 350 351int sumi = sumi0 + sumi1 ; 352sumf += sumi * GGML_CPU_FP16_TO_FP32 (x [ib ].d )* GGML_CPU_FP16_TO_FP32 (y [ib ].d ); 353 } 354 355* s = sumf ; 356} 357 358void ggml_vec_dot_q4_1_q8_1 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,size_t bx ,const void * GGML_RESTRICT vy ,size_t by ,int nrc ) { 359const int qk = QK8_1 ; 360const int nb = n /qk ; 361 362assert (n %qk == 0 ); 363assert (nrc == 1 ); 364UNUSED (nrc ); 365UNUSED (bx ); 366UNUSED (by ); 367UNUSED (bs ); 368 369const block_q4_1 * GGML_RESTRICT x = vx ; 370const block_q8_1 * GGML_RESTRICT y = vy ; 371 372float sumf = 0 ; 373 374#if defined__wasm_simd128__ 375v128_t sumv = wasm_f32x4_splat (0.0f ); 376float summs = 0.0f ; 377 378for (int ib = 0 ;ib < nb ;++ ib ) { 379const block_q4_1 * GGML_RESTRICT x0 = & x [ib ]; 380const block_q8_1 * GGML_RESTRICT y0 = & y [ib ]; 381 382summs += GGML_CPU_FP16_TO_FP32 (x0 -> m )* GGML_CPU_FP16_TO_FP32 (y0 -> s ); 383 384const v128_t raw = wasm_v128_load (x0 -> qs ); 385const v128_t v0s = wasm_v128_and (raw ,wasm_i8x16_splat (0x0F )); 386const v128_t v1s = wasm_u8x16_shr (raw ,4 ); 387 388const v128_t ys_lo = wasm_v128_load (y0 -> qs ); 389const v128_t ys_hi = wasm_v128_load (y0 -> qs + 16 ); 390 391const v128_t v0s_l = wasm_u16x8_extend_low_u8x16 (v0s ); 392const v128_t v0s_h = wasm_u16x8_extend_high_u8x16 (v0s ); 393const v128_t ylo_l = wasm_i16x8_extend_low_i8x16 (ys_lo ); 394const v128_t ylo_h = wasm_i16x8_extend_high_i8x16 (ys_lo ); 395const v128_t v1s_l = wasm_u16x8_extend_low_u8x16 (v1s ); 396const v128_t v1s_h = wasm_u16x8_extend_high_u8x16 (v1s ); 397const v128_t yhi_l = wasm_i16x8_extend_low_i8x16 (ys_hi ); 398const v128_t yhi_h = wasm_i16x8_extend_high_i8x16 (ys_hi ); 399 400const v128_t acc = wasm_i32x4_add ( 401wasm_i32x4_add ( 402wasm_i32x4_dot_i16x8 (v0s_l ,ylo_l ), 403wasm_i32x4_dot_i16x8 (v0s_h ,ylo_h )), 404wasm_i32x4_add ( 405wasm_i32x4_dot_i16x8 (v1s_l ,yhi_l ), 406wasm_i32x4_dot_i16x8 (v1s_h ,yhi_h ))); 407 408sumv = wasm_f32x4_add (sumv , 409wasm_f32x4_mul ( 410wasm_f32x4_convert_i32x4 (acc ), 411wasm_f32x4_splat (GGML_CPU_FP16_TO_FP32 (x0 -> d )* GGML_CPU_FP16_TO_FP32 (y0 -> d )))); 412 } 413 414sumf = wasm_f32x4_extract_lane (sumv ,0 )+ wasm_f32x4_extract_lane (sumv ,1 )+ 415wasm_f32x4_extract_lane (sumv ,2 )+ wasm_f32x4_extract_lane (sumv ,3 )+ summs ; 416 417* s = sumf ; 418 419#else 420UNUSED (nb ); 421UNUSED (x ); 422UNUSED (y ); 423UNUSED (sumf ); 424 425ggml_vec_dot_q4_1_q8_1_generic ( 426n ,s ,bs ,vx ,bx ,vy ,by ,nrc ); 427#endif 428} 429 430void ggml_vec_dot_q5_0_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,size_t bx ,const void * GGML_RESTRICT vy ,size_t by ,int nrc ) { 431const int qk = QK8_0 ; 432const int nb = n /qk ; 433 434int ib = 0 ; 435float sumf = 0 ; 436 437assert (n %qk == 0 ); 438assert (qk == QK5_0 ); 439assert (nrc == 1 ); 440UNUSED (nrc ); 441UNUSED (bx ); 442UNUSED (by ); 443UNUSED (bs ); 444 445const block_q5_0 * GGML_RESTRICT x = vx ; 446const block_q8_0 * GGML_RESTRICT y = vy ; 447 448#if defined__wasm_simd128__ 449v128_t sumv = wasm_f32x4_splat (0.0f ); 450 451uint32_t qh_ ; 452uint64_t tmp [4 ]; 453 454// TODO: check if unrolling this is better 455for (;ib < nb ;++ ib ) { 456const block_q5_0 * GGML_RESTRICT x0 = & x [ib ]; 457const block_q8_0 * GGML_RESTRICT y0 = & y [ib ]; 458 459const v128_t m4b = wasm_i8x16_splat (0x0F ); 460 461// extract the 5th bit 462memcpy (& qh_ ,x0 -> qh ,sizeof (qh_ )); 463 464tmp [0 ]= table_b2b_1 [(qh_ >>0 )& 0xFF ]; 465tmp [1 ]= table_b2b_1 [(qh_ >>8 )& 0xFF ]; 466tmp [2 ]= table_b2b_1 [(qh_ >>16 )& 0xFF ]; 467tmp [3 ]= table_b2b_1 [(qh_ >>24 ) ]; 468 469const v128_t qhl = wasm_v128_load (tmp + 0 ); 470const v128_t qhh = wasm_v128_load (tmp + 2 ); 471 472const v128_t v0 = wasm_v128_load (x0 -> qs ); 473 474// 4-bit -> 8-bit 475const v128_t v0l = wasm_v128_and (v0 ,m4b ); 476const v128_t v0h = wasm_u8x16_shr (v0 ,4 ); 477 478// add high bit and sub 16 (equivalent to sub 0x10 when bit is zero) 479const v128_t v0lf = wasm_i8x16_sub (v0l ,qhl ); 480const v128_t v0hf = wasm_i8x16_sub (v0h ,qhh ); 481 482// load y 483const v128_t v1l = wasm_v128_load (y0 -> qs ); 484const v128_t v1h = wasm_v128_load (y0 -> qs + 16 ); 485 486// int8x16 -> int16x8 487const v128_t v0lfl = wasm_i16x8_extend_low_i8x16 (v0lf ); 488const v128_t v0lfh = wasm_i16x8_extend_high_i8x16 (v0lf ); 489const v128_t v0hfl = wasm_i16x8_extend_low_i8x16 (v0hf ); 490const v128_t v0hfh = wasm_i16x8_extend_high_i8x16 (v0hf ); 491 492const v128_t v1ll = wasm_i16x8_extend_low_i8x16 (v1l ); 493const v128_t v1lh = wasm_i16x8_extend_high_i8x16 (v1l ); 494const v128_t v1hl = wasm_i16x8_extend_low_i8x16 (v1h ); 495const v128_t v1hh = wasm_i16x8_extend_high_i8x16 (v1h ); 496 497// dot product 498sumv = wasm_f32x4_add (sumv ,wasm_f32x4_mul (wasm_f32x4_convert_i32x4 ( 499wasm_i32x4_add ( 500wasm_i32x4_add (wasm_i32x4_dot_i16x8 (v0lfl ,v1ll ), 501wasm_i32x4_dot_i16x8 (v0lfh ,v1lh )), 502wasm_i32x4_add (wasm_i32x4_dot_i16x8 (v0hfl ,v1hl ), 503wasm_i32x4_dot_i16x8 (v0hfh ,v1hh )))), 504wasm_f32x4_splat (GGML_CPU_FP16_TO_FP32 (x0 -> d )* GGML_CPU_FP16_TO_FP32 (y0 -> d )))); 505 } 506 507sumf = wasm_f32x4_extract_lane (sumv ,0 )+ wasm_f32x4_extract_lane (sumv ,1 )+ 508wasm_f32x4_extract_lane (sumv ,2 )+ wasm_f32x4_extract_lane (sumv ,3 ); 509 510* s = sumf ; 511#else 512UNUSED (nb ); 513UNUSED (ib ); 514UNUSED (sumf ); 515UNUSED (x ); 516UNUSED (y ); 517ggml_vec_dot_q5_0_q8_0_generic (n ,s ,bs ,vx ,bx ,vy ,by ,nrc ); 518#endif 519} 520 521void ggml_vec_dot_q5_1_q8_1 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,size_t bx ,const void * GGML_RESTRICT vy ,size_t by ,int nrc ) { 522const int qk = QK8_1 ; 523const int nb = n /qk ; 524 525int ib = 0 ; 526float sumf = 0 ; 527 528assert (n %qk == 0 ); 529assert (qk == QK5_1 ); 530assert (nrc == 1 ); 531UNUSED (nrc ); 532UNUSED (bx ); 533UNUSED (by ); 534UNUSED (bs ); 535 536const block_q5_1 * GGML_RESTRICT x = vx ; 537const block_q8_1 * GGML_RESTRICT y = vy ; 538 539#if defined__wasm_simd128__ 540v128_t sumv = wasm_f32x4_splat (0.0f ); 541 542float summs = 0.0f ; 543 544uint32_t qh_ ; 545uint64_t tmp [4 ]; 546 547// TODO: check if unrolling this is better 548for (;ib < nb ;++ ib ) { 549const block_q5_1 * GGML_RESTRICT x0 = & x [ib ]; 550const block_q8_1 * GGML_RESTRICT y0 = & y [ib ]; 551 552summs += GGML_CPU_FP16_TO_FP32 (x0 -> m )* GGML_CPU_FP16_TO_FP32 (y0 -> s ); 553 554const v128_t m4b = wasm_i8x16_splat (0x0F ); 555 556// extract the 5th bit 557memcpy (& qh_ ,x0 -> qh ,sizeof (qh_ )); 558 559tmp [0 ]= table_b2b_0 [(qh_ >>0 )& 0xFF ]; 560tmp [1 ]= table_b2b_0 [(qh_ >>8 )& 0xFF ]; 561tmp [2 ]= table_b2b_0 [(qh_ >>16 )& 0xFF ]; 562tmp [3 ]= table_b2b_0 [(qh_ >>24 ) ]; 563 564const v128_t qhl = wasm_v128_load (tmp + 0 ); 565const v128_t qhh = wasm_v128_load (tmp + 2 ); 566 567const v128_t v0 = wasm_v128_load (x0 -> qs ); 568 569// 4-bit -> 8-bit 570const v128_t v0l = wasm_v128_and (v0 ,m4b ); 571const v128_t v0h = wasm_u8x16_shr (v0 ,4 ); 572 573// add high bit 574const v128_t v0lf = wasm_v128_or (v0l ,qhl ); 575const v128_t v0hf = wasm_v128_or (v0h ,qhh ); 576 577// load y 578const v128_t v1l = wasm_v128_load (y0 -> qs ); 579const v128_t v1h = wasm_v128_load (y0 -> qs + 16 ); 580 581// int8x16 -> int16x8 582const v128_t v0lfl = wasm_i16x8_extend_low_i8x16 (v0lf ); 583const v128_t v0lfh = wasm_i16x8_extend_high_i8x16 (v0lf ); 584const v128_t v0hfl = wasm_i16x8_extend_low_i8x16 (v0hf ); 585const v128_t v0hfh = wasm_i16x8_extend_high_i8x16 (v0hf ); 586 587const v128_t v1ll = wasm_i16x8_extend_low_i8x16 (v1l ); 588const v128_t v1lh = wasm_i16x8_extend_high_i8x16 (v1l ); 589const v128_t v1hl = wasm_i16x8_extend_low_i8x16 (v1h ); 590const v128_t v1hh = wasm_i16x8_extend_high_i8x16 (v1h ); 591 592// dot product 593sumv = wasm_f32x4_add (sumv , 594wasm_f32x4_mul (wasm_f32x4_convert_i32x4 (wasm_i32x4_add ( 595wasm_i32x4_add (wasm_i32x4_dot_i16x8 (v0lfl ,v1ll ), 596wasm_i32x4_dot_i16x8 (v0lfh ,v1lh )), 597wasm_i32x4_add (wasm_i32x4_dot_i16x8 (v0hfl ,v1hl ), 598wasm_i32x4_dot_i16x8 (v0hfh ,v1hh )))), 599wasm_f32x4_splat (GGML_CPU_FP16_TO_FP32 (x0 -> d )* GGML_CPU_FP16_TO_FP32 (y0 -> d )))); 600 } 601 602sumf = wasm_f32x4_extract_lane (sumv ,0 )+ wasm_f32x4_extract_lane (sumv ,1 )+ 603wasm_f32x4_extract_lane (sumv ,2 )+ wasm_f32x4_extract_lane (sumv ,3 )+ summs ; 604 605* s = sumf ; 606#else 607UNUSED (nb ); 608UNUSED (ib ); 609UNUSED (sumf ); 610UNUSED (x ); 611UNUSED (y ); 612ggml_vec_dot_q5_1_q8_1_generic (n ,s ,bs ,vx ,bx ,vy ,by ,nrc ); 613#endif 614} 615 616void ggml_vec_dot_q8_0_q8_0 (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,size_t bx ,const void * GGML_RESTRICT vy ,size_t by ,int nrc ) { 617const int qk = QK8_0 ; 618const int nb = n /qk ; 619 620assert (n %qk == 0 ); 621assert (nrc == 1 ); 622UNUSED (nrc ); 623UNUSED (bx ); 624UNUSED (by ); 625UNUSED (bs ); 626 627const block_q8_0 * GGML_RESTRICT x = vx ; 628const block_q8_0 * GGML_RESTRICT y = vy ; 629 630int ib = 0 ; 631float sumf = 0 ; 632 633#if defined__wasm_simd128__ 634v128_t sumv = wasm_f32x4_splat (0.0f ); 635 636for (;ib < nb ;++ ib ) { 637const block_q8_0 * GGML_RESTRICT x0 = & x [ib ]; 638const block_q8_0 * GGML_RESTRICT y0 = & y [ib ]; 639 640const v128_t x0_0 = wasm_v128_load (x0 -> qs ); 641const v128_t x0_1 = wasm_v128_load (x0 -> qs + 16 ); 642const v128_t y0_0 = wasm_v128_load (y0 -> qs ); 643const v128_t y0_1 = wasm_v128_load (y0 -> qs + 16 ); 644 645// Extend 8-bit to 16-bit 646const v128_t x0_0l = wasm_i16x8_extend_low_i8x16 (x0_0 ); 647const v128_t x0_0h = wasm_i16x8_extend_high_i8x16 (x0_0 ); 648const v128_t x0_1l = wasm_i16x8_extend_low_i8x16 (x0_1 ); 649const v128_t x0_1h = wasm_i16x8_extend_high_i8x16 (x0_1 ); 650 651const v128_t y0_0l = wasm_i16x8_extend_low_i8x16 (y0_0 ); 652const v128_t y0_0h = wasm_i16x8_extend_high_i8x16 (y0_0 ); 653const v128_t y0_1l = wasm_i16x8_extend_low_i8x16 (y0_1 ); 654const v128_t y0_1h = wasm_i16x8_extend_high_i8x16 (y0_1 ); 655 656// Compute dot products 657const v128_t dx0_0 = wasm_i32x4_dot_i16x8 (x0_0l ,y0_0l ); 658const v128_t dx0_1 = wasm_i32x4_dot_i16x8 (x0_0h ,y0_0h ); 659const v128_t dx1_0 = wasm_i32x4_dot_i16x8 (x0_1l ,y0_1l ); 660const v128_t dx1_1 = wasm_i32x4_dot_i16x8 (x0_1h ,y0_1h ); 661 662// Sum all dot products 663const v128_t sum_dots = wasm_i32x4_add (wasm_i32x4_add (dx0_0 ,dx0_1 ),wasm_i32x4_add (dx1_0 ,dx1_1 )); 664 665// Convert to float and accumulate 666const float scale = GGML_CPU_FP16_TO_FP32 (x0 -> d )* GGML_CPU_FP16_TO_FP32 (y0 -> d ); 667sumv = wasm_f32x4_add (sumv ,wasm_f32x4_mul (wasm_f32x4_convert_i32x4 (sum_dots ),wasm_f32x4_splat (scale ))); 668 } 669 670sumf = wasm_f32x4_extract_lane (sumv ,0 )+ wasm_f32x4_extract_lane (sumv ,1 )+ 671wasm_f32x4_extract_lane (sumv ,2 )+ wasm_f32x4_extract_lane (sumv ,3 ); 672 673* s = sumf ; 674#else 675UNUSED (nb ); 676UNUSED (x ); 677UNUSED (y ); 678UNUSED (ib ); 679UNUSED (sumf ); 680ggml_vec_dot_q8_0_q8_0_generic (n ,s ,bs ,vx ,bx ,vy ,by ,nrc ); 681#endif 682} 683 684void ggml_vec_dot_q2_K_q8_K (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,size_t bx ,const void * GGML_RESTRICT vy ,size_t by ,int nrc ) { 685assert (nrc == 1 ); 686UNUSED (nrc ); 687UNUSED (bx ); 688UNUSED (by ); 689UNUSED (bs ); 690 691const block_q2_K * GGML_RESTRICT x = vx ; 692const block_q8_K * GGML_RESTRICT y = vy ; 693 694const int nb = n /QK_K ; 695 696#if defined__wasm_simd128__ 697float sumf = 0 ; 698 699for (int i = 0 ;i < nb ;++ i ) { 700const uint8_t * q2 = x [i ].qs ; 701const int8_t * q8 = y [i ].qs ; 702const uint8_t * sc = x [i ].scales ; 703 704// Vectorized summs calculation 705v128_t summs_vec = wasm_i32x4_splat (0 ); 706 { 707v128_t sc_vec = wasm_v128_load (sc ); 708v128_t sc_upper = wasm_u8x16_shr (sc_vec ,4 ); 709 710v128_t sc_low = wasm_u16x8_extend_low_u8x16 (sc_upper ); 711v128_t sc_high = wasm_u16x8_extend_high_u8x16 (sc_upper ); 712 713v128_t bsums1 = wasm_v128_load (& y [i ].bsums [0 ]); 714v128_t bsums2 = wasm_v128_load (& y [i ].bsums [8 ]); 715 716summs_vec = wasm_i32x4_add ( 717wasm_i32x4_add (wasm_i32x4_dot_i16x8 (sc_low ,bsums1 ), 718wasm_i32x4_dot_i16x8 (sc_high ,bsums2 )), 719summs_vec 720 ); 721 722summs_vec = wasm_i32x4_add (summs_vec ,wasm_i32x4_shuffle (summs_vec ,summs_vec ,2 ,3 ,0 ,1 )); 723summs_vec = wasm_i32x4_add (summs_vec ,wasm_i32x4_shuffle (summs_vec ,summs_vec ,1 ,0 ,3 ,2 )); 724 } 725int32_t summs = wasm_i32x4_extract_lane (summs_vec ,0 ); 726 727// Vectorized isum calculation 728int32_t isum = 0 ; 729const uint8_t * sc_ptr = sc ; 730const int k_iters = QK_K /128 ; 731 732for (int k = 0 ;k < k_iters ;++ k ) { 733v128_t isum_vec = wasm_i32x4_splat (0 ); 734int shift = 0 ; 735 736for (int j = 0 ;j < 4 ;++ j ) { 737const int d0 = (sc_ptr [0 ]& 0xF ); 738const int d1 = (sc_ptr [1 ]& 0xF ); 739sc_ptr += 2 ; 740 741// Process first 16 elements 742v128_t q2_0 = wasm_v128_load (q2 ); 743v128_t q8_0 = wasm_v128_load (q8 ); 744v128_t q2_shift_0 = wasm_u8x16_shr (q2_0 ,shift ); 745v128_t q2_bits_0 = wasm_v128_and (q2_shift_0 ,wasm_i8x16_splat (0x03 )); 746 747// Process next 16 elements 748v128_t q2_1 = wasm_v128_load (q2 + 16 ); 749v128_t q8_1 = wasm_v128_load (q8 + 16 ); 750v128_t q2_shift_1 = wasm_u8x16_shr (q2_1 ,shift ); 751v128_t q2_bits_1 = wasm_v128_and (q2_shift_1 ,wasm_i8x16_splat (0x03 )); 752 753// Calculate dot products 754v128_t p0 = wasm_i32x4_dot_i16x8 ( 755wasm_i16x8_extend_low_i8x16 (q8_0 ), 756wasm_i16x8_extend_low_i8x16 (q2_bits_0 ) 757 ); 758v128_t p1 = wasm_i32x4_dot_i16x8 ( 759wasm_i16x8_extend_high_i8x16 (q8_0 ), 760wasm_i16x8_extend_high_i8x16 (q2_bits_0 ) 761 ); 762v128_t p2 = wasm_i32x4_dot_i16x8 ( 763wasm_i16x8_extend_low_i8x16 (q8_1 ), 764wasm_i16x8_extend_low_i8x16 (q2_bits_1 ) 765 ); 766v128_t p3 = wasm_i32x4_dot_i16x8 ( 767wasm_i16x8_extend_high_i8x16 (q8_1 ), 768wasm_i16x8_extend_high_i8x16 (q2_bits_1 ) 769 ); 770 771// Accumulate scaled results 772v128_t scaled = wasm_i32x4_add ( 773wasm_i32x4_mul (wasm_i32x4_add (p0 ,p1 ),wasm_i32x4_splat (d0 )), 774wasm_i32x4_mul (wasm_i32x4_add (p2 ,p3 ),wasm_i32x4_splat (d1 )) 775 ); 776 777isum_vec = wasm_i32x4_add (isum_vec ,scaled ); 778q8 += 32 ; 779shift += 2 ; 780 } 781q2 += 32 ; 782 783// Horizontal sum of isum_vec 784isum_vec = wasm_i32x4_add (isum_vec ,wasm_i32x4_shuffle (isum_vec ,isum_vec ,2 ,3 ,0 ,1 )); 785isum_vec = wasm_i32x4_add (isum_vec ,wasm_i32x4_shuffle (isum_vec ,isum_vec ,1 ,0 ,3 ,2 )); 786isum += wasm_i32x4_extract_lane (isum_vec ,0 ); 787 } 788 789const float dall = GGML_CPU_FP16_TO_FP32 (x [i ].d )* y [i ].d ; 790const float dmin = GGML_CPU_FP16_TO_FP32 (x [i ].dmin )* y [i ].d ; 791sumf += dall * isum - dmin * summs ; 792 } 793 794* s = sumf ; 795 796#else 797UNUSED (x ); 798UNUSED (y ); 799UNUSED (nb ); 800ggml_vec_dot_q2_K_q8_K_generic (n ,s ,bs ,vx ,bx ,vy ,by ,nrc ); 801#endif 802} 803 804void ggml_vec_dot_q3_K_q8_K (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,size_t bx ,const void * GGML_RESTRICT vy ,size_t by ,int nrc ) { 805assert (n %QK_K == 0 ); 806assert (nrc == 1 ); 807UNUSED (nrc ); 808UNUSED (bx ); 809UNUSED (by ); 810UNUSED (bs ); 811 812const uint32_t kmask1 = 0x03030303 ; 813const uint32_t kmask2 = 0x0f0f0f0f ; 814 815const block_q3_K * GGML_RESTRICT x = vx ; 816const block_q8_K * GGML_RESTRICT y = vy ; 817 818const int nb = n /QK_K ; 819 820#if defined__wasm_simd128__ 821int8_t aux8 [QK_K ]; 822float sums [8 ]= {0 }; 823uint32_t auxs [4 ]; 824 825float sumf = 0 ; 826for (int i = 0 ;i < nb ;++ i ) { 827const uint8_t * GGML_RESTRICT q3 = x [i ].qs ; 828const uint8_t * GGML_RESTRICT hm = x [i ].hmask ; 829const int8_t * GGML_RESTRICT q8 = y [i ].qs ; 830 831// Process blocks with SIMD 832int8_t * a = aux8 ; 833uint8_t m = 1 ; 834for (int j = 0 ;j < QK_K ;j += 128 ) { 835for (int shift = 0 ;shift <=6 ;shift += 2 ) { 836v128_t v_m = wasm_i8x16_splat (m ); 837for (int l = 0 ;l < 32 ;l += 16 ) { 838v128_t v_q3 = wasm_v128_load (q3 + l ); 839v128_t v_shift = wasm_i8x16_shr (v_q3 ,shift ); 840v128_t v_low2 = wasm_v128_and (v_shift ,wasm_i8x16_splat (0x03 )); 841 842v128_t v_hm = wasm_v128_load (hm + l ); 843v128_t v_mask = wasm_v128_and (v_hm ,v_m ); 844v_mask = wasm_i8x16_ne (v_mask ,wasm_i8x16_splat (0 )); 845 846v_low2 = wasm_i8x16_sub (v_low2 ,wasm_v128_and (wasm_i8x16_splat (4 ),wasm_v128_not (v_mask ))); 847wasm_v128_store (a + l ,v_low2 ); 848 } 849a += 32 ; 850m <<=1 ; 851 } 852q3 += 32 ; 853 } 854 855// Extract scales 856memcpy (auxs ,x [i ].scales ,12 ); 857uint32_t tmp = auxs [2 ]; 858auxs [2 ]= ((auxs [0 ] >>4 )& kmask2 ) | (((tmp >>4 )& kmask1 ) <<4 ); 859auxs [3 ]= ((auxs [1 ] >>4 )& kmask2 ) | (((tmp >>6 )& kmask1 ) <<4 ); 860auxs [0 ]= (auxs [0 ]& kmask2 ) | (((tmp >>0 )& kmask1 ) <<4 ); 861auxs [1 ]= (auxs [1 ]& kmask2 ) | (((tmp >>2 )& kmask1 ) <<4 ); 862const int8_t * scales = (const int8_t * )auxs ; 863 864// SIMD dot product with register accumulators 865v128_t v_acc0 = wasm_i32x4_splat (0 ); 866v128_t v_acc1 = wasm_i32x4_splat (0 ); 867a = aux8 ; 868for (int j = 0 ;j < QK_K /16 ;++ j ) { 869const v128_t v_scale = wasm_i16x8_splat (scales [j ]- 32 ); 870 871// Process 16 elements per iteration 872for (int k = 0 ;k < 2 ;++ k ) { 873const v128_t v_q8 = wasm_i16x8_load8x8 (q8 ); 874const v128_t v_a = wasm_i16x8_load8x8 (a ); 875 876v128_t v_prod = wasm_i16x8_mul (v_q8 ,v_a ); 877v_prod = wasm_i16x8_mul (v_prod ,v_scale ); 878 879v_acc0 = wasm_i32x4_add (v_acc0 ,wasm_i32x4_extend_low_i16x8 (v_prod )); 880v_acc1 = wasm_i32x4_add (v_acc1 ,wasm_i32x4_extend_high_i16x8 (v_prod )); 881 882q8 += 8 ; 883a += 8 ; 884 } 885 } 886 887// Accumulate results 888const float d = GGML_CPU_FP16_TO_FP32 (x [i ].d )* y [i ].d ; 889const v128_t v_d = wasm_f32x4_splat (d ); 890v128_t v_sum = wasm_f32x4_add ( 891wasm_f32x4_mul (wasm_f32x4_convert_i32x4 (v_acc0 ),v_d ), 892wasm_f32x4_mul (wasm_f32x4_convert_i32x4 (v_acc1 ),v_d ) 893 ); 894 895// Accumulate into sums vector 896wasm_v128_store (sums ,wasm_f32x4_add (wasm_v128_load (sums ),v_sum )); 897 } 898 899// Horizontal sum 900v128_t v_sum = wasm_f32x4_add (wasm_v128_load (sums ),wasm_v128_load (sums + 4 )); 901sumf = wasm_f32x4_extract_lane (v_sum ,0 )+ 902wasm_f32x4_extract_lane (v_sum ,1 )+ 903wasm_f32x4_extract_lane (v_sum ,2 )+ 904wasm_f32x4_extract_lane (v_sum ,3 ); 905 906* s = sumf ; 907 908#else 909UNUSED (kmask1 ); 910UNUSED (kmask2 ); 911UNUSED (x ); 912UNUSED (y ); 913UNUSED (nb ); 914ggml_vec_dot_q3_K_q8_K_generic (n ,s ,bs ,vx ,bx ,vy ,by ,nrc ); 915#endif 916 917} 918 919void ggml_vec_dot_q4_K_q8_K (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,size_t bx ,const void * GGML_RESTRICT vy ,size_t by ,int nrc ) { 920assert (n %QK_K == 0 ); 921assert (nrc == 1 ); 922UNUSED (nrc ); 923UNUSED (bx ); 924UNUSED (by ); 925UNUSED (bs ); 926 927const block_q4_K * GGML_RESTRICT x = vx ; 928const block_q8_K * GGML_RESTRICT y = vy ; 929 930const int nb = n /QK_K ; 931 932static const uint32_t kmask1 = 0x3f3f3f3f ; 933static const uint32_t kmask2 = 0x0f0f0f0f ; 934static const uint32_t kmask3 = 0x03030303 ; 935 936uint32_t utmp [4 ]; 937 938#if defined__wasm_simd128__ 939const uint8_t * scales = (const uint8_t * )& utmp [0 ]; 940float sumf = 0 ; 941 942for (int i = 0 ;i < nb ;++ i ) { 943const float d = y [i ].d * GGML_CPU_FP16_TO_FP32 (x [i ].d ); 944const float dmin = y [i ].d * GGML_CPU_FP16_TO_FP32 (x [i ].dmin );// Corrected sign 945 946const uint8_t * GGML_RESTRICT q4 = x [i ].qs ; 947const int8_t * GGML_RESTRICT q8 = y [i ].qs ; 948 949// Process scales and mins 950memcpy (utmp ,x [i ].scales ,12 ); 951utmp [3 ]= ((utmp [2 ] >>4 )& kmask2 ) | (((utmp [1 ] >>6 )& kmask3 ) <<4 ); 952const uint32_t uaux = utmp [1 ]& kmask1 ; 953utmp [1 ]= (utmp [2 ]& kmask2 ) | (((utmp [0 ] >>6 )& kmask3 ) <<4 ); 954utmp [2 ]= uaux ; 955utmp [0 ] &=kmask1 ; 956 957// Sum mins * q8sums 958int32_t sumi = 0 ; 959const int16_t * GGML_RESTRICT q8sums = y [i ].bsums ; 960const uint8_t * m = (const uint8_t * )& utmp [2 ]; 961for (int j = 0 ;j < 16 ;j += 2 ) { 962sumi += (q8sums [j ]+ q8sums [j + 1 ])* m [j /2 ]; 963 } 964sumf -= dmin * sumi ; 965 966int32_t sumi1 = 0 ; 967int32_t sumi2 = 0 ; 968 969for (int j = 0 ;j < QK_K /64 ;++ j ) { 970// Load 64 4-bit weights (32 bytes) 971const v128_t q4x0 = wasm_v128_load (q4 ); 972const v128_t q4x1 = wasm_v128_load (q4 + 16 ); 973q4 += 32 ; 974 975// Split into low/high nibbles 976const v128_t q4l0 = wasm_v128_and (q4x0 ,wasm_i8x16_splat (0x0F )); 977const v128_t q4h0 = wasm_u8x16_shr (q4x0 ,4 ); 978const v128_t q4l1 = wasm_v128_and (q4x1 ,wasm_i8x16_splat (0x0F )); 979const v128_t q4h1 = wasm_u8x16_shr (q4x1 ,4 ); 980 981// Load 64 8-bit values (64 bytes) 982const v128_t q8x0 = wasm_v128_load (q8 ); 983const v128_t q8x1 = wasm_v128_load (q8 + 16 ); 984const v128_t q8x2 = wasm_v128_load (q8 + 32 ); 985const v128_t q8x3 = wasm_v128_load (q8 + 48 ); 986q8 += 64 ; 987 988// Low nibble products 989v128_t vacc1 = wasm_i32x4_dot_i16x8 ( 990wasm_i16x8_extend_low_i8x16 (q4l0 ), 991wasm_i16x8_extend_low_i8x16 (q8x0 ) 992 ); 993vacc1 = wasm_i32x4_add (vacc1 ,wasm_i32x4_dot_i16x8 ( 994wasm_i16x8_extend_high_i8x16 (q4l0 ), 995wasm_i16x8_extend_high_i8x16 (q8x0 ) 996 )); 997vacc1 = wasm_i32x4_add (vacc1 ,wasm_i32x4_dot_i16x8 ( 998wasm_i16x8_extend_low_i8x16 (q4l1 ), 999wasm_i16x8_extend_low_i8x16 (q8x1 ) 1000 )); 1001vacc1 = wasm_i32x4_add (vacc1 ,wasm_i32x4_dot_i16x8 ( 1002wasm_i16x8_extend_high_i8x16 (q4l1 ), 1003wasm_i16x8_extend_high_i8x16 (q8x1 ) 1004 )); 1005 1006// High nibble products 1007v128_t vacc2 = wasm_i32x4_dot_i16x8 ( 1008wasm_i16x8_extend_low_i8x16 (q4h0 ), 1009wasm_i16x8_extend_low_i8x16 (q8x2 ) 1010 ); 1011vacc2 = wasm_i32x4_add (vacc2 ,wasm_i32x4_dot_i16x8 ( 1012wasm_i16x8_extend_high_i8x16 (q4h0 ), 1013wasm_i16x8_extend_high_i8x16 (q8x2 ) 1014 )); 1015vacc2 = wasm_i32x4_add (vacc2 ,wasm_i32x4_dot_i16x8 ( 1016wasm_i16x8_extend_low_i8x16 (q4h1 ), 1017wasm_i16x8_extend_low_i8x16 (q8x3 ) 1018 )); 1019vacc2 = wasm_i32x4_add (vacc2 ,wasm_i32x4_dot_i16x8 ( 1020wasm_i16x8_extend_high_i8x16 (q4h1 ), 1021wasm_i16x8_extend_high_i8x16 (q8x3 ) 1022 )); 1023 1024// Accumulate scaled results 1025int32_t vacc1_sum = wasm_i32x4_extract_lane (vacc1 ,0 )+ wasm_i32x4_extract_lane (vacc1 ,1 )+ 1026wasm_i32x4_extract_lane (vacc1 ,2 )+ wasm_i32x4_extract_lane (vacc1 ,3 ); 1027sumi1 += vacc1_sum * scales [2 * j ]; 1028 1029int32_t vacc2_sum = wasm_i32x4_extract_lane (vacc2 ,0 )+ wasm_i32x4_extract_lane (vacc2 ,1 )+ 1030wasm_i32x4_extract_lane (vacc2 ,2 )+ wasm_i32x4_extract_lane (vacc2 ,3 ); 1031sumi2 += vacc2_sum * scales [2 * j + 1 ]; 1032 } 1033 1034sumf += d * (sumi1 + sumi2 ); 1035 } 1036 1037* s = sumf ; 1038 1039#else 1040UNUSED (x ); 1041UNUSED (y ); 1042UNUSED (nb ); 1043UNUSED (kmask1 ); 1044UNUSED (kmask2 ); 1045UNUSED (kmask3 ); 1046UNUSED (utmp ); 1047ggml_vec_dot_q4_K_q8_K_generic (n ,s ,bs ,vx ,bx ,vy ,by ,nrc ); 1048#endif 1049} 1050 1051void ggml_vec_dot_q5_K_q8_K (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,size_t bx ,const void * GGML_RESTRICT vy ,size_t by ,int nrc ) { 1052assert (n %QK_K == 0 ); 1053assert (nrc == 1 ); 1054UNUSED (nrc ); 1055UNUSED (bx ); 1056UNUSED (by ); 1057UNUSED (bs ); 1058 1059const block_q5_K * GGML_RESTRICT x = vx ; 1060const block_q8_K * GGML_RESTRICT y = vy ; 1061 1062const int nb = n /QK_K ; 1063 1064static const uint32_t kmask1 = 0x3f3f3f3f ; 1065static const uint32_t kmask2 = 0x0f0f0f0f ; 1066static const uint32_t kmask3 = 0x03030303 ; 1067 1068uint32_t utmp [4 ]; 1069 1070#if defined__wasm_simd128__ 1071//const uint8_t * scales = (const uint8_t*)&utmp[0]; 1072float sumf = 0 ; 1073 1074for (int i = 0 ;i < nb ;++ i ) { 1075const float d = y [i ].d * GGML_CPU_FP16_TO_FP32 (x [i ].d ); 1076const float dmin = y [i ].d * GGML_CPU_FP16_TO_FP32 (x [i ].dmin );// Fixed sign 1077 1078const uint8_t * GGML_RESTRICT q5 = x [i ].qs ; 1079const uint8_t * GGML_RESTRICT qh = x [i ].qh ; 1080const int8_t * GGML_RESTRICT q8 = y [i ].qs ; 1081 1082// Process scales and mins 1083memcpy (utmp ,x [i ].scales ,12 ); 1084utmp [3 ]= ((utmp [2 ] >>4 )& kmask2 ) | (((utmp [1 ] >>6 )& kmask3 ) <<4 ); 1085const uint32_t uaux = utmp [1 ]& kmask1 ; 1086utmp [1 ]= (utmp [2 ]& kmask2 ) | (((utmp [0 ] >>6 )& kmask3 ) <<4 ); 1087utmp [2 ]= uaux ; 1088utmp [0 ] &=kmask1 ; 1089 1090// Sum mins * q8sums 1091int32_t sumi_mins = 0 ; 1092const int16_t * GGML_RESTRICT q8sums = y [i ].bsums ; 1093const uint8_t * m = (const uint8_t * )& utmp [2 ]; 1094for (int j = 0 ;j < 16 ;j += 2 ) { 1095sumi_mins += (q8sums [j ]+ q8sums [j + 1 ])* m [j /2 ]; 1096 } 1097sumf -= dmin * sumi_mins ;// Correct subtraction 1098 1099v128_t qh0 = wasm_v128_load (qh ); 1100v128_t qh1 = wasm_v128_load (qh + 16 ); 1101const uint8_t * sc = (const uint8_t * )utmp ; 1102 1103int32_t sumi = 0 ; 1104 1105for (int j = 0 ;j < QK_K /64 ;++ j ) { 1106const int shift = j * 2 ; 1107v128_t qh_shift0 = wasm_u8x16_shr (qh0 ,shift ); 1108v128_t qh_shift1 = wasm_u8x16_shr (qh1 ,shift ); 1109 1110v128_t qh_low0 = wasm_i8x16_shl (wasm_v128_and (qh_shift0 ,wasm_i8x16_splat (0x01 )),4 ); 1111v128_t qh_high0 = wasm_i8x16_shl (wasm_v128_and (qh_shift0 ,wasm_i8x16_splat (0x02 )),3 ); 1112v128_t qh_low1 = wasm_i8x16_shl (wasm_v128_and (qh_shift1 ,wasm_i8x16_splat (0x01 )),4 ); 1113v128_t qh_high1 = wasm_i8x16_shl (wasm_v128_and (qh_shift1 ,wasm_i8x16_splat (0x02 )),3 ); 1114 1115v128_t q5_0 = wasm_v128_load (q5 ); 1116v128_t q5_1 = wasm_v128_load (q5 + 16 ); 1117q5 += 32 ; 1118 1119v128_t q5l_0 = wasm_v128_or (wasm_v128_and (q5_0 ,wasm_i8x16_splat (0x0F )),qh_low0 ); 1120v128_t q5h_0 = wasm_v128_or (wasm_u8x16_shr (q5_0 ,4 ),qh_high0 ); 1121v128_t q5l_1 = wasm_v128_or (wasm_v128_and (q5_1 ,wasm_i8x16_splat (0x0F )),qh_low1 ); 1122v128_t q5h_1 = wasm_v128_or (wasm_u8x16_shr (q5_1 ,4 ),qh_high1 ); 1123 1124v128_t q8_0 = wasm_v128_load (q8 ); 1125v128_t q8_1 = wasm_v128_load (q8 + 16 ); 1126v128_t q8_2 = wasm_v128_load (q8 + 32 ); 1127v128_t q8_3 = wasm_v128_load (q8 + 48 ); 1128q8 += 64 ; 1129 1130// Process low quants 1131v128_t pl0 = wasm_i32x4_dot_i16x8 ( 1132wasm_i16x8_extend_low_i8x16 (q5l_0 ), 1133wasm_i16x8_extend_low_i8x16 (q8_0 ) 1134 ); 1135pl0 = wasm_i32x4_add (pl0 ,wasm_i32x4_dot_i16x8 ( 1136wasm_i16x8_extend_high_i8x16 (q5l_0 ), 1137wasm_i16x8_extend_high_i8x16 (q8_0 ) 1138 )); 1139v128_t pl1 = wasm_i32x4_dot_i16x8 ( 1140wasm_i16x8_extend_low_i8x16 (q5l_1 ), 1141wasm_i16x8_extend_low_i8x16 (q8_1 ) 1142 ); 1143pl1 = wasm_i32x4_add (pl1 ,wasm_i32x4_dot_i16x8 ( 1144wasm_i16x8_extend_high_i8x16 (q5l_1 ), 1145wasm_i16x8_extend_high_i8x16 (q8_1 ) 1146 )); 1147v128_t sum_low = wasm_i32x4_add (pl0 ,pl1 ); 1148 1149// Process high quants 1150v128_t ph0 = wasm_i32x4_dot_i16x8 ( 1151wasm_i16x8_extend_low_i8x16 (q5h_0 ), 1152wasm_i16x8_extend_low_i8x16 (q8_2 ) 1153 ); 1154ph0 = wasm_i32x4_add (ph0 ,wasm_i32x4_dot_i16x8 ( 1155wasm_i16x8_extend_high_i8x16 (q5h_0 ), 1156wasm_i16x8_extend_high_i8x16 (q8_2 ) 1157 )); 1158v128_t ph1 = wasm_i32x4_dot_i16x8 ( 1159wasm_i16x8_extend_low_i8x16 (q5h_1 ), 1160wasm_i16x8_extend_low_i8x16 (q8_3 ) 1161 ); 1162ph1 = wasm_i32x4_add (ph1 ,wasm_i32x4_dot_i16x8 ( 1163wasm_i16x8_extend_high_i8x16 (q5h_1 ), 1164wasm_i16x8_extend_high_i8x16 (q8_3 ) 1165 )); 1166v128_t sum_high = wasm_i32x4_add (ph0 ,ph1 ); 1167 1168// Accumulate with scale factors 1169int32_t sl = wasm_i32x4_extract_lane (sum_low ,0 )+ wasm_i32x4_extract_lane (sum_low ,1 )+ 1170wasm_i32x4_extract_lane (sum_low ,2 )+ wasm_i32x4_extract_lane (sum_low ,3 ); 1171int32_t sh = wasm_i32x4_extract_lane (sum_high ,0 )+ wasm_i32x4_extract_lane (sum_high ,1 )+ 1172wasm_i32x4_extract_lane (sum_high ,2 )+ wasm_i32x4_extract_lane (sum_high ,3 ); 1173 1174sumi += sl * sc [2 * j ]+ sh * sc [2 * j + 1 ]; 1175 } 1176 1177sumf += d * sumi ; 1178 } 1179 1180* s = sumf ; 1181 1182#else 1183UNUSED (x ); 1184UNUSED (y ); 1185UNUSED (nb ); 1186UNUSED (kmask1 ); 1187UNUSED (kmask2 ); 1188UNUSED (kmask3 ); 1189UNUSED (utmp ); 1190ggml_vec_dot_q5_K_q8_K_generic (n ,s ,bs ,vx ,bx ,vy ,by ,nrc ); 1191#endif 1192} 1193 1194void ggml_vec_dot_q6_K_q8_K (int n ,float * GGML_RESTRICT s ,size_t bs ,const void * GGML_RESTRICT vx ,size_t bx ,const void * GGML_RESTRICT vy ,size_t by ,int nrc ) { 1195assert (n %QK_K == 0 ); 1196assert (nrc == 1 ); 1197UNUSED (nrc ); 1198UNUSED (bx ); 1199UNUSED (by ); 1200UNUSED (bs ); 1201 1202const block_q6_K * GGML_RESTRICT x = vx ; 1203const block_q8_K * GGML_RESTRICT y = vy ; 1204 1205const int nb = n /QK_K ; 1206 1207#if defined__wasm_simd128__ 1208int8_t aux8 [QK_K ] __attribute__((aligned (16 ))); 1209int32_t aux32 [8 ] __attribute__((aligned (16 )))= {0 }; 1210float sums [8 ] __attribute__((aligned (16 )))= {0 }; 1211 1212for (int i = 0 ;i < nb ;++ i ) { 1213// Unpack 6-bit quantized data into aux8 (unchanged) 1214const uint8_t * GGML_RESTRICT q4 = x [i ].ql ; 1215const uint8_t * GGML_RESTRICT qh = x [i ].qh ; 1216int8_t * a = aux8 ; 1217for (int j = 0 ;j < QK_K ;j += 128 ) { 1218for (int l = 0 ;l < 32 ;++ l ) { 1219a [l + 0 ]= (int8_t )((q4 [l + 0 ]& 0xF ) | (((qh [l ] >>0 )& 3 ) <<4 ))- 32 ; 1220a [l + 32 ]= (int8_t )((q4 [l + 32 ]& 0xF ) | (((qh [l ] >>2 )& 3 ) <<4 ))- 32 ; 1221a [l + 64 ]= (int8_t )((q4 [l + 0 ] >>4 ) | (((qh [l ] >>4 )& 3 ) <<4 ))- 32 ; 1222a [l + 96 ]= (int8_t )((q4 [l + 32 ] >>4 ) | (((qh [l ] >>6 )& 3 ) <<4 ))- 32 ; 1223 } 1224a += 128 ; 1225q4 += 64 ; 1226qh += 32 ; 1227 } 1228 1229const int8_t * GGML_RESTRICT a_ptr = aux8 ; 1230const int8_t * GGML_RESTRICT q8 = y [i ].qs ; 1231v128_t acc0 = wasm_i32x4_splat (0 ); 1232v128_t acc1 = wasm_i32x4_splat (0 ); 1233 1234for (int j = 0 ;j < QK_K /16 ;++ j ) { 1235const int scale = x [i ].scales [j ]; 1236const v128_t vscale = wasm_i32x4_splat (scale ); 1237 1238// Load 16 elements from a and q8 1239const v128_t a_vec = wasm_v128_load (a_ptr ); 1240const v128_t q8_vec = wasm_v128_load (q8 ); 1241 1242// Process low 8 elements 1243v128_t a_low = wasm_i16x8_extend_low_i8x16 (a_vec ); 1244v128_t q8_low = wasm_i16x8_extend_low_i8x16 (q8_vec ); 1245v128_t prod_low = wasm_i16x8_mul (a_low ,q8_low ); 1246v128_t prod_lo_lo = wasm_i32x4_extend_low_i16x8 (prod_low ); 1247v128_t prod_lo_hi = wasm_i32x4_extend_high_i16x8 (prod_low ); 1248 1249// Process high 8 elements 1250v128_t a_high = wasm_i16x8_extend_high_i8x16 (a_vec ); 1251v128_t q8_high = wasm_i16x8_extend_high_i8x16 (q8_vec ); 1252v128_t prod_high = wasm_i16x8_mul (a_high ,q8_high ); 1253v128_t prod_hi_lo = wasm_i32x4_extend_low_i16x8 (prod_high ); 1254v128_t prod_hi_hi = wasm_i32x4_extend_high_i16x8 (prod_high ); 1255 1256// Scale and accumulate 1257prod_lo_lo = wasm_i32x4_mul (prod_lo_lo ,vscale ); 1258prod_lo_hi = wasm_i32x4_mul (prod_lo_hi ,vscale ); 1259prod_hi_lo = wasm_i32x4_mul (prod_hi_lo ,vscale ); 1260prod_hi_hi = wasm_i32x4_mul (prod_hi_hi ,vscale ); 1261 1262acc0 = wasm_i32x4_add (acc0 ,wasm_i32x4_add (prod_lo_lo ,prod_hi_lo )); 1263acc1 = wasm_i32x4_add (acc1 ,wasm_i32x4_add (prod_lo_hi ,prod_hi_hi )); 1264 1265a_ptr += 16 ; 1266q8 += 16 ; 1267 } 1268 1269// Store accumulated results 1270wasm_v128_store (& aux32 [0 ],acc0 ); 1271wasm_v128_store (& aux32 [4 ],acc1 ); 1272 1273const float d = GGML_CPU_FP16_TO_FP32 (x [i ].d )* y [i ].d ; 1274for (int l = 0 ;l < 8 ;++ l ) { 1275sums [l ]+= d * aux32 [l ]; 1276 } 1277 } 1278 1279// Sum final results 1280float sumf = 0 ; 1281for (int l = 0 ;l < 8 ;++ l ) { 1282sumf += sums [l ]; 1283 } 1284* s = sumf ; 1285 1286#else 1287UNUSED (x ); 1288UNUSED (y ); 1289UNUSED (nb ); 1290ggml_vec_dot_q6_K_q8_K_generic (n ,s ,bs ,vx ,bx ,vy ,by ,nrc ); 1291#endif 1292}