char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
81b0d882a
char/aliceai-t5-moe
1#define GGML_COMMON_IMPL_CPP 2#define GGML_COMMON_DECL_CPP 3 4#include "repack.h" 5 6#include "ggml-common.h" 7#include "ggml-cpu.h" 8#include "ggml-impl.h" 9#include "ime_kernels.h" 10 11#include <algorithm> 12#include <cassert> 13#include <cmath> 14#include <cstring> 15 16// clang-format off 17#if defined(__riscv ) 18 19#if !defined(__riscv_v )|| !defined(__riscv_v_intrinsic ) 20#error "riscv v extension or v_intrinsic not enabled" 21#else 22#include <riscv_vector.h> 23#endif 24 25#if !defined(__riscv_zfh ) 26#error "riscv zfh extension not enabled" 27#endif 28 29#else 30#error "riscv not enabled in this build" 31#endif 32 33#if defined(__GNUC__ ) 34#pragma GCC diagnostic ignored "-Wcast-qual" 35#pragma GCC diagnostic ignored "-Wunused-parameter" 36#endif 37 38// clang-format on 39 40template < int K > constexpr int QK_0 () { 41if constexpr (K == 4 ) { 42return QK4_0 ; 43 } 44if constexpr (K == 8 ) { 45return QK8_0 ; 46 } 47return -1 ; 48} 49 50template < int K ,int N > struct block { 51ggml_half d [N ];// deltas for N qK_0 blocks 52uint8_t qs [(QK_0 < K > ()* N * K ) /8 ];// quants for N qK_0 blocks 53}; 54 55template < int K ,int N > struct block_with_zp { 56ggml_half d [N ];// deltas for N qK_1 blocks 57uint8_t zp [N ];// zero points for N qK_1 blocks 58uint8_t qs [(QK_0 < K > ()* N * K ) /8 ];// quants for N qK_1 blocks 59}; 60 61// control size 62static_assert(sizeof (block < 4 ,16 > )== 16 * sizeof (ggml_half )+ QK4_0 * 8 ,"wrong block<4,16> size/padding" ); 63static_assert(sizeof (block_with_zp < 4 ,16 > )== 16 * sizeof (ggml_half )+ QK4_0 * 8 + 16 * sizeof (uint8_t ), 64"wrong block_with_zp<4,16> size/padding" ); 65 66static_assert(sizeof (block < 8 ,16 > )== 16 * sizeof (ggml_half )+ QK4_0 * 16 ,"wrong block<8,16> size/padding" ); 67 68static_assert(sizeof (block < 4 ,32 > )== 32 * sizeof (ggml_half )+ QK4_0 * 16 ,"wrong block<4,32> size/padding" ); 69static_assert(sizeof (block_with_zp < 4 ,32 > )== 32 * sizeof (ggml_half )+ QK4_0 * 16 + 32 * sizeof (uint8_t ), 70"wrong block_with_zp<4,32> size/padding" ); 71 72using block_q4_0x16 = block < 4 ,16 > ; 73using block_q4_1x16 = block_with_zp < 4 ,16 > ; 74using block_q8_0x16 = block < 8 ,16 > ; 75 76using block_q4_0x32 = block < 4 ,32 > ; 77using block_q4_1x32 = block_with_zp < 4 ,32 > ; 78using block_q8_0x32 = block < 8 ,32 > ; 79 80struct block_q4_0x32x256 { 81block_q4_0x32 blocks [8 ];// [f16 * 32 | i4 * 32 * 32] * 8 82}; 83 84struct block_q4_1x32x256 { 85block_q4_0x32 blocks [8 ]; 86uint8_t zps [32 * 8 ]; 87}; 88 89static block_q4_0x16 make_block_q4_0x16 (block_q4_0 * in ,unsigned int blck_size_interleave ) { 90block_q4_0x16 out ; 91GGML_ASSERT (QK4_0 /blck_size_interleave == 2 ); 92 93for (int i = 0 ;i < 16 ;i ++ ) { 94out .d [i ]= in [i ].d ; 95 } 96 97for (int i = 0 ;i < 16 ;i ++ ) { 98// [0, 15], in.d & 0x0F 99for (int j = 0 ;j < QK4_0 /4 ;j ++ ) { 100//src [b0 b16] ......... [b8 b24] ......... [b15 b31] 101//dst [b0 b8] ......... [b7 b15] 102out .qs [i * QK4_0 /4 + j ]= (in [i ].qs [j ]& 0x0F ) | ((in [i ].qs [j + QK4_0 /4 ]& 0x0F ) <<4 ); 103 } 104 } 105 106for (int i = 0 ;i < 16 ;i ++ ) { 107// [16, 31], in.d & 0xF0 108for (int j = 0 ;j < QK4_0 /4 ;j ++ ) { 109//src [b0 b16] ......... [b8 b24] ......... [b15 b31] 110//dst [b16 b24] ......... [b23 b31] 111out .qs [4 * QK4_0 + i * QK4_0 /4 + j ]= ((in [i ].qs [j ]& 0xF0 ) >>4 ) | (in [i ].qs [j + QK4_0 /4 ]& 0xF0 ); 112 } 113 } 114 115return out ; 116} 117 118static block_q4_1x16 make_block_q4_1x16 (block_q4_1 * in ,unsigned int blck_size_interleave ) { 119block_q4_1x16 out ; 120GGML_ASSERT (QK4_1 /blck_size_interleave == 2 ); 121 122for (int i = 0 ;i < 16 ;i ++ ) { 123float d = GGML_FP16_TO_FP32 (in [i ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .d ); 124float m = GGML_FP16_TO_FP32 (in [i ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .m ); 125float mid = - std::nearbyintf (m /d ); 126mid = std::min (15.0f , std::max (0.0f ,mid )); 127out .d [i ]= GGML_FP32_TO_FP16 (d ); 128out .zp [i ]= static_cast < uint8_t > (mid ); 129 } 130 131for (int i = 0 ;i < 16 ;i ++ ) { 132// [0, 15], in.d & 0x0F 133for (int j = 0 ;j < QK4_1 /4 ;j ++ ) { 134//src [b0 b16] ......... [b8 b24] ......... [b15 b31] 135//dst [b0 b8] ......... [b7 b15] 136out .qs [i * QK4_1 /4 + j ]= (in [i ].qs [j ]& 0x0F ) | ((in [i ].qs [j + QK4_1 /4 ]& 0x0F ) <<4 ); 137 } 138 } 139 140for (int i = 0 ;i < 16 ;i ++ ) { 141// [16, 31], in.d & 0xF0 142for (int j = 0 ;j < QK4_1 /4 ;j ++ ) { 143//src [b0 b16] ......... [b8 b24] ......... [b15 b31] 144//dst [b16 b24] ......... [b23 b31] 145out .qs [4 * QK4_1 + i * QK4_1 /4 + j ]= ((in [i ].qs [j ]& 0xF0 ) >>4 ) | (in [i ].qs [j + QK4_1 /4 ]& 0xF0 ); 146 } 147 } 148 149return out ; 150} 151 152static int repack_q4_0_to_q4_0_16_bl (ggml_tensor * t , 153int interleave_block , 154const void * GGML_RESTRICT data , 155size_t data_size ) { 156GGML_ASSERT (t -> type == GGML_TYPE_Q4_0 ); 157GGML_ASSERT (interleave_block == 16 ); 158 159constexpr int nrows_interleaved = 16 ; 160 161block_q4_0x16 * dst = (block_q4_0x16 * )t -> data ; 162const block_q4_0 * src = (const block_q4_0 * )data ; 163block_q4_0 dst_tmp [16 ]; 164int nrow = ggml_nrows (t ); 165int nblocks = t -> ne [0 ] /QK4_0 ; 166 167GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q4_0 )); 168 169if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK4_0 != 0 ) { 170return -1 ; 171 } 172 173for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 174for (int64_t x = 0 ;x < nblocks ;x ++ ) { 175for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 176dst_tmp [i ]= src [x + i * nblocks ]; 177 } 178* dst ++ = make_block_q4_0x16 (dst_tmp ,interleave_block ); 179 } 180src += nrows_interleaved * nblocks ; 181 } 182return 0 ; 183 184GGML_UNUSED (data_size ); 185} 186 187static int repack_q4_1_to_q4_1_16_bl (ggml_tensor * t , 188int interleave_block , 189const void * GGML_RESTRICT data , 190size_t data_size ) { 191GGML_ASSERT (t -> type == GGML_TYPE_Q4_1 ); 192GGML_ASSERT (interleave_block == 16 ); 193 194constexpr int nrows_interleaved = 16 ; 195 196block_q4_1x16 * dst = (block_q4_1x16 * )t -> data ; 197const block_q4_1 * src = (const block_q4_1 * )data ; 198block_q4_1 dst_tmp [16 ]; 199int nrow = ggml_nrows (t ); 200int nblocks = t -> ne [0 ] /QK4_1 ; 201 202GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q4_1 )); 203 204if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK4_1 != 0 ) { 205return -1 ; 206 } 207 208for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 209for (int64_t x = 0 ;x < nblocks ;x ++ ) { 210for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 211dst_tmp [i ]= src [x + i * nblocks ]; 212 } 213* dst ++ = make_block_q4_1x16 (dst_tmp ,interleave_block ); 214 } 215src += nrows_interleaved * nblocks ; 216 } 217return 0 ; 218 219GGML_UNUSED (data_size ); 220} 221 222static inline void get_scale_min_k4 (int j , 223const uint8_t * GGML_RESTRICT q , 224uint8_t * GGML_RESTRICT d , 225uint8_t * GGML_RESTRICT m ) { 226if (j < 4 ) { 227* d = q [j ]& 63 ; 228* m = q [j + 4 ]& 63 ; 229 }else { 230* d = (q [j + 4 ]& 0xF ) | ((q [j - 4 ] >>6 ) <<4 ); 231* m = (q [j + 4 ] >>4 ) | ((q [j - 0 ] >>6 ) <<4 ); 232 } 233} 234 235static int repack_q4_k_to_q4_1_16_bl (ggml_tensor * t , 236int interleave_block , 237const void * GGML_RESTRICT data , 238size_t data_size ) { 239GGML_ASSERT (t -> type == GGML_TYPE_Q4_K ); 240GGML_ASSERT (interleave_block == 16 ); 241GGML_ASSERT (QK_K /QK4_1 == 8 ); 242 243constexpr int nrows_interleaved = 16 ; 244 245block_q4_1x16 * dst = (block_q4_1x16 * )t -> data ; 246const block_q4_K * src = (const block_q4_K * )data ; 247block_q4_1 dst_tmp [16 ]; 248int nrow = ggml_nrows (t ); 249int nblocks = t -> ne [0 ] /QK_K ; 250 251if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK_K != 0 ) { 252return -1 ; 253 } 254 255for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 256for (int64_t x = 0 ;x < nblocks ;x ++ ) { 257for (int j = 0 ;j < 8 ;j ++ ) { 258for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 259uint8_t sc ,m ; 260const float d = GGML_FP16_TO_FP32 (src [x + i * nblocks ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .d ); 261const float min = 262GGML_FP16_TO_FP32 (src [x + i * nblocks ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .dmin ); 263get_scale_min_k4 (j ,src [x + i * nblocks ].scales ,& sc ,& m ); 264const float d1 = d * sc ; 265const float m1 = min * m ; 266 267dst_tmp [i ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .d = GGML_FP32_TO_FP16 (d1 ); 268dst_tmp [i ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .m = GGML_FP32_TO_FP16 (- m1 ); 269// src -> [b0, b32] [b1, b33] ... [b31, b63] 270// dst -> [b0, b16] [b1, b17] ... [b15, b31] [b32, b48] [b33, b49] ... [b47, b63] 271const uint8_t * q = src [x + i * nblocks ].qs + (j /2 )* QK4_1 ; 272if (j %2 == 0 ) { 273for (int ii = 0 ;ii < 16 ;ii ++ ) { 274dst_tmp [i ].qs [ii ]= (q [ii ]& 0x0F ) | ((q [ii + 16 ]& 0x0F ) <<4 ); 275 } 276 }else { 277for (int ii = 0 ;ii < 16 ;ii ++ ) { 278dst_tmp [i ].qs [ii ]= ((q [ii ]& 0xF0 ) >>4 ) | (q [ii + 16 ]& 0xF0 ); 279 } 280 } 281 } 282* dst ++ = make_block_q4_1x16 (dst_tmp ,interleave_block ); 283 } 284 } 285src += nrows_interleaved * nblocks ; 286 } 287return 0 ; 288 289GGML_UNUSED (data_size ); 290} 291 292static block_q4_0x32 make_block_q4_0x32 (block_q4_0 * in ,unsigned int blck_size_interleave ) { 293block_q4_0x32 out ; 294assert (QK4_0 /blck_size_interleave == 1 ); 295GGML_UNUSED (blck_size_interleave ); 296 297for (int i = 0 ;i < 32 ;i ++ ) { 298out .d [i ]= in [i ].d ; 299 } 300 301for (int i = 0 ;i < 32 ;i ++ ) { 302// [0, 15], in.d & 0x0F 303for (int j = 0 ;j < QK4_0 /4 ;j ++ ) { 304//src [b0 b16] ......... [b8 b24] ......... [b15 b31] 305//dst [b0 b1] ......... [b14 b15] 306out .qs [i * QK4_0 /2 + j ]= (in [i ].qs [j * 2 ]& 0x0F ) | ((in [i ].qs [j * 2 + 1 ]& 0x0F ) <<4 ); 307 } 308 } 309 310for (int i = 0 ;i < 32 ;i ++ ) { 311// [16, 31], in.d & 0xF0 312for (int j = 0 ;j < QK4_0 /4 ;j ++ ) { 313//src [b0 b16] ......... [b8 b24] ......... [b15 b31] 314//dst [b16 b17] ......... [b30 b31] 315out .qs [i * QK4_0 /2 + QK4_0 /4 + j ]= ((in [i ].qs [j * 2 ]& 0xF0 ) >>4 ) | (in [i ].qs [j * 2 + 1 ]& 0xF0 ); 316 } 317 } 318 319return out ; 320} 321 322static block_q4_1x32 make_block_q4_1x32 (block_q4_1 * in ,unsigned int blck_size_interleave ) { 323block_q4_1x32 out ; 324GGML_ASSERT (QK4_1 /blck_size_interleave == 1 ); 325GGML_UNUSED (blck_size_interleave ); 326 327for (int i = 0 ;i < 32 ;i ++ ) { 328float d = GGML_FP16_TO_FP32 (in [i ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .d ); 329float m = GGML_FP16_TO_FP32 (in [i ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .m ); 330float mid = - std::nearbyintf (m /d ); 331mid = std::min (15.0f , std::max (0.0f ,mid )); 332out .d [i ]= GGML_FP32_TO_FP16 (d ); 333out .zp [i ]= static_cast < uint8_t > (mid ); 334 } 335 336for (int i = 0 ;i < 32 ;i ++ ) { 337// [0, 15], in.d & 0x0F 338for (int j = 0 ;j < QK4_1 /4 ;j ++ ) { 339//src [b0 b16] ......... [b8 b24] ......... [b15 b31] 340//dst [b0 b1] ......... [b14 b15] 341out .qs [i * QK4_1 /2 + j ]= (in [i ].qs [j * 2 ]& 0x0F ) | ((in [i ].qs [j * 2 + 1 ]& 0x0F ) <<4 ); 342 } 343 } 344 345for (int i = 0 ;i < 32 ;i ++ ) { 346// [16, 31], in.d & 0xF0 347for (int j = 0 ;j < QK4_1 /4 ;j ++ ) { 348//src [b0 b16] ......... [b8 b24] ......... [b15 b31] 349//dst [b16 b24] ......... [b23 b31] 350out .qs [i * QK4_1 /2 + QK4_1 /4 + j ]= ((in [i ].qs [j * 2 ]& 0xF0 ) >>4 ) | (in [i ].qs [j * 2 + 1 ]& 0xF0 ); 351 } 352 } 353 354return out ; 355} 356 357static block_q8_0x32 make_block_q8_0x32 (block_q8_0 * in ,unsigned int blck_size_interleave ) { 358block_q8_0x32 out ; 359GGML_ASSERT (QK8_0 /blck_size_interleave == 1 ); 360GGML_UNUSED (blck_size_interleave ); 361 362for (int i = 0 ;i < 32 ;i ++ ) { 363out .d [i ]= in [i ].d ; 364 } 365 366for (int i = 0 ;i < 32 ;i ++ ) { 367memcpy (out .qs + i * QK8_0 ,in [i ].qs ,QK8_0 ); 368 } 369 370return out ; 371} 372 373static int repack_q2_k_to_q2_k_32_bl (ggml_tensor * t , 374int interleave_block , 375const void * GGML_RESTRICT data , 376size_t data_size ) { 377GGML_ASSERT (t -> type == GGML_TYPE_Q2_K ); 378GGML_ASSERT (interleave_block == 32 ); 379GGML_ASSERT (QK_K == 256 ); 380 381constexpr int nrows_interleaved = 32 ; 382 383const block_q2_K * src = (const block_q2_K * )data ; 384 385auto * dst = (spacemit_kernels::nrow_block_q2_k < 32 > * )t -> data ; 386 387int nrow = ggml_nrows (t ); 388int nblocks = t -> ne [0 ] /QK_K ; 389 390GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q2_K )); 391 392if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK_K != 0 ) { 393return -1 ; 394 } 395 396uint8_t qs_aux [256 ]= {0 }; 397for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 398for (int64_t x = 0 ;x < nblocks ;x ++ ) { 399for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 400const block_q2_K * src_block = & src [(b + i )* nblocks + x ]; 401 402// scale for [16, N] 403for (int j = 0 ;j < 16 ;j ++ ) { 404auto zp_aux = (dst -> scales [j * nrows_interleaved + i ])& 0xF0 ; 405 406dst -> scales [j * nrows_interleaved + i ]= (src_block -> scales [j ]& 0x0F ) |zp_aux ; 407 } 408 409// zp for [N, 16] 410for (int j = 0 ;j < 16 ;j ++ ) { 411auto scale_aux = (dst -> scales [16 * i + j ])& 0x0F ; 412 413dst -> scales [16 * i + j ]= (src_block -> scales [j ]& 0xF0 ) |scale_aux ; 414 } 415 416for (int k = 0 ;k < 4 ;k ++ ) { 417for (int j = 0 ;j < 32 ;j ++ ) { 418qs_aux [k * 32 + j ]= (src_block -> qs [j ] >> (2 * k ))& 0x03 ; 419 } 420 } 421 422for (int k = 0 ;k < 4 ;k ++ ) { 423for (int j = 0 ;j < 32 ;j ++ ) { 424qs_aux [k * 32 + j + 128 ]= (src_block -> qs [j + 32 ] >> (2 * k ))& 0x03 ; 425 } 426 } 427 428// from nrows_interleaved * [2 * 32byte] 429// to 4 * [nrows_interleaved * 16byte] 430for (int k = 0 ;k < 4 ;k ++ ) { 431for (int j = 0 ;j < 16 ;j ++ ) { 432uint8_t qs0 = qs_aux [j + k * 64 ]; 433uint8_t qs16 = qs_aux [j + 16 + k * 64 ]; 434uint8_t qs32 = qs_aux [j + 32 + k * 64 ]; 435uint8_t qs48 = qs_aux [j + 48 + k * 64 ]; 436 437dst -> qs [(k * nrows_interleaved + i )* 16 + j ]= 438 (qs0 & 0x03 ) | ((qs16 & 0x03 ) <<2 ) | ((qs32 & 0x03 ) <<4 ) | ((qs48 & 0x03 ) <<6 ); 439 } 440 } 441 442dst -> scales16 [i ]= src_block -> GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .d ; 443dst -> zeros16 [i ]= src_block -> GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .dmin ; 444 } 445dst ++ ; 446 } 447 } 448 449return 0 ; 450} 451 452static int repack_q3_k_to_q3_k_32_bl (ggml_tensor * t , 453int interleave_block , 454const void * GGML_RESTRICT data , 455size_t data_size ) { 456GGML_ASSERT (t -> type == GGML_TYPE_Q3_K ); 457GGML_ASSERT (interleave_block == 32 ); 458GGML_ASSERT (QK_K == 256 ); 459 460constexpr int nrows_interleaved = 32 ; 461 462const uint32_t kmask1 = 0x03030303 ; 463const uint32_t kmask2 = 0x0f0f0f0f ; 464 465const block_q3_K * src = (const block_q3_K * )data ; 466 467auto * dst = (spacemit_kernels::nrow_block_q3_k < 32 > * )t -> data ; 468 469int nrow = ggml_nrows (t ); 470int nblocks = t -> ne [0 ] /QK_K ; 471 472GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q3_K )); 473 474if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK_K != 0 ) { 475return -1 ; 476 } 477 478uint32_t b_scale_aux [4 ]= {0 }; 479uint8_t qs_aux [256 ]= {0 }; 480 481for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 482for (int64_t x = 0 ;x < nblocks ;x ++ ) { 483for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 484const block_q3_K * src_block = & src [(b + i )* nblocks + x ]; 485 486uint32_t * auxs = b_scale_aux ; 487int8_t * scale = (int8_t * )auxs ; 488memcpy (auxs ,src_block -> scales ,12 ); 489 490uint32_t tmp = auxs [2 ]; 491auxs [2 ]= ((auxs [0 ] >>4 )& kmask2 ) | (((tmp >>4 )& kmask1 ) <<4 ); 492auxs [3 ]= ((auxs [1 ] >>4 )& kmask2 ) | (((tmp >>6 )& kmask1 ) <<4 ); 493auxs [0 ]= (auxs [0 ]& kmask2 ) | (((tmp >>0 )& kmask1 ) <<4 ); 494auxs [1 ]= (auxs [1 ]& kmask2 ) | (((tmp >>2 )& kmask1 ) <<4 ); 495 496for (int j = 0 ;j < 16 ;j ++ ) { 497dst -> scales [j * nrows_interleaved + i ]= scale [j ]- 32 ; 498 } 499 500for (int k = 0 ;k < 4 ;k ++ ) { 501for (int j = 0 ;j < 32 ;j ++ ) { 502qs_aux [k * 32 + j ]= (src_block -> qs [j ] >> (2 * k ))& 0x03 ; 503 } 504 } 505 506for (int k = 0 ;k < 4 ;k ++ ) { 507for (int j = 0 ;j < 32 ;j ++ ) { 508qs_aux [k * 32 + j + 128 ]= (src_block -> qs [j + 32 ] >> (2 * k ))& 0x03 ; 509 } 510 } 511 512// from nrows_interleaved * [2 * 32byte] 513// to 4 * [nrows_interleaved * 16byte] 514for (int k = 0 ;k < 4 ;k ++ ) { 515for (int j = 0 ;j < 16 ;j ++ ) { 516uint8_t qs0 = qs_aux [j + k * 64 ]; 517uint8_t qs16 = qs_aux [j + 16 + k * 64 ]; 518uint8_t qs32 = qs_aux [j + 32 + k * 64 ]; 519uint8_t qs48 = qs_aux [j + 48 + k * 64 ]; 520 521dst -> qs [(k * nrows_interleaved + i )* 16 + j ]= 522 (qs0 & 0x03 ) | ((qs16 & 0x03 ) <<2 ) | ((qs32 & 0x03 ) <<4 ) | ((qs48 & 0x03 ) <<6 ); 523 } 524 } 525 526//memcpy(dst->hmask + i * 32, src_block->hmask, 32); 527 528// from nrows_interleaved * [32byte] 529// to 16 * [nrows_interleaved * uint16_t] 530uint16_t * dst_mask = ((uint16_t * )dst -> hmask )+ i ; 531for (int j = 0 ;j < 16 ;j ++ ,dst_mask += nrows_interleaved ) { 532uint8_t b_shift = j /2 ; 533uint8_t * b_mask_col = (uint8_t * ) (src_block -> hmask + (j %2 )* 16 ); 534// b0 - b15 535uint16_t msk_out_0 = 0 ; 536 537for (int k = 0 ;k < 8 ;k ++ ) { 538msk_out_0 |= (uint16_t ) ((b_mask_col [k ] >>b_shift )& 0x01 ) <<k ; 539 } 540for (int k = 8 ;k < 16 ;k ++ ) { 541msk_out_0 |= (uint16_t ) ((b_mask_col [k ] >>b_shift )& 0x01 ) <<k ; 542 } 543 544dst_mask [0 ]= msk_out_0 ; 545 } 546 547dst -> scales16 [i ]= src_block -> d ; 548 } 549 550dst ++ ; 551 } 552 } 553 554return 0 ; 555} 556 557static int repack_q4_0_to_q4_0_32_bl_ref (ggml_tensor * t , 558int interleave_block , 559const void * GGML_RESTRICT data , 560size_t data_size ) { 561GGML_ASSERT (t -> type == GGML_TYPE_Q4_0 ); 562GGML_ASSERT (interleave_block == 32 );// unused 563 564constexpr int nrows_interleaved = 32 ; 565 566block_q4_0x32 * dst = (block_q4_0x32 * )t -> data ; 567const block_q4_0 * src = (const block_q4_0 * )data ; 568block_q4_0 dst_tmp [32 ]; 569int nrow = ggml_nrows (t ); 570int nblocks = t -> ne [0 ] /QK4_0 ; 571 572GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q4_0 )); 573 574if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK4_0 != 0 ) { 575return -1 ; 576 } 577 578for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 579for (int64_t x = 0 ;x < nblocks ;x ++ ) { 580for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 581dst_tmp [i ]= src [x + i * nblocks ]; 582 } 583* dst ++ = make_block_q4_0x32 (dst_tmp ,interleave_block ); 584 } 585src += nrows_interleaved * nblocks ; 586 } 587return 0 ; 588 589GGML_UNUSED (data_size ); 590} 591 592static int repack_q4_0_to_q4_0_256_32_bl_ref (ggml_tensor * t , 593int interleave_block , 594const void * GGML_RESTRICT data , 595size_t data_size ) { 596GGML_ASSERT (t -> type == GGML_TYPE_Q4_0 ); 597GGML_ASSERT (interleave_block == 32 );// unused 598 599constexpr int nrows_interleaved = 32 ; 600 601block_q4_0x32x256 * dst = (block_q4_0x32x256 * )t -> data ; 602const block_q4_0 * src = (const block_q4_0 * )data ; 603block_q4_0 dst_tmp [32 ]; 604int nrow = ggml_nrows (t ); 605int nblocks = t -> ne [0 ] /QK4_0 ; 606 607GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q4_0 )); 608GGML_ASSERT (nblocks %8 == 0 );// for 256-block interleaving 609if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK4_0 != 0 ) { 610return -1 ; 611 } 612 613for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 614for (int64_t x = 0 ;x < nblocks ;x += 8 ) { 615for (int j = 0 ;j < 8 ;j ++ ) { 616for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 617dst_tmp [i ]= src [x + j + i * nblocks ]; 618 } 619dst -> blocks [j ]= make_block_q4_0x32 (dst_tmp ,interleave_block ); 620 } 621dst ++ ; 622 } 623src += nrows_interleaved * nblocks ; 624 } 625return 0 ; 626 627GGML_UNUSED (data_size ); 628} 629 630static int repack_q4_0_to_q4_1_256_32_bl_ref (ggml_tensor * t , 631int interleave_block , 632const void * GGML_RESTRICT data , 633size_t data_size ) { 634GGML_ASSERT (t -> type == GGML_TYPE_Q4_1 ); 635GGML_ASSERT (interleave_block == 32 );// unused 636 637constexpr int nrows_interleaved = 32 ; 638 639block_q4_1x32x256 * dst = (block_q4_1x32x256 * )t -> data ; 640const block_q4_1 * src = (const block_q4_1 * )data ; 641block_q4_1 dst_tmp [32 ]; 642int nrow = ggml_nrows (t ); 643int nblocks = t -> ne [0 ] /QK4_0 ; 644 645GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q4_1 )); 646GGML_ASSERT (nblocks %8 == 0 );// for 256-block interleaving 647if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK4_0 != 0 ) { 648return -1 ; 649 } 650 651for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 652for (int64_t x = 0 ;x < nblocks ;x += 8 ) { 653for (int j = 0 ;j < 8 ;j ++ ) { 654for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 655dst_tmp [i ]= src [x + j + i * nblocks ]; 656 } 657 658block_q4_0x32 * dst_block = & dst -> blocks [j ]; 659uint8_t * dst_zp = dst -> zps + j * nrows_interleaved ; 660 661for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 662float d = GGML_FP16_TO_FP32 (dst_tmp [i ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .d ); 663float m = GGML_FP16_TO_FP32 (dst_tmp [i ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .m ); 664float mid = - std::nearbyintf (m /d ); 665mid = std::min (15.0f , std::max (0.0f ,mid )); 666 667dst_block -> d [i ]= GGML_FP32_TO_FP16 (d ); 668dst_zp [i ]= static_cast < uint8_t > (mid ); 669 } 670 671for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 672for (int k = 0 ;k < QK4_1 /4 ;k ++ ) { 673dst_block -> qs [i * QK4_1 /2 + k ]= 674 (dst_tmp [i ].qs [k * 2 ]& 0x0F ) | ((dst_tmp [i ].qs [k * 2 + 1 ]& 0x0F ) <<4 ); 675 } 676 } 677 678for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 679for (int k = 0 ;k < QK4_1 /4 ;k ++ ) { 680dst_block -> qs [i * QK4_1 /2 + QK4_1 /4 + k ]= 681 ((dst_tmp [i ].qs [k * 2 ]& 0xF0 ) >>4 ) | (dst_tmp [i ].qs [k * 2 + 1 ]& 0xF0 ); 682 } 683 } 684 } 685dst ++ ; 686 } 687src += nrows_interleaved * nblocks ; 688 } 689return 0 ; 690 691GGML_UNUSED (data_size ); 692} 693 694// RVV optimized version of repack_q4_0_to_q4_0_32_bl 695// Eliminates the intermediate dst_tmp buffer and vectorizes nibble repack. 696static int repack_q4_0_to_q4_0_32_bl (ggml_tensor * t , 697int interleave_block , 698const void * GGML_RESTRICT data , 699size_t data_size ) { 700GGML_ASSERT (t -> type == GGML_TYPE_Q4_0 ); 701GGML_ASSERT (interleave_block == 32 ); 702 703constexpr int nrows_interleaved = 32 ; 704constexpr int qs_bytes = QK4_0 /2 ;// 16 705 706block_q4_0x32 * dst = (block_q4_0x32 * )t -> data ; 707const block_q4_0 * src = (const block_q4_0 * )data ; 708int nrow = ggml_nrows (t ); 709int nblocks = t -> ne [0 ] /QK4_0 ; 710 711GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q4_0 )); 712 713if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK4_0 != 0 ) { 714return -1 ; 715 } 716 717const ptrdiff_t row_stride = (ptrdiff_t )nblocks * sizeof (block_q4_0 ); 718 719for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 720for (int64_t x = 0 ;x < nblocks ;x ++ ) { 721const block_q4_0 * col_src = src + x ; 722 723// --- 1) Gather 32 scale values (ggml_half d) with stride load --- 724// d is at offset 0 of each block_q4_0, stride between rows = row_stride 725 { 726const uint8_t * d_base = (const uint8_t * )& col_src -> d ; 727ggml_half * d_dst = dst -> d ; 728size_t remaining = 32 ; 729size_t offset = 0 ; 730while (remaining > 0 ) { 731size_t vl = __riscv_vsetvl_e16m1 (remaining ); 732vuint16m1_t vd = 733__riscv_vlse16_v_u16m1 ((const uint16_t * ) (d_base + offset * row_stride ),row_stride ,vl ); 734__riscv_vse16_v_u16m1 ((uint16_t * ) (d_dst + offset ),vd ,vl ); 735offset += vl ; 736remaining -= vl ; 737 } 738 } 739 740// --- 2) Nibble repack qs for each of the 32 rows --- 741// For each row i: 742// src qs[16]: [b0|b16] [b1|b17] ... [b15|b31] (lo nibble = b_j, hi nibble = b_{j+16}) 743// dst qs low 8B: (qs[2j] & 0x0F) | ((qs[2j+1] & 0x0F) << 4) for j=0..7 744// dst qs high 8B: ((qs[2j] >> 4)) | (qs[2j+1] & 0xF0) for j=0..7 745 { 746const size_t vl8 = __riscv_vsetvl_e8m1 (8 ); 747for (int i = 0 ;i < 32 ;i ++ ) { 748const uint8_t * sq = col_src [i * nblocks ].qs ; 749uint8_t * dq = dst -> qs + i * qs_bytes ; 750 751// stride-2 load to separate even/odd bytes 752vuint8m1_t v_even = __riscv_vlse8_v_u8m1 (sq ,2 ,vl8 );// qs[0], qs[2], ..., qs[14] 753vuint8m1_t v_odd = __riscv_vlse8_v_u8m1 (sq + 1 ,2 ,vl8 );// qs[1], qs[3], ..., qs[15] 754 755// low nibble part: (even & 0x0F) | ((odd & 0x0F) << 4) 756vuint8m1_t v_even_lo = __riscv_vand_vx_u8m1 (v_even ,0x0F ,vl8 ); 757vuint8m1_t v_odd_lo = __riscv_vand_vx_u8m1 (v_odd ,0x0F ,vl8 ); 758vuint8m1_t v_lo = __riscv_vor_vv_u8m1 (v_even_lo ,__riscv_vsll_vx_u8m1 (v_odd_lo ,4 ,vl8 ),vl8 ); 759 760// high nibble part: (even >> 4) | (odd & 0xF0) 761vuint8m1_t v_even_hi = __riscv_vsrl_vx_u8m1 (v_even ,4 ,vl8 ); 762vuint8m1_t v_odd_hi = __riscv_vand_vx_u8m1 (v_odd ,0xF0 ,vl8 ); 763vuint8m1_t v_hi = __riscv_vor_vv_u8m1 (v_even_hi ,v_odd_hi ,vl8 ); 764 765__riscv_vse8_v_u8m1 (dq ,v_lo ,vl8 ); 766__riscv_vse8_v_u8m1 (dq + 8 ,v_hi ,vl8 ); 767 } 768 } 769 770dst ++ ; 771 } 772src += nrows_interleaved * nblocks ; 773 } 774return 0 ; 775 776GGML_UNUSED (data_size ); 777} 778 779static int repack_q4_1_to_q4_1_32_bl_ref (ggml_tensor * t , 780int interleave_block , 781const void * GGML_RESTRICT data , 782size_t data_size ) { 783GGML_ASSERT (t -> type == GGML_TYPE_Q4_1 ); 784GGML_ASSERT (interleave_block == 32 );// unused 785 786constexpr int nrows_interleaved = 32 ; 787 788block_q4_1x32 * dst = (block_q4_1x32 * )t -> data ; 789const block_q4_1 * src = (const block_q4_1 * )data ; 790block_q4_1 dst_tmp [32 ]; 791int nrow = ggml_nrows (t ); 792int nblocks = t -> ne [0 ] /QK4_1 ; 793 794GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q4_1 )); 795 796if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK4_1 != 0 ) { 797return -1 ; 798 } 799 800for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 801for (int64_t x = 0 ;x < nblocks ;x ++ ) { 802for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 803dst_tmp [i ]= src [x + i * nblocks ]; 804 } 805* dst ++ = make_block_q4_1x32 (dst_tmp ,interleave_block ); 806 } 807src += nrows_interleaved * nblocks ; 808 } 809return 0 ; 810 811GGML_UNUSED (data_size ); 812} 813 814// RVV optimized version of repack_q4_1_to_q4_1_32_bl 815// Eliminates the intermediate dst_tmp buffer and vectorizes nibble repack + zp computation. 816static int repack_q4_1_to_q4_1_32_bl (ggml_tensor * t , 817int interleave_block , 818const void * GGML_RESTRICT data , 819size_t data_size ) { 820GGML_ASSERT (t -> type == GGML_TYPE_Q4_1 ); 821GGML_ASSERT (interleave_block == 32 ); 822 823constexpr int nrows_interleaved = 32 ; 824constexpr int qs_bytes = QK4_1 /2 ;// 16 825 826block_q4_1x32 * dst = (block_q4_1x32 * )t -> data ; 827const block_q4_1 * src = (const block_q4_1 * )data ; 828int nrow = ggml_nrows (t ); 829int nblocks = t -> ne [0 ] /QK4_1 ; 830 831GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q4_1 )); 832 833if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK4_1 != 0 ) { 834return -1 ; 835 } 836 837const ptrdiff_t row_stride = (ptrdiff_t )nblocks * sizeof (block_q4_1 ); 838 839for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 840for (int64_t x = 0 ;x < nblocks ;x ++ ) { 841const block_q4_1 * col_src = src + x ; 842 843// --- 1) Gather d and m, compute zp = clamp(nearbyint(-m/d), 0, 15) --- 844// block_q4_1 layout: [d(f16), m(f16), qs[16]] 845// d is at byte offset 0, m is at byte offset 2 from each block start 846 { 847const uint8_t * dm_base = (const uint8_t * )& col_src -> GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .d ; 848ggml_half * d_dst = dst -> d ; 849uint8_t * zp_dst = dst -> zp ; 850size_t remaining = 32 ; 851size_t offset = 0 ; 852while (remaining > 0 ) { 853size_t vl = __riscv_vsetvl_e16m1 (remaining ); 854 855// stride load d (f16) from each row 856vuint16m1_t vd_raw = 857__riscv_vlse16_v_u16m1 ((const uint16_t * ) (dm_base + offset * row_stride ),row_stride ,vl ); 858__riscv_vse16_v_u16m1 ((uint16_t * ) (d_dst + offset ),vd_raw ,vl ); 859 860// stride load m (f16) from each row (offset +2 bytes from d) 861vuint16m1_t vm_raw = 862__riscv_vlse16_v_u16m1 ((const uint16_t * ) (dm_base + 2 + offset * row_stride ),row_stride ,vl ); 863 864// convert to f32 for zp computation: zp = nearbyint(-m / d) 865vfloat16m1_t vd_f16 = __riscv_vreinterpret_v_u16m1_f16m1 (vd_raw ); 866vfloat16m1_t vm_f16 = __riscv_vreinterpret_v_u16m1_f16m1 (vm_raw ); 867 868// -m / d in f16 directly (SpaceMIT X60 supports f16 arithmetic) 869vfloat16m1_t v_neg_m = __riscv_vfneg_v_f16m1 (vm_f16 ,vl ); 870vfloat16m1_t v_ratio = __riscv_vfdiv_vv_f16m1 (v_neg_m ,vd_f16 ,vl ); 871 872// Convert to f32 for nearbyint, then clamp 873vfloat32m2_t v_ratio_f32 = __riscv_vfwcvt_f_f_v_f32m2 (v_ratio ,vl ); 874 875// Use integer rounding: convert f32 -> int (rounds to nearest) 876vint32m2_t v_zp_i32 = __riscv_vfcvt_x_f_v_i32m2 (v_ratio_f32 ,vl ); 877 878// clamp to [0, 15] 879v_zp_i32 = __riscv_vmax_vx_i32m2 (v_zp_i32 ,0 ,vl ); 880v_zp_i32 = __riscv_vmin_vx_i32m2 (v_zp_i32 ,15 ,vl ); 881 882// narrow i32 -> u8 883vint16m1_t v_zp_i16 = __riscv_vncvt_x_x_w_i16m1 (v_zp_i32 ,vl ); 884vint8mf2_t v_zp_i8 = __riscv_vncvt_x_x_w_i8mf2 (v_zp_i16 ,vl ); 885vuint8mf2_t v_zp_u8 = __riscv_vreinterpret_v_i8mf2_u8mf2 (v_zp_i8 ); 886__riscv_vse8_v_u8mf2 (zp_dst + offset ,v_zp_u8 ,vl ); 887 888offset += vl ; 889remaining -= vl ; 890 } 891 } 892 893// --- 2) Nibble repack qs for each of the 32 rows --- 894 { 895const size_t vl8 = __riscv_vsetvl_e8m1 (8 ); 896for (int i = 0 ;i < 32 ;i ++ ) { 897const uint8_t * sq = col_src [i * nblocks ].qs ; 898uint8_t * dq = dst -> qs + i * qs_bytes ; 899 900// stride-2 load to separate even/odd bytes 901vuint8m1_t v_even = __riscv_vlse8_v_u8m1 (sq ,2 ,vl8 ); 902vuint8m1_t v_odd = __riscv_vlse8_v_u8m1 (sq + 1 ,2 ,vl8 ); 903 904// low nibble part: (even & 0x0F) | ((odd & 0x0F) << 4) 905vuint8m1_t v_even_lo = __riscv_vand_vx_u8m1 (v_even ,0x0F ,vl8 ); 906vuint8m1_t v_odd_lo = __riscv_vand_vx_u8m1 (v_odd ,0x0F ,vl8 ); 907vuint8m1_t v_lo = __riscv_vor_vv_u8m1 (v_even_lo ,__riscv_vsll_vx_u8m1 (v_odd_lo ,4 ,vl8 ),vl8 ); 908 909// high nibble part: (even >> 4) | (odd & 0xF0) 910vuint8m1_t v_even_hi = __riscv_vsrl_vx_u8m1 (v_even ,4 ,vl8 ); 911vuint8m1_t v_odd_hi = __riscv_vand_vx_u8m1 (v_odd ,0xF0 ,vl8 ); 912vuint8m1_t v_hi = __riscv_vor_vv_u8m1 (v_even_hi ,v_odd_hi ,vl8 ); 913 914__riscv_vse8_v_u8m1 (dq ,v_lo ,vl8 ); 915__riscv_vse8_v_u8m1 (dq + 8 ,v_hi ,vl8 ); 916 } 917 } 918 919dst ++ ; 920 } 921src += nrows_interleaved * nblocks ; 922 } 923return 0 ; 924 925GGML_UNUSED (data_size ); 926} 927 928static int repack_q4_k_to_q4_1_32_bl (ggml_tensor * t , 929int interleave_block , 930const void * GGML_RESTRICT data , 931size_t data_size ) { 932GGML_ASSERT (t -> type == GGML_TYPE_Q4_K ); 933GGML_ASSERT (interleave_block == 32 ); 934GGML_ASSERT (QK_K /QK4_1 == 8 ); 935 936constexpr int nrows_interleaved = 32 ; 937 938block_q4_1x32 * dst = (block_q4_1x32 * )t -> data ; 939const block_q4_K * src = (const block_q4_K * )data ; 940block_q4_1 dst_tmp [32 ]; 941int nrow = ggml_nrows (t ); 942int nblocks = t -> ne [0 ] /QK_K ; 943 944if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK_K != 0 ) { 945return -1 ; 946 } 947 948for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 949for (int64_t x = 0 ;x < nblocks ;x ++ ) { 950for (int j = 0 ;j < 8 ;j ++ ) { 951for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 952uint8_t sc ,m ; 953const float d = GGML_FP16_TO_FP32 (src [x + i * nblocks ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .d ); 954const float min = 955GGML_FP16_TO_FP32 (src [x + i * nblocks ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .dmin ); 956get_scale_min_k4 (j ,src [x + i * nblocks ].scales ,& sc ,& m ); 957const float d1 = d * sc ; 958const float m1 = min * m ; 959 960dst_tmp [i ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .d = GGML_FP32_TO_FP16 (d1 ); 961dst_tmp [i ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .m = GGML_FP32_TO_FP16 (- m1 ); 962// src -> [b0, b32] [b1, b33] ... [b31, b63] 963// dst -> [b0, b16] [b1, b17] ... [b15, b31] [b32, b48] [b33, b49] ... [b47, b63] 964const uint8_t * q = src [x + i * nblocks ].qs + (j /2 )* QK4_1 ; 965if (j %2 == 0 ) { 966for (int ii = 0 ;ii < 16 ;ii ++ ) { 967dst_tmp [i ].qs [ii ]= (q [ii ]& 0x0F ) | ((q [ii + 16 ]& 0x0F ) <<4 ); 968 } 969 }else { 970for (int ii = 0 ;ii < 16 ;ii ++ ) { 971dst_tmp [i ].qs [ii ]= ((q [ii ]& 0xF0 ) >>4 ) | (q [ii + 16 ]& 0xF0 ); 972 } 973 } 974 } 975* dst ++ = make_block_q4_1x32 (dst_tmp ,interleave_block ); 976 } 977 } 978src += nrows_interleaved * nblocks ; 979 } 980return 0 ; 981 982GGML_UNUSED (data_size ); 983} 984 985static int repack_q6_k_to_q8_0_32_bl_ref (ggml_tensor * t , 986int interleave_block , 987const void * GGML_RESTRICT data , 988size_t data_size ) { 989GGML_ASSERT (t -> type == GGML_TYPE_Q6_K ); 990GGML_ASSERT (interleave_block == 32 ); 991GGML_ASSERT (QK_K /QK4_1 == 8 ); 992 993constexpr int nrows_interleaved = 32 ; 994 995block_q8_0x32 * dst = (block_q8_0x32 * )t -> data ; 996const block_q6_K * src = (const block_q6_K * )data ; 997block_q8_0 dst_tmp [32 ]; 998int8_t aux8 [QK4_1 ]; 999int nrow = ggml_nrows (t ); 1000int nblocks = t -> ne [0 ] /QK_K ; 1001 1002if (t -> ne [0 ] %QK_K != 0 ) { 1003return -1 ; 1004 } 1005 1006for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 1007int64_t nrow_real = std::min ((int64_t )nrow - b , (int64_t )nrows_interleaved ); 1008for (int64_t x = 0 ;x < nblocks ;x ++ ) { 1009for (int bi = 0 ;bi < 8 ;bi ++ ) { 1010int i = 0 ; 1011for (;i < nrow_real ;i ++ ) { 1012const uint8_t * q4 = src [x + i * nblocks ].ql ; 1013const uint8_t * qh = src [x + i * nblocks ].qh ; 1014const int8_t * scales = src [x + i * nblocks ].scales ; 1015float d = GGML_FP16_TO_FP32 (src [x + i * nblocks ].d ); 1016 1017q4 += 64 * (bi /4 ); 1018qh += 32 * (bi /4 ); 1019int8_t * GGML_RESTRICT a = aux8 ; 1020 1021int8_t bi_idx = bi %4 ; 1022 1023if (bi_idx == 0 ) { 1024for (int l = 0 ;l < 32 ;++ l ) { 1025a [l ]= (int8_t ) ((q4 [l ]& 0xF ) | (((qh [l ] >>0 )& 3 ) <<4 ))- 32 ; 1026 } 1027 }else if (bi_idx == 1 ) { 1028for (int l = 0 ;l < 32 ;++ l ) { 1029a [l ]= (int8_t ) ((q4 [l + 32 ]& 0xF ) | (((qh [l ] >>2 )& 3 ) <<4 ))- 32 ; 1030 } 1031 }else if (bi_idx == 2 ) { 1032for (int l = 0 ;l < 32 ;++ l ) { 1033a [l ]= (int8_t ) ((q4 [l + 0 ] >>4 ) | (((qh [l ] >>4 )& 3 ) <<4 ))- 32 ; 1034 } 1035 }else if (bi_idx == 3 ) { 1036for (int l = 0 ;l < 32 ;++ l ) { 1037a [l ]= (int8_t ) ((q4 [l + 32 ] >>4 ) | (((qh [l ] >>6 )& 3 ) <<4 ))- 32 ; 1038 } 1039 } 1040a = aux8 ; 1041 1042float a_max_abs = 0.0f ; 1043float scale_0 = scales [bi * 2 + 0 ]* d ; 1044float scale_1 = scales [bi * 2 + 1 ]* d ; 1045for (int l = 0 ;l < 16 ;++ l ) { 1046a_max_abs = std::max (a_max_abs , std::abs (a [l ]* scale_0 )); 1047 } 1048 1049for (int l = 16 ;l < 32 ;++ l ) { 1050a_max_abs = std::max (a_max_abs , std::abs (a [l ]* scale_1 )); 1051 } 1052 1053float reflect_scale = a_max_abs / ((1 <<7 )- 1 ); 1054float reflect_scale_0 = scale_0 /reflect_scale ; 1055float reflect_scale_1 = scale_1 /reflect_scale ; 1056 1057for (int l = 0 ;l < 16 ;++ l ) { 1058float a_temp = std::clamp (std::nearbyintf (a [l ]* reflect_scale_0 ),-128.0f ,127.0f ); 1059a [l ]= (int8_t ) (a_temp ); 1060 } 1061 1062for (int l = 16 ;l < 32 ;++ l ) { 1063float a_temp = std::clamp (std::nearbyintf (a [l ]* reflect_scale_1 ),-128.0f ,127.0f ); 1064a [l ]= (int8_t ) (a_temp ); 1065 } 1066 1067dst_tmp [i ].d = GGML_FP32_TO_FP16 (reflect_scale ); 1068 1069memcpy (dst_tmp [i ].qs ,a ,32 * sizeof (int8_t )); 1070 } 1071 1072for (;i < nrows_interleaved ;i ++ ) { 1073memset (& dst_tmp [i ],0 ,sizeof (block_q8_0 )); 1074 } 1075 1076* dst ++ = make_block_q8_0x32 (dst_tmp ,interleave_block ); 1077 } 1078 } 1079src += nrows_interleaved * nblocks ; 1080 } 1081return 0 ; 1082 1083GGML_UNUSED (data_size ); 1084} 1085 1086// RVV optimized version of repack_q6_k_to_q8_0_32_bl 1087// Vectorizes the Q6_K dequant -> requant pipeline using RVV intrinsics. 1088// For each sub-block (bi), dequant 32 Q6_K values to int6 -> apply two sub-block scales -> 1089// find max abs -> compute reflect_scale -> requant to int8 -> gather d with stride load. 1090static int repack_q6_k_to_q8_0_32_bl (ggml_tensor * t , 1091int interleave_block , 1092const void * GGML_RESTRICT data , 1093size_t data_size ) { 1094GGML_ASSERT (t -> type == GGML_TYPE_Q6_K ); 1095GGML_ASSERT (interleave_block == 32 ); 1096GGML_ASSERT (QK_K /QK4_1 == 8 ); 1097 1098constexpr int nrows_interleaved = 32 ; 1099 1100block_q8_0x32 * dst = (block_q8_0x32 * )t -> data ; 1101const block_q6_K * src = (const block_q6_K * )data ; 1102int nrow = ggml_nrows (t ); 1103int nblocks = t -> ne [0 ] /QK_K ; 1104 1105if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK_K != 0 ) { 1106return -1 ; 1107 } 1108 1109const ptrdiff_t row_stride = (ptrdiff_t )nblocks * sizeof (block_q6_K ); 1110 1111for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 1112for (int64_t x = 0 ;x < nblocks ;x ++ ) { 1113for (int bi = 0 ;bi < 8 ;bi ++ ) { 1114// --- 1) Gather 32 d values with stride load --- 1115// We need to compute reflect_scale per row first, so gather d later. 1116// Process each row: dequant Q6_K sub-block -> requant to Q8_0 1117for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 1118const block_q6_K * src_blk = & src [x + i * nblocks ]; 1119const uint8_t * q4 = src_blk -> ql + 64 * (bi /4 ); 1120const uint8_t * qh = src_blk -> qh + 32 * (bi /4 ); 1121const int8_t * scales = src_blk -> scales ; 1122float d = GGML_FP16_TO_FP32 (src_blk -> d ); 1123 1124int8_t bi_idx = bi %4 ; 1125 1126// --- Dequant 32 Q6_K values to int6 (range [-32, 31]) using RVV --- 1127// vl = 32 for e8m2 (VLEN=256) or loop for smaller VLEN 1128const size_t vl16 = __riscv_vsetvl_e8m1 (16 ); 1129 1130vint8m1_t va_lo ,va_hi ;// 16 elements each 1131 1132if (bi_idx == 0 ) { 1133// a[l] = (q4[l] & 0xF) | (((qh[l] >> 0) & 3) << 4) - 32 1134vuint8m1_t vq4_lo = __riscv_vle8_v_u8m1 (q4 ,vl16 ); 1135vuint8m1_t vq4_hi = __riscv_vle8_v_u8m1 (q4 + 16 ,vl16 ); 1136vuint8m1_t vqh_lo = __riscv_vle8_v_u8m1 (qh ,vl16 ); 1137vuint8m1_t vqh_hi = __riscv_vle8_v_u8m1 (qh + 16 ,vl16 ); 1138 1139vuint8m1_t vlo4_lo = __riscv_vand_vx_u8m1 (vq4_lo ,0x0F ,vl16 ); 1140vuint8m1_t vlo4_hi = __riscv_vand_vx_u8m1 (vq4_hi ,0x0F ,vl16 ); 1141vuint8m1_t vh_lo = __riscv_vsll_vx_u8m1 (__riscv_vand_vx_u8m1 (vqh_lo ,0x03 ,vl16 ),4 ,vl16 ); 1142vuint8m1_t vh_hi = __riscv_vsll_vx_u8m1 (__riscv_vand_vx_u8m1 (vqh_hi ,0x03 ,vl16 ),4 ,vl16 ); 1143 1144vuint8m1_t vcomb_lo = __riscv_vor_vv_u8m1 (vlo4_lo ,vh_lo ,vl16 ); 1145vuint8m1_t vcomb_hi = __riscv_vor_vv_u8m1 (vlo4_hi ,vh_hi ,vl16 ); 1146 1147va_lo = __riscv_vsub_vx_i8m1 (__riscv_vreinterpret_v_u8m1_i8m1 (vcomb_lo ),32 ,vl16 ); 1148va_hi = __riscv_vsub_vx_i8m1 (__riscv_vreinterpret_v_u8m1_i8m1 (vcomb_hi ),32 ,vl16 ); 1149 }else if (bi_idx == 1 ) { 1150// a[l] = (q4[l+32] & 0xF) | (((qh[l] >> 2) & 3) << 4) - 32 1151vuint8m1_t vq4_lo = __riscv_vle8_v_u8m1 (q4 + 32 ,vl16 ); 1152vuint8m1_t vq4_hi = __riscv_vle8_v_u8m1 (q4 + 48 ,vl16 ); 1153vuint8m1_t vqh_lo = __riscv_vle8_v_u8m1 (qh ,vl16 ); 1154vuint8m1_t vqh_hi = __riscv_vle8_v_u8m1 (qh + 16 ,vl16 ); 1155 1156vuint8m1_t vlo4_lo = __riscv_vand_vx_u8m1 (vq4_lo ,0x0F ,vl16 ); 1157vuint8m1_t vlo4_hi = __riscv_vand_vx_u8m1 (vq4_hi ,0x0F ,vl16 ); 1158vuint8m1_t vh_lo = __riscv_vsll_vx_u8m1 ( 1159__riscv_vand_vx_u8m1 (__riscv_vsrl_vx_u8m1 (vqh_lo ,2 ,vl16 ),0x03 ,vl16 ),4 ,vl16 ); 1160vuint8m1_t vh_hi = __riscv_vsll_vx_u8m1 ( 1161__riscv_vand_vx_u8m1 (__riscv_vsrl_vx_u8m1 (vqh_hi ,2 ,vl16 ),0x03 ,vl16 ),4 ,vl16 ); 1162 1163vuint8m1_t vcomb_lo = __riscv_vor_vv_u8m1 (vlo4_lo ,vh_lo ,vl16 ); 1164vuint8m1_t vcomb_hi = __riscv_vor_vv_u8m1 (vlo4_hi ,vh_hi ,vl16 ); 1165 1166va_lo = __riscv_vsub_vx_i8m1 (__riscv_vreinterpret_v_u8m1_i8m1 (vcomb_lo ),32 ,vl16 ); 1167va_hi = __riscv_vsub_vx_i8m1 (__riscv_vreinterpret_v_u8m1_i8m1 (vcomb_hi ),32 ,vl16 ); 1168 }else if (bi_idx == 2 ) { 1169// a[l] = (q4[l] >> 4) | (((qh[l] >> 4) & 3) << 4) - 32 1170vuint8m1_t vq4_lo = __riscv_vle8_v_u8m1 (q4 ,vl16 ); 1171vuint8m1_t vq4_hi = __riscv_vle8_v_u8m1 (q4 + 16 ,vl16 ); 1172vuint8m1_t vqh_lo = __riscv_vle8_v_u8m1 (qh ,vl16 ); 1173vuint8m1_t vqh_hi = __riscv_vle8_v_u8m1 (qh + 16 ,vl16 ); 1174 1175vuint8m1_t vhi4_lo = __riscv_vsrl_vx_u8m1 (vq4_lo ,4 ,vl16 ); 1176vuint8m1_t vhi4_hi = __riscv_vsrl_vx_u8m1 (vq4_hi ,4 ,vl16 ); 1177vuint8m1_t vh_lo = __riscv_vsll_vx_u8m1 ( 1178__riscv_vand_vx_u8m1 (__riscv_vsrl_vx_u8m1 (vqh_lo ,4 ,vl16 ),0x03 ,vl16 ),4 ,vl16 ); 1179vuint8m1_t vh_hi = __riscv_vsll_vx_u8m1 ( 1180__riscv_vand_vx_u8m1 (__riscv_vsrl_vx_u8m1 (vqh_hi ,4 ,vl16 ),0x03 ,vl16 ),4 ,vl16 ); 1181 1182vuint8m1_t vcomb_lo = __riscv_vor_vv_u8m1 (vhi4_lo ,vh_lo ,vl16 ); 1183vuint8m1_t vcomb_hi = __riscv_vor_vv_u8m1 (vhi4_hi ,vh_hi ,vl16 ); 1184 1185va_lo = __riscv_vsub_vx_i8m1 (__riscv_vreinterpret_v_u8m1_i8m1 (vcomb_lo ),32 ,vl16 ); 1186va_hi = __riscv_vsub_vx_i8m1 (__riscv_vreinterpret_v_u8m1_i8m1 (vcomb_hi ),32 ,vl16 ); 1187 }else {// bi_idx == 3 1188// a[l] = (q4[l+32] >> 4) | (((qh[l] >> 6) & 3) << 4) - 32 1189vuint8m1_t vq4_lo = __riscv_vle8_v_u8m1 (q4 + 32 ,vl16 ); 1190vuint8m1_t vq4_hi = __riscv_vle8_v_u8m1 (q4 + 48 ,vl16 ); 1191vuint8m1_t vqh_lo = __riscv_vle8_v_u8m1 (qh ,vl16 ); 1192vuint8m1_t vqh_hi = __riscv_vle8_v_u8m1 (qh + 16 ,vl16 ); 1193 1194vuint8m1_t vhi4_lo = __riscv_vsrl_vx_u8m1 (vq4_lo ,4 ,vl16 ); 1195vuint8m1_t vhi4_hi = __riscv_vsrl_vx_u8m1 (vq4_hi ,4 ,vl16 ); 1196vuint8m1_t vh_lo = __riscv_vsll_vx_u8m1 ( 1197__riscv_vand_vx_u8m1 (__riscv_vsrl_vx_u8m1 (vqh_lo ,6 ,vl16 ),0x03 ,vl16 ),4 ,vl16 ); 1198vuint8m1_t vh_hi = __riscv_vsll_vx_u8m1 ( 1199__riscv_vand_vx_u8m1 (__riscv_vsrl_vx_u8m1 (vqh_hi ,6 ,vl16 ),0x03 ,vl16 ),4 ,vl16 ); 1200 1201vuint8m1_t vcomb_lo = __riscv_vor_vv_u8m1 (vhi4_lo ,vh_lo ,vl16 ); 1202vuint8m1_t vcomb_hi = __riscv_vor_vv_u8m1 (vhi4_hi ,vh_hi ,vl16 ); 1203 1204va_lo = __riscv_vsub_vx_i8m1 (__riscv_vreinterpret_v_u8m1_i8m1 (vcomb_lo ),32 ,vl16 ); 1205va_hi = __riscv_vsub_vx_i8m1 (__riscv_vreinterpret_v_u8m1_i8m1 (vcomb_hi ),32 ,vl16 ); 1206 } 1207 1208// --- Widen to i16 for scaled abs computation --- 1209float scale_0 = scales [bi * 2 + 0 ]* d ; 1210float scale_1 = scales [bi * 2 + 1 ]* d ; 1211 1212// Widen i8 -> i16 -> f32 for abs*scale computation 1213vint16m2_t va_lo_w = __riscv_vsext_vf2_i16m2 (va_lo ,vl16 ); 1214vint16m2_t va_hi_w = __riscv_vsext_vf2_i16m2 (va_hi ,vl16 ); 1215 1216// Compute |a[l] * scale_0| for lo half, |a[l] * scale_1| for hi half 1217vfloat32m4_t vf_lo = __riscv_vfcvt_f_x_v_f32m4 (__riscv_vsext_vf2_i32m4 (va_lo_w ,vl16 ),vl16 ); 1218vfloat32m4_t vf_hi = __riscv_vfcvt_f_x_v_f32m4 (__riscv_vsext_vf2_i32m4 (va_hi_w ,vl16 ),vl16 ); 1219 1220vfloat32m4_t vabs_lo = __riscv_vfabs_v_f32m4 (__riscv_vfmul_vf_f32m4 (vf_lo ,scale_0 ,vl16 ),vl16 ); 1221vfloat32m4_t vabs_hi = __riscv_vfabs_v_f32m4 (__riscv_vfmul_vf_f32m4 (vf_hi ,scale_1 ,vl16 ),vl16 ); 1222 1223// Find max abs across both halves 1224vfloat32m4_t vabs_max = __riscv_vfmax_vv_f32m4 (vabs_lo ,vabs_hi ,vl16 ); 1225 1226// Reduce to scalar max 1227vfloat32m1_t vzero = __riscv_vfmv_v_f_f32m1 (0.0f ,1 ); 1228vfloat32m1_t vmax_red = __riscv_vfredmax_vs_f32m4_f32m1 (vabs_max ,vzero ,vl16 ); 1229float a_max_abs = __riscv_vfmv_f_s_f32m1_f32 (vmax_red ); 1230 1231float reflect_scale = a_max_abs /127.0f ; 1232float reflect_scale_0 = scale_0 /reflect_scale ; 1233float reflect_scale_1 = scale_1 /reflect_scale ; 1234 1235// --- Requant: a[l] = clamp(nearbyint(a[l] * reflect_scale_x), -128, 127) --- 1236vfloat32m4_t vscaled_lo = __riscv_vfmul_vf_f32m4 (vf_lo ,reflect_scale_0 ,vl16 ); 1237vfloat32m4_t vscaled_hi = __riscv_vfmul_vf_f32m4 (vf_hi ,reflect_scale_1 ,vl16 ); 1238 1239// fcvt.x rounds to nearest (using current rounding mode) 1240vint32m4_t vi_lo = __riscv_vfcvt_x_f_v_i32m4 (vscaled_lo ,vl16 ); 1241vint32m4_t vi_hi = __riscv_vfcvt_x_f_v_i32m4 (vscaled_hi ,vl16 ); 1242 1243// Clamp to [-128, 127] 1244vi_lo = __riscv_vmax_vx_i32m4 (vi_lo ,-128 ,vl16 ); 1245vi_lo = __riscv_vmin_vx_i32m4 (vi_lo ,127 ,vl16 ); 1246vi_hi = __riscv_vmax_vx_i32m4 (vi_hi ,-128 ,vl16 ); 1247vi_hi = __riscv_vmin_vx_i32m4 (vi_hi ,127 ,vl16 ); 1248 1249// Narrow i32 -> i16 -> i8 1250vint16m2_t vi16_lo = __riscv_vncvt_x_x_w_i16m2 (vi_lo ,vl16 ); 1251vint16m2_t vi16_hi = __riscv_vncvt_x_x_w_i16m2 (vi_hi ,vl16 ); 1252vint8m1_t vi8_lo = __riscv_vncvt_x_x_w_i8m1 (vi16_lo ,vl16 ); 1253vint8m1_t vi8_hi = __riscv_vncvt_x_x_w_i8m1 (vi16_hi ,vl16 ); 1254 1255// Store d and qs directly into dst block 1256dst -> d [i ]= GGML_FP32_TO_FP16 (reflect_scale ); 1257int8_t * dq = (int8_t * )dst -> qs + i * QK8_0 ; 1258__riscv_vse8_v_i8m1 (dq ,vi8_lo ,vl16 ); 1259__riscv_vse8_v_i8m1 (dq + 16 ,vi8_hi ,vl16 ); 1260 } 1261dst ++ ; 1262 } 1263 } 1264src += nrows_interleaved * nblocks ; 1265 } 1266return 0 ; 1267 1268GGML_UNUSED (data_size ); 1269} 1270 1271static int repack_q8_0_to_q8_0_32_bl_ref (ggml_tensor * t , 1272int interleave_block , 1273const void * GGML_RESTRICT data , 1274size_t data_size ) { 1275GGML_ASSERT (t -> type == GGML_TYPE_Q8_0 ); 1276GGML_ASSERT (interleave_block == 32 );// unused 1277 1278constexpr int nrows_interleaved = 32 ; 1279 1280block_q8_0x32 * dst = (block_q8_0x32 * )t -> data ; 1281const block_q8_0 * src = (const block_q8_0 * )data ; 1282block_q8_0 dst_tmp [32 ]; 1283int nrow = ggml_nrows (t ); 1284int nblocks = t -> ne [0 ] /QK8_0 ; 1285 1286GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q8_0 )); 1287 1288if (t -> ne [0 ] %QK8_0 != 0 ) { 1289return -1 ; 1290 } 1291 1292for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 1293int64_t nrows_real = std::min ((int64_t )nrow - b , (int64_t )nrows_interleaved ); 1294for (int64_t x = 0 ;x < nblocks ;x ++ ) { 1295int i = 0 ; 1296for (;i < nrows_real ;i ++ ) { 1297dst_tmp [i ]= src [x + i * nblocks ]; 1298 } 1299for (;i < nrows_interleaved ;i ++ ) { 1300memset (& dst_tmp [i ],0 ,sizeof (block_q8_0 )); 1301 } 1302* dst ++ = make_block_q8_0x32 (dst_tmp ,interleave_block ); 1303 } 1304src += nrows_interleaved * nblocks ; 1305 } 1306return 0 ; 1307 1308GGML_UNUSED (data_size ); 1309} 1310 1311// RVV optimized version of repack_q8_0_to_q8_0_32_bl 1312// Eliminates the intermediate dst_tmp buffer and vectorizes scale gather + qs copy. 1313static int repack_q8_0_to_q8_0_32_bl (ggml_tensor * t , 1314int interleave_block , 1315const void * GGML_RESTRICT data , 1316size_t data_size ) { 1317GGML_ASSERT (t -> type == GGML_TYPE_Q8_0 ); 1318GGML_ASSERT (interleave_block == 32 ); 1319 1320constexpr int nrows_interleaved = 32 ; 1321 1322block_q8_0x32 * dst = (block_q8_0x32 * )t -> data ; 1323const block_q8_0 * src = (const block_q8_0 * )data ; 1324int nrow = ggml_nrows (t ); 1325int nblocks = t -> ne [0 ] /QK8_0 ; 1326 1327GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q8_0 )); 1328 1329if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK8_0 != 0 ) { 1330return -1 ; 1331 } 1332 1333const ptrdiff_t row_stride = (ptrdiff_t )nblocks * sizeof (block_q8_0 ); 1334 1335for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 1336for (int64_t x = 0 ;x < nblocks ;x ++ ) { 1337const block_q8_0 * col_src = src + x ; 1338 1339// --- 1) Gather 32 scale values (ggml_half d) with stride load --- 1340 { 1341const uint8_t * d_base = (const uint8_t * )& col_src -> d ; 1342ggml_half * d_dst = dst -> d ; 1343size_t remaining = 32 ; 1344size_t offset = 0 ; 1345while (remaining > 0 ) { 1346size_t vl = __riscv_vsetvl_e16m1 (remaining ); 1347vuint16m1_t vd = 1348__riscv_vlse16_v_u16m1 ((const uint16_t * ) (d_base + offset * row_stride ),row_stride ,vl ); 1349__riscv_vse16_v_u16m1 ((uint16_t * ) (d_dst + offset ),vd ,vl ); 1350offset += vl ; 1351remaining -= vl ; 1352 } 1353 } 1354 1355// --- 2) Copy qs for each of the 32 rows (32 bytes per row) --- 1356 { 1357for (int i = 0 ;i < 32 ;i ++ ) { 1358const int8_t * sq = col_src [i * nblocks ].qs ; 1359int8_t * dq = (int8_t * )dst -> qs + i * QK8_0 ; 1360 1361size_t len = QK8_0 ; 1362size_t idx = 0 ; 1363while (len > 0 ) { 1364size_t vl = __riscv_vsetvl_e8m2 (len ); 1365vint8m2_t vs = __riscv_vle8_v_i8m2 (sq + idx ,vl ); 1366__riscv_vse8_v_i8m2 (dq + idx ,vs ,vl ); 1367idx += vl ; 1368len -= vl ; 1369 } 1370 } 1371 } 1372 1373dst ++ ; 1374 } 1375src += nrows_interleaved * nblocks ; 1376 } 1377return 0 ; 1378 1379GGML_UNUSED (data_size ); 1380} 1381 1382static void convert_mxfp4_to_5bit (const block_mxfp4 & src , spacemit_kernels::nrow_block_mxfp4 < 1 > & dst ) { 1383dst .e [0 ]= src .e ; 1384 1385// Decode all 32 mxfp4 values to signed integers via kvalues_mxfp4 1386int8_t vals [32 ]; 1387for (int j = 0 ;j < QK_MXFP4 /2 ;j ++ ) { 1388vals [j ]= kvalues_mxfp4 [src .qs [j ]& 0xF ]; 1389vals [j + QK_MXFP4 /2 ]= kvalues_mxfp4 [src .qs [j ] >>4 ]; 1390 } 1391 1392// vals [b0, b1, b2, b3, ..., b30, b31] 1393// Pack abs into qs with reorder: [b0,b1]..[b14,b15]..[b30,b31] 1394for (int j = 0 ;j < QK_MXFP4 /2 ;j ++ ) { 1395uint8_t lo0 = static_cast < uint8_t > (std::abs (vals [j * 2 ])); 1396uint8_t lo1 = static_cast < uint8_t > (std::abs (vals [j * 2 + 1 ])); 1397dst .qs [j ]= (lo0 & 0x0F ) | ((lo1 & 0x0F ) <<4 ); 1398 } 1399 1400// Pack sign bits into qh[4] (32 bits total, 1 bit per weight) 1401// reorder: [0,1,2,...,15,16,17,...,31] after the qs reorder above 1402uint32_t sign_bits = 0 ; 1403for (int j = 0 ;j < 32 ;j ++ ) { 1404if (vals [j ]< 0 ) { 1405sign_bits |= (1u <<j ); 1406 } 1407 } 1408memcpy (dst .qh ,& sign_bits ,4 ); 1409} 1410 1411static spacemit_kernels::nrow_block_mxfp4 < 32 > make_block_mxfp4x32 (spacemit_kernels::nrow_block_mxfp4 < 1 > * in , 1412unsigned int blck_size_interleave ) { 1413 spacemit_kernels::nrow_block_mxfp4 < 32 > out ; 1414GGML_ASSERT (QK_MXFP4 /blck_size_interleave == 1 ); 1415GGML_UNUSED (blck_size_interleave ); 1416 1417for (int i = 0 ;i < 32 ;i ++ ) { 1418out .e [i ]= in [i ].e [0 ]; 1419 } 1420 1421// qs: copy per-row 16 bytes 1422for (int i = 0 ;i < 32 ;i ++ ) { 1423memcpy (out .qs + i * 16 ,in [i ].qs ,16 ); 1424 } 1425 1426// qh: copy per-row 4 bytes 1427for (int i = 0 ;i < 32 ;i ++ ) { 1428memcpy (out .qh + i * 4 ,in [i ].qh ,4 ); 1429 } 1430 1431return out ; 1432} 1433 1434static int repack_mxfp4_to_mxfp4_32_bl (ggml_tensor * t , 1435int interleave_block , 1436const void * GGML_RESTRICT data , 1437size_t data_size ) { 1438GGML_ASSERT (t -> type == GGML_TYPE_MXFP4 ); 1439GGML_ASSERT (interleave_block == 32 ); 1440 1441constexpr int nrows_interleaved = 32 ; 1442 1443 spacemit_kernels::nrow_block_mxfp4 < 32 > * dst = (spacemit_kernels::nrow_block_mxfp4 < 32 > * )t -> data ; 1444const block_mxfp4 * src = (const block_mxfp4 * )data ; 1445 spacemit_kernels::nrow_block_mxfp4 < 1 > dst_tmp [32 ]; 1446int nrow = ggml_nrows (t ); 1447int nblocks = t -> ne [0 ] /QK_MXFP4 ; 1448 1449GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_mxfp4 )); 1450 1451if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK_MXFP4 != 0 ) { 1452return -1 ; 1453 } 1454 1455for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 1456for (int64_t x = 0 ;x < nblocks ;x ++ ) { 1457for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 1458convert_mxfp4_to_5bit (src [x + i * nblocks ],dst_tmp [i ]); 1459 } 1460* dst ++ = make_block_mxfp4x32 (dst_tmp ,interleave_block ); 1461 } 1462src += nrows_interleaved * nblocks ; 1463 } 1464return 0 ; 1465} 1466 1467static spacemit_kernels::nrow_block_q5_1 < 32 > make_block_q5_1x32 (spacemit_kernels::nrow_block_q5_1 < 1 > * in , 1468unsigned int blck_size_interleave ) { 1469 spacemit_kernels::nrow_block_q5_1 < 32 > out ; 1470GGML_ASSERT (QK5_1 /blck_size_interleave == 1 ); 1471GGML_UNUSED (blck_size_interleave ); 1472 1473for (int i = 0 ;i < 32 ;i ++ ) { 1474out .scales16 [i ]= in [i ].scales16 [0 ]; 1475out .zp [i ]= in [i ].zp [0 ]; 1476 } 1477 1478// qs: low 4 bits, reorder from [b0,b16],[b1,b17]... to [b0,b1]...[b14,b15] and [b16,b17]...[b30,b31] 1479for (int i = 0 ;i < 32 ;i ++ ) { 1480// low half [0..15] 1481for (int j = 0 ;j < QK5_1 /4 ;j ++ ) { 1482out .qs [i * QK5_1 /2 + j ]= (in [i ].qs [j * 2 ]& 0x0F ) | ((in [i ].qs [j * 2 + 1 ]& 0x0F ) <<4 ); 1483 } 1484// high half [16..31] 1485for (int j = 0 ;j < QK5_1 /4 ;j ++ ) { 1486out .qs [i * QK5_1 /2 + QK5_1 /4 + j ]= ((in [i ].qs [j * 2 ]& 0xF0 ) >>4 ) | (in [i ].qs [j * 2 + 1 ]& 0xF0 ); 1487 } 1488 } 1489 1490// qh: 5th bit, copy directly 1491for (int i = 0 ;i < 32 ;i ++ ) { 1492for (int j = 0 ;j < 4 ;j ++ ) { 1493out .qh [i * 4 + j ]= in [i ].qh [j ]; 1494 } 1495 } 1496 1497return out ; 1498} 1499 1500static spacemit_kernels::nrow_block_q5_0 < 32 > make_block_q5_0x32 (spacemit_kernels::nrow_block_q5_0 < 1 > * in , 1501unsigned int blck_size_interleave ) { 1502 spacemit_kernels::nrow_block_q5_0 < 32 > out ; 1503GGML_ASSERT (QK5_0 /blck_size_interleave == 1 ); 1504GGML_UNUSED (blck_size_interleave ); 1505 1506for (int i = 0 ;i < 32 ;i ++ ) { 1507out .scales16 [i ]= in [i ].scales16 [0 ]; 1508 } 1509 1510// qs: low 4 bits, reorder from [b0,b16],[b1,b17]... to [b0,b1]...[b14,b15] and [b16,b17]...[b30,b31] 1511for (int i = 0 ;i < 32 ;i ++ ) { 1512// low half [0..15] 1513for (int j = 0 ;j < QK5_0 /4 ;j ++ ) { 1514out .qs [i * QK5_0 /2 + j ]= (in [i ].qs [j * 2 ]& 0x0F ) | ((in [i ].qs [j * 2 + 1 ]& 0x0F ) <<4 ); 1515 } 1516// high half [16..31] 1517for (int j = 0 ;j < QK5_0 /4 ;j ++ ) { 1518out .qs [i * QK5_0 /2 + QK5_0 /4 + j ]= ((in [i ].qs [j * 2 ]& 0xF0 ) >>4 ) | (in [i ].qs [j * 2 + 1 ]& 0xF0 ); 1519 } 1520 } 1521 1522// qh: 5th bit, copy directly 1523for (int i = 0 ;i < 32 ;i ++ ) { 1524for (int j = 0 ;j < 4 ;j ++ ) { 1525out .qh [i * 4 + j ]= in [i ].qh [j ]; 1526 } 1527 } 1528 1529return out ; 1530} 1531 1532static int repack_q5_0_to_q5_0_32_bl (ggml_tensor * t , 1533int interleave_block , 1534const void * GGML_RESTRICT data , 1535size_t data_size ) { 1536GGML_ASSERT (t -> type == GGML_TYPE_Q5_0 ); 1537GGML_ASSERT (interleave_block == 32 );// unused 1538 1539constexpr int nrows_interleaved = 32 ; 1540 1541 spacemit_kernels::nrow_block_q5_0 < 32 > * dst = (spacemit_kernels::nrow_block_q5_0 < 32 > * )t -> data ; 1542const block_q5_0 * src = (const block_q5_0 * )data ; 1543 spacemit_kernels::nrow_block_q5_0 < 1 > dst_tmp [32 ]; 1544int nrow = ggml_nrows (t ); 1545int nblocks = t -> ne [0 ] /QK5_0 ; 1546 1547GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q5_0 )); 1548 1549if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK5_0 != 0 ) { 1550return -1 ; 1551 } 1552 1553for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 1554for (int64_t x = 0 ;x < nblocks ;x ++ ) { 1555for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 1556const block_q5_0 & s = src [x + i * nblocks ]; 1557 1558dst_tmp [i ].scales16 [0 ]= s .d ; 1559memcpy (dst_tmp [i ].qs ,s .qs ,sizeof (dst_tmp [i ].qs )); 1560memcpy (dst_tmp [i ].qh ,s .qh ,sizeof (dst_tmp [i ].qh )); 1561 } 1562* dst ++ = make_block_q5_0x32 (dst_tmp ,interleave_block ); 1563 } 1564src += nrows_interleaved * nblocks ; 1565 } 1566return 0 ; 1567} 1568 1569static int repack_q5_1_to_q5_1_32_bl (ggml_tensor * t , 1570int interleave_block , 1571const void * GGML_RESTRICT data , 1572size_t data_size ) { 1573GGML_ASSERT (t -> type == GGML_TYPE_Q5_1 ); 1574GGML_ASSERT (interleave_block == 32 );// unused 1575 1576constexpr int nrows_interleaved = 32 ; 1577 1578 spacemit_kernels::nrow_block_q5_1 < 32 > * dst = (spacemit_kernels::nrow_block_q5_1 < 32 > * )t -> data ; 1579const block_q5_1 * src = (const block_q5_1 * )data ; 1580 spacemit_kernels::nrow_block_q5_1 < 1 > dst_tmp [32 ]; 1581int nrow = ggml_nrows (t ); 1582int nblocks = t -> ne [0 ] /QK5_1 ; 1583 1584GGML_ASSERT (data_size == nrow * nblocks * sizeof (block_q5_1 )); 1585 1586if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK5_1 != 0 ) { 1587return -1 ; 1588 } 1589 1590for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 1591for (int64_t x = 0 ;x < nblocks ;x ++ ) { 1592for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 1593const block_q5_1 & s = src [x + i * nblocks ]; 1594 1595float d = GGML_FP16_TO_FP32 (s .GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .d ); 1596float m = GGML_FP16_TO_FP32 (s .GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .m ); 1597 1598if (d == 0.0f ) { 1599dst_tmp [i ].scales16 [0 ]= GGML_FP32_TO_FP16 (std::fabs (m )); 1600dst_tmp [i ].zp [0 ]= m < 0.0f ?1 :0 ; 1601memset (dst_tmp [i ].qh ,0 ,sizeof (dst_tmp [i ].qh )); 1602memset (dst_tmp [i ].qs ,m > 0.0f ?0x11 :0x00 ,sizeof (dst_tmp [i ].qs )); 1603continue ; 1604 } 1605 1606float mid = std::nearbyintf (- m /d ); 1607mid = std::min (31.0f , std::max (0.0f ,mid )); 1608 1609dst_tmp [i ].scales16 [0 ]= GGML_FP32_TO_FP16 (d ); 1610dst_tmp [i ].zp [0 ]= static_cast < uint8_t > (mid ); 1611 1612// qs: copy low 4 bits directly (same nibble packing) 1613memcpy (dst_tmp [i ].qs ,s .qs ,QK5_1 /2 ); 1614 1615// qh: copy 5th bit directly 1616memcpy (dst_tmp [i ].qh ,s .qh ,4 ); 1617 } 1618* dst ++ = make_block_q5_1x32 (dst_tmp ,interleave_block ); 1619 } 1620src += nrows_interleaved * nblocks ; 1621 } 1622return 0 ; 1623} 1624 1625static int repack_q5_k_to_q5_1_32_bl (ggml_tensor * t , 1626int interleave_block , 1627const void * GGML_RESTRICT data , 1628size_t data_size ) { 1629GGML_ASSERT (t -> type == GGML_TYPE_Q5_K ); 1630GGML_ASSERT (interleave_block == 32 ); 1631GGML_ASSERT (QK_K /QK5_1 == 8 ); 1632 1633constexpr int nrows_interleaved = 32 ; 1634 1635 spacemit_kernels::nrow_block_q5_1 < 32 > * dst = (spacemit_kernels::nrow_block_q5_1 < 32 > * )t -> data ; 1636const block_q5_K * src = (const block_q5_K * )data ; 1637 spacemit_kernels::nrow_block_q5_1 < 1 > dst_tmp [32 ]; 1638int nrow = ggml_nrows (t ); 1639int nblocks = t -> ne [0 ] /QK_K ; 1640 1641if (t -> ne [1 ] %nrows_interleaved != 0 || t -> ne [0 ] %QK_K != 0 ) { 1642return -1 ; 1643 } 1644 1645for (int b = 0 ;b < nrow ;b += nrows_interleaved ) { 1646for (int64_t x = 0 ;x < nblocks ;x ++ ) { 1647for (int j = 0 ;j < 8 ;j ++ ) { 1648for (int i = 0 ;i < nrows_interleaved ;i ++ ) { 1649uint8_t sc ,m ; 1650const float d = GGML_FP16_TO_FP32 (src [x + i * nblocks ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .d ); 1651const float min = 1652GGML_FP16_TO_FP32 (src [x + i * nblocks ].GGML_COMMON_AGGR_U .GGML_COMMON_AGGR_S .dmin ); 1653get_scale_min_k4 (j ,src [x + i * nblocks ].scales ,& sc ,& m ); 1654 1655float d1 = d * sc ; 1656float m1 = min * m ; 1657 1658float mid = std::nearbyintf (m1 /d1 ); 1659mid = std::min (31.0f , std::max (0.0f ,mid )); 1660dst_tmp [i ].scales16 [0 ]= GGML_FP32_TO_FP16 (d1 ); 1661dst_tmp [i ].zp [0 ]= static_cast < uint8_t > (mid ); 1662 1663// src -> [b0, b32] [b1, b33] ... [b31, b63] 1664// dst -> [b0, b16] [b1, b17] ... [b15, b31] [b32, b48] [b33, b49] ... [b47, b63] 1665const uint8_t * q = src [x + i * nblocks ].qs + (j /2 )* QK5_1 ; 1666if (j %2 == 0 ) { 1667for (int ii = 0 ;ii < 16 ;ii ++ ) { 1668dst_tmp [i ].qs [ii ]= (q [ii ]& 0x0F ) | ((q [ii + 16 ]& 0x0F ) <<4 ); 1669 } 1670 }else { 1671for (int ii = 0 ;ii < 16 ;ii ++ ) { 1672dst_tmp [i ].qs [ii ]= ((q [ii ]& 0xF0 ) >>4 ) | (q [ii + 16 ]& 0xF0 ); 1673 } 1674 } 1675 1676// Extract the 5th bit (qh) for this sub-block 1677// block_q5_K.qh[32]: for sub-block j, the 5th bit is at bit position j in qh[l] 1678// qs was reordered: dst_qs maps to src weights [0,16,1,17,...,15,31] 1679// So qh must follow the same reorder to stay aligned with qs 1680// dst qh[4] = 32 bits for 32 weights in the reordered layout: 1681// byte 0: weights 0..7 (from src_qh[0..7]) 1682// byte 1: weights 8..15 (from src_qh[8..15]) 1683// byte 2: weights 16..23 (from src_qh[16..23]) 1684// byte 3: weights 24..31 (from src_qh[24..31]) 1685const uint8_t * src_qh = src [x + i * nblocks ].qh ; 1686for (int bi = 0 ;bi < 4 ;bi ++ ) { 1687uint8_t qh_byte = 0 ; 1688for (int k = 0 ;k < 8 ;k ++ ) { 1689int src_idx = bi * 8 + k ; 1690qh_byte |= ((src_qh [src_idx ] >>j )& 1 ) <<k ; 1691 } 1692dst_tmp [i ].qh [bi ]= qh_byte ; 1693 } 1694 } 1695* dst ++ = make_block_q5_1x32 (dst_tmp ,interleave_block ); 1696 } 1697 } 1698src += nrows_interleaved * nblocks ; 1699 } 1700return 0 ; 1701} 1702 1703namespace ggml::cpu::riscv64_spacemit { 1704 1705template < typename BLOC_TYPE ,int64_t INTER_SIZE ,int64_t NB_COLS > int repack (ggml_tensor * ,const void * ,size_t ); 1706 1707template <> int repack < block_q4_0 ,32 ,16 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1708return repack_q4_0_to_q4_0_16_bl (t ,16 ,data ,data_size ); 1709} 1710 1711template <> int repack < block_q4_1 ,32 ,16 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1712return repack_q4_1_to_q4_1_16_bl (t ,16 ,data ,data_size ); 1713} 1714 1715template <> int repack < block_q4_K ,32 ,16 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1716return repack_q4_k_to_q4_1_16_bl (t ,16 ,data ,data_size ); 1717} 1718 1719template <> int repack < block_q2_K ,256 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1720return repack_q2_k_to_q2_k_32_bl (t ,32 ,data ,data_size ); 1721} 1722 1723template <> int repack < block_q3_K ,256 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1724return repack_q3_k_to_q3_k_32_bl (t ,32 ,data ,data_size ); 1725} 1726 1727template <> int repack < block_q4_0 ,32 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1728#if 0 1729return repack_q4_0_to_q4_0_32_bl_ref (t ,32 ,data ,data_size ); 1730#else 1731return repack_q4_0_to_q4_0_32_bl (t ,32 ,data ,data_size ); 1732#endif 1733} 1734 1735template <> int repack < block_q4_0 ,256 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1736#if 1 1737return repack_q4_0_to_q4_0_256_32_bl_ref (t ,32 ,data ,data_size ); 1738#else 1739//return repack_q4_0_to_q4_0_256_32_bl(t, 32, data, data_size); 1740#endif 1741} 1742 1743template <> int repack < block_q4_1 ,32 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1744#if 0 1745return repack_q4_1_to_q4_1_32_bl_ref (t ,32 ,data ,data_size ); 1746#else 1747return repack_q4_1_to_q4_1_32_bl (t ,32 ,data ,data_size ); 1748#endif 1749} 1750 1751template <> int repack < block_q4_1 ,256 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1752#if 1 1753return repack_q4_0_to_q4_1_256_32_bl_ref (t ,32 ,data ,data_size ); 1754#else 1755return repack_q4_1_to_q4_1_256_32_bl (t ,32 ,data ,data_size ); 1756#endif 1757} 1758 1759template <> int repack < block_q4_K ,32 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1760return repack_q4_k_to_q4_1_32_bl (t ,32 ,data ,data_size ); 1761} 1762 1763template <> int repack < block_q6_K ,32 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1764#if 1 1765return repack_q6_k_to_q8_0_32_bl_ref (t ,32 ,data ,data_size ); 1766#else 1767return repack_q6_k_to_q8_0_32_bl (t ,32 ,data ,data_size ); 1768#endif 1769} 1770 1771template <> int repack < block_q8_0 ,32 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1772#if 1 1773return repack_q8_0_to_q8_0_32_bl_ref (t ,32 ,data ,data_size ); 1774#else 1775return repack_q8_0_to_q8_0_32_bl (t ,32 ,data ,data_size ); 1776#endif 1777} 1778 1779template <> int repack < block_mxfp4 ,32 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1780return repack_mxfp4_to_mxfp4_32_bl (t ,32 ,data ,data_size ); 1781} 1782 1783template <> int repack < block_q5_0 ,32 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1784return repack_q5_0_to_q5_0_32_bl (t ,32 ,data ,data_size ); 1785} 1786 1787template <> int repack < block_q5_1 ,32 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1788return repack_q5_1_to_q5_1_32_bl (t ,32 ,data ,data_size ); 1789} 1790 1791template <> int repack < block_q5_K ,32 ,32 > (ggml_tensor * t ,const void * data ,size_t data_size ) { 1792return repack_q5_k_to_q5_1_32_bl (t ,32 ,data ,data_size ); 1793} 1794 1795}// namespace ggml::cpu::riscv64_spacemit