char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
08659901c
char/aliceai-t5-moe
1#define GGML_COMMON_IMPL_CPP 2#define GGML_COMMON_DECL_CPP 3 4#include "ime.h" 5 6#include "binary-ops.h" 7#include "common.h" 8#include "ggml-backend-impl.h" 9#include "ggml-common.h" 10#include "ggml-cpu.h" 11#include "ime_env.h" 12#include "ime_kernels.h" 13#include "ops.h" 14#include "repack.h" 15#include "rvv_kernels.h" 16#include "spine_mem_pool.h" 17#include "traits.h" 18#include "vec.h" 19 20#include <fcntl.h> 21#include <sys/mman.h> 22#include <unistd.h> 23 24#include <algorithm> 25#include <atomic> 26#include <cassert> 27#include <cerrno> 28#include <cmath> 29#include <cstdio> // for GGML_ASSERT 30#include <stdexcept> 31#include <thread> 32// clang-format off 33#if defined(__riscv ) 34 35#if !defined(__riscv_v )|| !defined(__riscv_v_intrinsic ) 36#error "riscv v extension or v_intrinsic not enabled" 37#else 38#include <riscv_vector.h> 39#endif 40 41#if !defined(__riscv_zfh )|| !defined(__riscv_zvfh ) 42#error "riscv zfh extension not enabled, GGML_RV_ZFH and GGML_RV_ZVFH must be defined to 1" 43#endif 44 45#if !defined(__riscv_zba ) 46#error "riscv zba extension not enabled, GGML_RV_ZBA must be defined to 1" 47#endif 48 49#if defined(RISCV64_SPACEMIT_IME1 )|| defined(RISCV64_SPACEMIT_IME2 ) 50#else 51#error "RISCV64_SPACEMIT_IME1 or RISCV64_SPACEMIT_IME2 not defined" 52#endif 53 54#else 55 56#error "riscv not enabled in this build" 57 58#endif 59 60#if defined(__GNUC__ ) 61#pragma GCC diagnostic ignored "-Woverlength-strings" 62#pragma GCC diagnostic ignored "-Wcast-qual" 63#pragma GCC diagnostic ignored "-Wunused-parameter" 64#endif 65 66// clang-format on 67 68extern "C" { 69extern void ggml_threadpool_chunk_set (struct ggml_threadpool * tp ,int value ); 70extern int ggml_threadpool_chunk_add (struct ggml_threadpool * tp ,int value ); 71} 72 73namespace ggml::cpu::riscv64_spacemit { 74 75struct TLSContext { 76int cpu_id {-1 }; 77cpu_set_t cpuset ; 78void * tcm_buffer {nullptr }; 79size_t tcm_buffer_size {0 }; 80}; 81 82thread_localTLSContext tls_context ; 83 84template < typename BLOC_TYPE ,int64_t INTER_SIZE ,int64_t NB_COLS > constexpr size_t get_repacked_block_type_size () { 85if constexpr (std::is_same_v < BLOC_TYPE ,block_q6_K > || std::is_same_v < BLOC_TYPE ,block_q8_0 > ) { 86return sizeof (block_q8_0 ); 87 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q4_0 > ) { 88return sizeof (block_q4_0 )* INTER_SIZE /QK4_0 ; 89 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q4_1 > || std::is_same_v < BLOC_TYPE ,block_q4_K > ) { 90return (sizeof (block_q4_0 )+ sizeof (uint8_t ))* INTER_SIZE /QK4_1 ; 91 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q2_K > ) { 92return sizeof (spacemit_kernels::nrow_block_q2_k < 1 > ); 93 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q3_K > ) { 94return sizeof (spacemit_kernels::nrow_block_q3_k < 1 > ); 95 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_mxfp4 > ) { 96return sizeof (spacemit_kernels::nrow_block_mxfp4 < 1 > ); 97 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q5_1 > || std::is_same_v < BLOC_TYPE ,block_q5_K > ) { 98return sizeof (spacemit_kernels::nrow_block_q5_1 < 1 > ); 99 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q5_0 > ) { 100return sizeof (spacemit_kernels::nrow_block_q5_0 < 1 > ); 101 }else { 102assert (false); 103return 0 ; 104 } 105} 106 107template < typename BLOC_TYPE > constexpr bool block_type_has_zp () { 108if constexpr (std::is_same_v < BLOC_TYPE ,block_q6_K > || std::is_same_v < BLOC_TYPE ,block_q8_0 > || 109 std::is_same_v < BLOC_TYPE ,block_q3_K > || std::is_same_v < BLOC_TYPE ,block_q4_0 > || 110 std::is_same_v < BLOC_TYPE ,block_mxfp4 > || std::is_same_v < BLOC_TYPE ,block_q5_0 > ) { 111return false; 112 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q4_1 > || std::is_same_v < BLOC_TYPE ,block_q4_K > || 113 std::is_same_v < BLOC_TYPE ,block_q2_K > || std::is_same_v < BLOC_TYPE ,block_q5_1 > || 114 std::is_same_v < BLOC_TYPE ,block_q5_K > ) { 115return true; 116 }else { 117assert (false); 118return false; 119 } 120} 121 122class tensor_traits_base :public ggml::cpu::tensor_traits { 123public : 124virtual int repack (ggml_tensor * t ,const void * data ,size_t data_size )= 0 ; 125}; 126 127template < typename BLOC_TYPE ,int64_t INTER_SIZE ,int64_t NB_COLS > class tensor_traits :public tensor_traits_base { 128bool work_size (int /* n_threads */ ,const ggml_tensor * op ,size_t & size )override { 129switch (op -> op ) { 130case GGML_OP_MUL_MAT : 131 { 132int64_t src1_nelements = ggml_nelements (op -> src [1 ]); 133 134if constexpr (std::is_same_v < BLOC_TYPE ,block_q2_K > || std::is_same_v < BLOC_TYPE ,block_q3_K > ) { 135size = 136 spacemit_kernels::div_round_up (src1_nelements ,QK_K )* spacemit_kernels::q8k_blk_size (QK_K ); 137 }else if constexpr (INTER_SIZE == QK4_0 ) { 138size = spacemit_kernels::div_round_up (src1_nelements ,QK4_0 )* 139 spacemit_kernels::q8_blk_size (QK4_0 , true); 140 }else if constexpr (INTER_SIZE == 256 ) { 141size = spacemit_kernels::div_round_up (src1_nelements ,256 )* 142 spacemit_kernels::q8_hp_blk_size (256 , true, true); 143 }else { 144GGML_ABORT ("unsupported block type" ); 145 } 146 147size = GGML_PAD (size ,sizeof (int64_t )); 148 149return true; 150 } 151case GGML_OP_MUL_MAT_ID : 152 { 153int64_t src1_nelements = ggml_nelements (op -> src [1 ]); 154 155if constexpr (std::is_same_v < BLOC_TYPE ,block_q2_K > || std::is_same_v < BLOC_TYPE ,block_q3_K > ) { 156size = 157 spacemit_kernels::div_round_up (src1_nelements ,QK_K )* spacemit_kernels::q8k_blk_size (QK_K ); 158 }else if constexpr (INTER_SIZE == QK4_0 ) { 159size = spacemit_kernels::div_round_up (src1_nelements ,QK4_0 )* 160 spacemit_kernels::q8_blk_size (QK4_0 , true); 161 }else if constexpr (INTER_SIZE == 256 ) { 162size = spacemit_kernels::div_round_up (src1_nelements ,256 )* 163 spacemit_kernels::q8_hp_blk_size (256 , true, true); 164 }else { 165GGML_ABORT ("unsupported block type" ); 166 } 167 168size = GGML_PAD (size ,sizeof (int64_t )); 169 170const int64_t ne02 = op -> src [0 ]-> ne [2 ];// n_as, n_expert 171const int64_t ne12 = op -> src [1 ]-> ne [2 ];// n_tokens 172 173const size_t sizeof_mmid_row_mapping = sizeof (int64_t ); 174size += sizeof_mmid_row_mapping * ne02 * (ne12 + 1 )+ (ne02 + 1 )* sizeof (int64_t ); 175 176size = GGML_PAD (size ,sizeof (int64_t )); 177 178return true; 179 } 180default : 181// GGML_ABORT("fatal error"); 182break ; 183 } 184return false; 185 } 186 187bool compute_forward (ggml_compute_params * params ,ggml_tensor * op )override { 188switch (op -> op ) { 189case GGML_OP_MUL_MAT : 190switch (op -> src [0 ]-> type ) { 191case GGML_TYPE_Q2_K : 192case GGML_TYPE_Q3_K : 193case GGML_TYPE_Q4_0 : 194case GGML_TYPE_Q4_1 : 195case GGML_TYPE_Q4_K : 196case GGML_TYPE_Q6_K : 197case GGML_TYPE_Q8_0 : 198case GGML_TYPE_Q5_0 : 199case GGML_TYPE_Q5_1 : 200case GGML_TYPE_Q5_K : 201//case GGML_TYPE_MXFP4: 202forward_mul_mat (params ,op ); 203return true; 204default : 205// GGML_ABORT("fatal error: unsupported type for src0 in MUL_MAT"); 206return false; 207 } 208break ; 209case GGML_OP_MUL_MAT_ID : 210switch (op -> src [0 ]-> type ) { 211case GGML_TYPE_Q2_K : 212case GGML_TYPE_Q3_K : 213case GGML_TYPE_Q4_0 : 214case GGML_TYPE_Q4_1 : 215case GGML_TYPE_Q4_K : 216case GGML_TYPE_Q6_K : 217case GGML_TYPE_Q8_0 : 218case GGML_TYPE_Q5_0 : 219case GGML_TYPE_Q5_1 : 220case GGML_TYPE_Q5_K : 221//case GGML_TYPE_MXFP4: 222forward_mul_mat_id (params ,op ); 223return true; 224default : 225// GGML_ABORT("fatal error: unsupported type for src0 in MUL_MAT_ID"); 226return false; 227 } 228break ; 229default : 230// GGML_ABORT("fatal error"); 231break ; 232 } 233return false; 234 } 235 236void forward_mul_mat (ggml_compute_params * params ,ggml_tensor * op ) { 237constexpr size_t a_blk_len = INTER_SIZE ; 238constexpr size_t b_blk_len = INTER_SIZE ; 239 240const ggml_tensor * src0 = op -> src [0 ]; 241const ggml_tensor * src1 = op -> src [1 ]; 242ggml_tensor * dst = op ; 243 244GGML_TENSOR_BINARY_OP_LOCALS 245 246int ith = params -> ith ; 247int nth = params -> nth ; 248 249 [[maybe_unused ]]const enum ggml_type type = src0 -> type ; 250 251void * w_data = (void * )src0 -> data ; 252const float * feature = (const float * )src1 -> data ; 253float * output = (float * )dst -> data ; 254 255const int64_t gemm_m = ne11 * ne12 * ne13 ; 256const int64_t gemm_k = ne10 ; 257const int64_t gemm_n = ne01 ; 258 259 spacemit_kernels::quantize_a_row_def quantize_a_row_i8 ; 260 spacemit_kernels::quantize_a_row_def quantize_a_4row_i8 ; 261 spacemit_kernels::gemm_kernel_quantize_def gemm_kernel ; 262bool set_kernel_impl = false; 263 264int64_t block_stride_a = spacemit_kernels::q8_blk_size (a_blk_len ); 265 266#if defined(RISCV64_SPACEMIT_IME2 ) 267if (!set_kernel_impl && (global_spine_env_info .use_ime2 )) { 268quantize_a_row_i8 = spacemit_kernels::rvv::quantize_a_row_i8 ; 269quantize_a_4row_i8 = spacemit_kernels::rvv::quantize_a_4row_i8 ; 270block_stride_a = spacemit_kernels::q8_blk_size (a_blk_len , true); 271 272if constexpr (std::is_same_v < BLOC_TYPE ,block_q6_K > || std::is_same_v < BLOC_TYPE ,block_q8_0 > ) { 273gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i8 ; 274set_kernel_impl = true; 275 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q4_0 > || std::is_same_v < BLOC_TYPE ,block_q4_1 > || 276 std::is_same_v < BLOC_TYPE ,block_q4_K > ) { 277if constexpr (INTER_SIZE == 256 ) { 278gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i4_hp ; 279quantize_a_row_i8 = spacemit_kernels::rvv::quantize_a_row_i8_hp ; 280quantize_a_4row_i8 = spacemit_kernels::rvv::quantize_a_4row_i8_hp ; 281block_stride_a = spacemit_kernels::q8_hp_blk_size (a_blk_len , true, true); 282set_kernel_impl = true; 283 }else { 284gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i4 ; 285quantize_a_row_i8 = spacemit_kernels::rvv::quantize_a_row_i8 ; 286quantize_a_4row_i8 = spacemit_kernels::rvv::quantize_a_4row_i8 ; 287block_stride_a = spacemit_kernels::q8_blk_size (a_blk_len , true); 288set_kernel_impl = true; 289 } 290 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q2_K > ) { 291quantize_a_row_i8 = spacemit_kernels::rvv::quantize_a_row_i8k ; 292quantize_a_4row_i8 = spacemit_kernels::rvv::quantize_a_4row_i8k ; 293block_stride_a = spacemit_kernels::q8k_blk_size (a_blk_len ); 294 295gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i2k ; 296set_kernel_impl = true; 297 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q3_K > ) { 298quantize_a_row_i8 = spacemit_kernels::rvv::quantize_a_row_i8k ; 299quantize_a_4row_i8 = spacemit_kernels::rvv::quantize_a_4row_i8k ; 300block_stride_a = spacemit_kernels::q8k_blk_size (a_blk_len ); 301 302gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i3k ; 303set_kernel_impl = true; 304 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_mxfp4 > ) { 305gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8mxfp4 ; 306set_kernel_impl = true; 307 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q5_1 > || std::is_same_v < BLOC_TYPE ,block_q5_K > || 308 std::is_same_v < BLOC_TYPE ,block_q5_0 > ) { 309gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i5 ; 310set_kernel_impl = true; 311 } 312 } 313#endif 314 315#if defined(RISCV64_SPACEMIT_IME1 ) 316if (!set_kernel_impl && (global_spine_env_info .use_ime1 )) { 317quantize_a_row_i8 = spacemit_kernels::ime1::quantize_a_row_i8 ; 318quantize_a_4row_i8 = spacemit_kernels::ime1::quantize_a_4row_i8 ; 319 320if constexpr (std::is_same_v < BLOC_TYPE ,block_q4_0 > || std::is_same_v < BLOC_TYPE ,block_q4_1 > || 321 std::is_same_v < BLOC_TYPE ,block_q4_K > ) { 322gemm_kernel = spacemit_kernels::ime1::gemm_kernel_i8i4 ; 323set_kernel_impl = true; 324 } 325 } 326#endif 327if (!set_kernel_impl ) { 328GGML_ABORT ("no kernel implementation found for the block type" ); 329 } 330 331const int64_t a_k_blks = spacemit_kernels::div_round_up (gemm_k ,a_blk_len ); 332const int64_t b_k_blks = spacemit_kernels::div_round_up (gemm_k ,b_blk_len ); 333 334const int64_t row_stride_a = a_k_blks * block_stride_a ; 335const int64_t gemm_workspace_size = GGML_PAD (gemm_m * row_stride_a , alignof(int64_t )); 336 337if (ith == 0 && params -> wsize < gemm_workspace_size ) { 338GGML_ABORT ("wsize less than gemm_workspace_size" ); 339 } 340 341uintptr_t ws_ptr = reinterpret_cast < uintptr_t > (params -> wdata ); 342 343void * tcm_buffer = ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer ; 344const int64_t tcm_buffer_size = ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer_size ; 345 346auto * quant_a_buffer = reinterpret_cast < uint8_t *> (ws_ptr ); 347 348constexpr int64_t row_align = 4 ; 349const int64_t row_blks = spacemit_kernels::div_round_up (gemm_m ,row_align ); 350 351const int64_t row_stride_b = b_k_blks * get_repacked_block_type_size < BLOC_TYPE ,INTER_SIZE ,NB_COLS > (); 352const int64_t per_mb_rows_wsize = row_align * row_stride_a ; 353const int64_t per_nb_cols_wsize = NB_COLS * row_stride_b ; 354 355const int64_t barrier_idx = static_cast < int64_t > (ith /2 ); 356 357GGML_ASSERT (global_spine_env_info .init_barrier != nullptr ); 358GGML_ASSERT (barrier_idx < spine_init_barrier_count ); 359spine_barrier_t * cur_barrier = & global_spine_env_info .init_barrier [barrier_idx ]; 360 361if (gemm_m == 1 ) { 362int task_per_thread = spacemit_kernels::div_round_up (a_k_blks ,nth ); 363int a_blk_start = ith * task_per_thread ; 364int a_blk_end = std::min (a_blk_start + task_per_thread , (int )a_k_blks ); 365if (a_blk_start < a_blk_end ) { 366quantize_a_row_i8 (a_blk_len ,feature + a_blk_start * a_blk_len , (a_blk_end - a_blk_start )* a_blk_len , 367quant_a_buffer + a_blk_start * block_stride_a ); 368 } 369 }else { 370int task_per_thread = spacemit_kernels::div_round_up (row_blks ,nth ); 371int m_row_blk_start = ith * task_per_thread ; 372int m_row_blk_end = std::min (m_row_blk_start + task_per_thread , (int )row_blks ); 373for (int m_row_blk = m_row_blk_start ;m_row_blk < m_row_blk_end ;m_row_blk ++ ) { 374int m_idx = m_row_blk * row_align ; 375int rows_tobe_handled = (gemm_m - m_idx )> row_align ?row_align : (gemm_m - m_idx ); 376 377if (rows_tobe_handled == row_align && quantize_a_4row_i8 != nullptr ) { 378const float * a_row_ptr = feature + m_idx * gemm_k ; 379auto * quant_a_row_ptr = quant_a_buffer + m_idx * row_stride_a ; 380quantize_a_4row_i8 (a_blk_len ,a_row_ptr ,gemm_k ,quant_a_row_ptr ); 381 }else { 382while (rows_tobe_handled ) { 383const float * a_row_ptr = feature + m_idx * gemm_k ; 384auto * quant_a_row_ptr = quant_a_buffer + m_idx * row_stride_a ; 385quantize_a_row_i8 (a_blk_len ,a_row_ptr ,gemm_k ,quant_a_row_ptr ); 386rows_tobe_handled -= 1 ; 387m_idx += 1 ; 388 } 389 } 390 } 391 } 392 393ggml_barrier (params -> threadpool ); 394 395const int64_t gemm_m_stride = gemm_n /gemm_m > 64 ?gemm_m :16 ; 396const int64_t gemm_m_blocked = spacemit_kernels::div_round_up (gemm_m ,gemm_m_stride ); 397const int64_t max_gemm_n_stride = spacemit_kernels::div_round_up (gemm_n * gemm_m_blocked ,nth ); 398 399int64_t gemm_n_stride = gemm_n ; 400if (max_gemm_n_stride < gemm_n ) { 401gemm_n_stride = 402 std::min (gemm_n_stride , spacemit_kernels::div_round_up (max_gemm_n_stride ,NB_COLS )* NB_COLS ); 403 } 404 405if (gemm_n_stride == gemm_n && tcm_buffer != nullptr && per_mb_rows_wsize <=tcm_buffer_size ) { 406for (int64_t m_start = ith * row_align ;m_start < gemm_m ;m_start += row_align * nth ) { 407uint8_t * b_col = reinterpret_cast < uint8_t *> (w_data ); 408uint8_t * b_col_zp = block_type_has_zp < BLOC_TYPE > () ?b_col :nullptr ; 409 410int64_t m_row_real = std::min (gemm_m - m_start ,row_align ); 411 412 spacemit_kernels::rvv::memcpy1d (tcm_buffer ,quant_a_buffer + m_start * row_stride_a , 413m_row_real * row_stride_a ); 414 415int64_t n_blk_real = 0 ; 416for (int64_t ni = 0 ;ni < gemm_n ;ni += n_blk_real ,b_col += n_blk_real * row_stride_b ) { 417n_blk_real = std::min (gemm_n - ni , (int64_t )NB_COLS ); 418 419uint8_t * a_row_ptr = (uint8_t * )tcm_buffer ; 420float * c_blk = output + m_start * gemm_n + ni ; 421 422int32_t rows_remaining = m_row_real ; 423 424while (rows_remaining > 0 ) { 425auto rows_handled = gemm_kernel (b_blk_len ,a_row_ptr ,b_col ,b_col_zp ,c_blk ,rows_remaining , 426n_blk_real ,b_k_blks ,gemm_n ); 427 428c_blk += rows_handled * gemm_n ; 429a_row_ptr += rows_handled * row_stride_a ; 430 431rows_remaining -= rows_handled ; 432 } 433 } 434 } 435 }else if (tcm_buffer != nullptr && per_nb_cols_wsize <=tcm_buffer_size ) { 436uint8_t * a_row = quant_a_buffer ; 437uint8_t * b_col = reinterpret_cast < uint8_t *> (tcm_buffer ); 438if ((gemm_workspace_size + per_nb_cols_wsize ) <=tcm_buffer_size ) { 439a_row = (uint8_t * )tcm_buffer ; 440b_col = reinterpret_cast < uint8_t *> (tcm_buffer )+ gemm_workspace_size ; 441 } 442uint8_t * b_col_zp = block_type_has_zp < BLOC_TYPE > () ?b_col :nullptr ; 443 444int64_t ni = ith * NB_COLS ; 445int64_t nb_real = std::min (gemm_n - ni ,NB_COLS ); 446 447if (ith %2 == 0 && nb_real > 0 ) { 448 spacemit_kernels::rvv::memcpy1d (b_col ,reinterpret_cast < uint8_t *> (w_data )+ ni * row_stride_b , 449nb_real * row_stride_b ); 450if (a_row != quant_a_buffer ) { 451 spacemit_kernels::rvv::memcpy1d (a_row ,quant_a_buffer ,gemm_workspace_size ); 452 } 453 } 454 455spine_barrier_wait (cur_barrier ); 456 457if (ith %2 != 0 && nb_real > 0 ) { 458if (a_row != quant_a_buffer ) { 459 spacemit_kernels::rvv::memcpy1d (a_row ,quant_a_buffer ,gemm_workspace_size ); 460 } 461 spacemit_kernels::rvv::memcpy1d (b_col ,reinterpret_cast < uint8_t *> (w_data )+ ni * row_stride_b , 462nb_real * row_stride_b ); 463 } 464 465for (;ni < gemm_n ;ni += NB_COLS * nth ) { 466int64_t rows_remaining = gemm_m ; 467float * c_blk = output + ni ; 468auto * a_row_cur = a_row ; 469 470if (ith %2 != 0 ) { 471spine_barrier_wait (cur_barrier ); 472 } 473 474while (rows_remaining > 0 ) { 475auto rows_handled = gemm_kernel (b_blk_len ,a_row_cur ,b_col ,b_col_zp ,c_blk ,rows_remaining , 476nb_real ,b_k_blks ,gemm_n ); 477 478c_blk += rows_handled * gemm_n ; 479a_row_cur += rows_handled * row_stride_a ; 480 481rows_remaining -= rows_handled ; 482 } 483 484if (ith %2 == 0 ) { 485spine_barrier_wait (cur_barrier ); 486 } 487 488const int64_t next_ni = ni + NB_COLS * nth ; 489if (next_ni < gemm_n ) { 490nb_real = std::min (gemm_n - next_ni ,NB_COLS ); 491 spacemit_kernels::rvv::memcpy1d (b_col ,reinterpret_cast < uint8_t *> (w_data )+ next_ni * row_stride_b , 492nb_real * row_stride_b ); 493 } 494 } 495 }else { 496const int64_t task_count_m = spacemit_kernels::div_round_up (gemm_m ,gemm_m_stride ); 497const int64_t task_count_n = spacemit_kernels::div_round_up (gemm_n ,gemm_n_stride ); 498 499int64_t task_count = task_count_m * task_count_n ; 500int64_t task_per_thread = (task_count + nth - 1 ) /nth ; 501int64_t start = ith * task_per_thread ; 502int64_t end = std::min ((ith + 1 )* task_per_thread ,task_count ); 503for (int64_t compute_idx = start ;compute_idx < end ;compute_idx ++ ) { 504const auto tid_n = compute_idx /task_count_m ; 505const auto tid_m = compute_idx %task_count_m ; 506 507const int64_t m_start = tid_m * gemm_m_stride ; 508const int64_t m_count = std::min (gemm_m - m_start , (int64_t )gemm_m_stride ); 509 510const int64_t n_start = tid_n * gemm_n_stride ; 511const int64_t n_count = std::min (gemm_n - n_start , (int64_t )gemm_n_stride ); 512 513const int64_t n_blk = m_count == 1 ?n_count :NB_COLS ; 514 515uint8_t * b_col = reinterpret_cast < uint8_t *> (w_data )+ n_start * row_stride_b ; 516uint8_t * b_col_zp = block_type_has_zp < BLOC_TYPE > () ?b_col :nullptr ; 517 518int64_t n_blk_real = 0 ; 519for (int64_t ni = 0 ;ni < n_count ;ni += n_blk_real ,b_col += n_blk_real * row_stride_b ) { 520n_blk_real = std::min (n_count - ni ,n_blk ); 521 522uint8_t * a_row = quant_a_buffer + m_start * row_stride_a ; 523 524float * c_blk = output + m_start * gemm_n + n_start + ni ; 525 526int64_t rows_remaining = m_count ; 527 528uint8_t * b_col_cur = b_col ; 529uint8_t * b_col_zp_cur = b_col_zp ; 530 531while (rows_remaining > 0 ) { 532auto rows_handled = gemm_kernel (b_blk_len ,a_row ,b_col_cur ,b_col_zp_cur ,c_blk , 533rows_remaining ,n_blk_real ,b_k_blks ,gemm_n ); 534 535c_blk += rows_handled * gemm_n ; 536a_row += rows_handled * row_stride_a ; 537 538rows_remaining -= rows_handled ; 539 } 540 } 541 } 542 } 543 } 544 545void forward_mul_mat_id (ggml_compute_params * params ,ggml_tensor * op ) { 546constexpr size_t a_blk_len = INTER_SIZE ; 547constexpr size_t b_blk_len = INTER_SIZE ; 548 549const ggml_tensor * src0 = op -> src [0 ]; 550const ggml_tensor * src1 = op -> src [1 ]; 551const ggml_tensor * ids = op -> src [2 ]; 552ggml_tensor * dst = op ; 553 554GGML_TENSOR_BINARY_OP_LOCALS 555 556int ith = params -> ith ; 557int nth = params -> nth ; 558 559// row groups 560const int n_ids = ids -> ne [0 ];// n_expert_used 561const int n_as = ne02 ;// n_expert 562 563struct mmid_row_mapping { 564int32_t i1 ; 565int32_t i2 ; 566 }; 567 568 spacemit_kernels::quantize_a_row_def quantize_a_row_i8 ; 569 spacemit_kernels::gemm_kernel_quantize_def gemm_kernel ; 570 spacemit_kernels::moe_gemm_kernel_quantize_def moe_gemm_kernel_m2 ; 571bool set_kernel_impl = false; 572size_t block_stride_a = spacemit_kernels::q8_blk_size (QK4_0 ); 573 574#if defined(RISCV64_SPACEMIT_IME2 ) 575if (!set_kernel_impl && (global_spine_env_info .use_ime2 )) { 576quantize_a_row_i8 = spacemit_kernels::rvv::quantize_a_row_i8 ; 577block_stride_a = spacemit_kernels::q8_blk_size (QK4_0 , true); 578 579if constexpr (std::is_same_v < BLOC_TYPE ,block_q6_K > || std::is_same_v < BLOC_TYPE ,block_q8_0 > ) { 580gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i8 ; 581set_kernel_impl = true; 582 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q4_0 > || std::is_same_v < BLOC_TYPE ,block_q4_1 > || 583 std::is_same_v < BLOC_TYPE ,block_q4_K > ) { 584if constexpr (INTER_SIZE == 256 ) { 585gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i4_hp ; 586quantize_a_row_i8 = spacemit_kernels::rvv::quantize_a_row_i8_hp ; 587block_stride_a = spacemit_kernels::q8_hp_blk_size (a_blk_len , true, true); 588set_kernel_impl = true; 589 }else { 590gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i4 ; 591moe_gemm_kernel_m2 = spacemit_kernels::ime2::moe_m2_gemm_kernel_i8i4 ; 592quantize_a_row_i8 = spacemit_kernels::rvv::quantize_a_row_i8 ; 593block_stride_a = spacemit_kernels::q8_blk_size (a_blk_len , true); 594set_kernel_impl = true; 595 } 596 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q2_K > ) { 597quantize_a_row_i8 = spacemit_kernels::rvv::quantize_a_row_i8k ; 598block_stride_a = spacemit_kernels::q8k_blk_size (a_blk_len ); 599gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i2k ; 600set_kernel_impl = true; 601 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q3_K > ) { 602quantize_a_row_i8 = spacemit_kernels::rvv::quantize_a_row_i8k ; 603block_stride_a = spacemit_kernels::q8k_blk_size (a_blk_len ); 604gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i3k ; 605set_kernel_impl = true; 606 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_mxfp4 > ) { 607gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8mxfp4 ; 608moe_gemm_kernel_m2 = spacemit_kernels::ime2::moe_m2_gemm_kernel_i8mxfp4 ; 609set_kernel_impl = true; 610 }else if constexpr (std::is_same_v < BLOC_TYPE ,block_q5_1 > || std::is_same_v < BLOC_TYPE ,block_q5_K > || 611 std::is_same_v < BLOC_TYPE ,block_q5_0 > ) { 612gemm_kernel = spacemit_kernels::ime2::gemm_kernel_i8i5 ; 613moe_gemm_kernel_m2 = spacemit_kernels::ime2::moe_m2_gemm_kernel_i8i5 ; 614set_kernel_impl = true; 615 } 616 } 617#endif 618 619#if defined(RISCV64_SPACEMIT_IME1 ) 620if (!set_kernel_impl && (global_spine_env_info .use_ime1 )) { 621quantize_a_row_i8 = spacemit_kernels::ime1::quantize_a_row_i8 ; 622 623if constexpr (std::is_same_v < BLOC_TYPE ,block_q4_0 > || std::is_same_v < BLOC_TYPE ,block_q4_1 > || 624 std::is_same_v < BLOC_TYPE ,block_q4_K > ) { 625gemm_kernel = spacemit_kernels::ime1::gemm_kernel_i8i4 ; 626set_kernel_impl = true; 627 } 628 } 629#endif 630if (!set_kernel_impl ) { 631GGML_ABORT ("no kernel implementation found for the block type" ); 632 } 633 634const size_t a_k_blks = spacemit_kernels::div_round_up (ne10 ,a_blk_len ); 635const size_t b_k_blks = spacemit_kernels::div_round_up (ne10 ,b_blk_len ); 636 637const size_t nbw1 = a_k_blks * block_stride_a ; 638const size_t nbw2 = ne11 * nbw1 ; 639const size_t nbw3 = nbw2 * ne12 ; 640const size_t gemm_workspace_size = GGML_PAD (nbw3 , alignof(int64_t )); 641 642const uintptr_t ws_ptr = reinterpret_cast < uintptr_t > (params -> wdata ); 643auto * quant_a_buffer = reinterpret_cast < uint8_t *> (ws_ptr ); 644 645if (ne11 == 1 ) { 646for (int64_t ii = ith ;ii < ne12 * a_k_blks ;ii += nth ) { 647int64_t i12 = ii /a_k_blks ; 648int64_t ak_blk_id = ii %a_k_blks ; 649quantize_a_row_i8 (a_blk_len , (float * ) ((char * )src1 -> data + i12 * nb12 )+ ak_blk_id * a_blk_len , 650a_blk_len ,quant_a_buffer + i12 * nbw2 + ak_blk_id * block_stride_a ); 651 } 652 }else { 653for (int64_t ii = ith ;ii < ne12 * ne11 ;ii += nth ) { 654int64_t i12 = ii /ne11 ; 655int64_t i11 = ii %ne11 ; 656quantize_a_row_i8 (a_blk_len , (float * ) ((char * )src1 -> data + i12 * nb12 + i11 * nb11 ),ne10 , 657quant_a_buffer + i12 * nbw2 + i11 * nbw1 ); 658 } 659 } 660 661#define MMID_MATRIX_ROW (row_id ,i1 ) matrix_rows[(row_id) *ne12 + (i1)] 662 663int64_t * matrix_row_counts = (int64_t * ) (ws_ptr + gemm_workspace_size ); 664int32_t * valid_ep_count = (int32_t * ) (matrix_row_counts + n_as ); 665int32_t * valid_act_count = (int32_t * ) (valid_ep_count + 1 ); 666int64_t * valid_matrix_row_counts = (int64_t * ) (valid_act_count + 1 ); 667mmid_row_mapping * matrix_rows = (mmid_row_mapping * ) (valid_matrix_row_counts + n_as ); 668 669if (ith == 0 ) { 670// initialize matrix_row_counts 671memset (matrix_row_counts ,0 ,n_as * sizeof (int64_t )); 672 673// group rows by src0 matrix 674for (int32_t iid1 = 0 ;iid1 < ids -> ne [1 ];++ iid1 ) { 675for (int32_t id = 0 ;id < n_ids ;++ id ) { 676const int32_t i02 = 677* (const int32_t * ) ((const char * )ids -> data + iid1 * ids -> nb [1 ]+ id * ids -> nb [0 ]); 678 679GGML_ASSERT (i02 >=0 && i02 < n_as ); 680 681MMID_MATRIX_ROW (i02 ,matrix_row_counts [i02 ])= {id ,iid1 }; 682matrix_row_counts [i02 ]+= 1 ; 683 } 684 } 685 686int32_t valid_ep_count_t = 0 ; 687int32_t valid_act_count_t = 0 ; 688for (int cur_a = 0 ;cur_a < n_as ;++ cur_a ) { 689const int64_t cne1 = matrix_row_counts [cur_a ]; 690if (cne1 == 0 ) { 691continue ; 692 } 693valid_matrix_row_counts [valid_ep_count_t ]= cur_a ; 694valid_act_count_t += cne1 ; 695valid_ep_count_t += 1 ; 696 } 697valid_ep_count [0 ]= valid_ep_count_t ; 698valid_act_count [0 ]= valid_act_count_t ; 699 } 700 701const int64_t barrier_idx = static_cast < int64_t > (ith /2 ); 702 703GGML_ASSERT (global_spine_env_info .init_barrier != nullptr ); 704GGML_ASSERT (barrier_idx < spine_init_barrier_count ); 705spine_barrier_t * cur_barrier = & global_spine_env_info .init_barrier [barrier_idx ]; 706 707ggml_barrier (params -> threadpool ); 708 709const size_t row_stride_b = b_k_blks * get_repacked_block_type_size < BLOC_TYPE ,INTER_SIZE ,NB_COLS > (); 710const size_t expert_b_stride = ne01 * row_stride_b ; 711const size_t per_nb_cols_wsize = NB_COLS * row_stride_b ; 712 713 std::array < const uint8_t * ,2 > src_workspaces ; 714 std::array < float * ,2 > dst_workspaces ; 715 716auto * tcm_buffer = ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer ; 717const auto tcm_buffer_size = ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer_size ; 718 719const auto valid_ep_count_t = valid_ep_count [0 ]; 720const auto valid_act_count_t = valid_act_count [0 ]; 721 722int nth_es = 1 ; 723int nth_n = nth ; 724 725int ith_es = ith %nth_es ; 726int ith_n = (ith /nth_es ) %nth_n ; 727 728if (valid_ep_count_t %nth == 0 && tcm_buffer != nullptr && valid_ep_count_t == n_as && 729valid_act_count_t == n_as && per_nb_cols_wsize <=tcm_buffer_size ) { 730for (int64_t valid_id = ith ;valid_id < valid_ep_count_t ;valid_id += nth ) { 731const int64_t cur_a = valid_matrix_row_counts [valid_id ]; 732 733auto * src0_cur = (uint8_t * )src0 -> data + cur_a * expert_b_stride ; 734 735mmid_row_mapping row_mapping = MMID_MATRIX_ROW (cur_a ,0 ); 736const int id = row_mapping .i1 ; 737const int64_t i11 = id %ne11 ; 738const int64_t i12 = row_mapping .i2 ; 739const int64_t i1 = id ; 740const int64_t i2 = i12 ; 741 742auto * src1_col = quant_a_buffer + (i11 * nbw1 + i12 * nbw2 ); 743float * c_blk = (float * ) ((char * )dst -> data + (i1 * nb1 + i2 * nb2 )); 744 745uint8_t * a_row = src1_col ; 746uint8_t * b_col = reinterpret_cast < uint8_t *> (tcm_buffer ); 747if ((nbw1 + per_nb_cols_wsize ) <=tcm_buffer_size ) { 748a_row = (uint8_t * )tcm_buffer ; 749b_col = reinterpret_cast < uint8_t *> (tcm_buffer )+ nbw1 ; 750 } 751uint8_t * b_col_zp = block_type_has_zp < BLOC_TYPE > () ?b_col :nullptr ; 752 753if (ith %2 == 0 ) { 754 spacemit_kernels::rvv::memcpy1d (b_col ,reinterpret_cast < uint8_t *> (src0_cur ),per_nb_cols_wsize ); 755 756if (a_row != src1_col ) { 757 spacemit_kernels::rvv::memcpy1d (a_row ,src1_col ,nbw1 ); 758 } 759 } 760 761spine_barrier_wait (cur_barrier ); 762 763if (ith %2 != 0 ) { 764if (a_row != src1_col ) { 765 spacemit_kernels::rvv::memcpy1d (a_row ,src1_col ,nbw1 ); 766 } 767 768 spacemit_kernels::rvv::memcpy1d (b_col ,reinterpret_cast < uint8_t *> (src0_cur ),per_nb_cols_wsize ); 769 } 770 771int64_t nb_real = std::min (ne01 ,NB_COLS ); 772for (int64_t ni = 0 ;ni < ne01 ;ni += NB_COLS ) { 773if (ith %2 != 0 ) { 774spine_barrier_wait (cur_barrier ); 775 } 776 777gemm_kernel (b_blk_len ,a_row ,b_col ,b_col_zp ,c_blk + ni ,1 ,nb_real ,b_k_blks ,ne01 ); 778 779if (ith %2 == 0 ) { 780spine_barrier_wait (cur_barrier ); 781 } 782 783const int64_t next_ni = ni + NB_COLS ; 784if (next_ni < ne01 ) { 785nb_real = std::min (ne01 - next_ni ,NB_COLS ); 786 spacemit_kernels::rvv::memcpy1d ( 787b_col ,reinterpret_cast < uint8_t *> (src0_cur )+ next_ni * row_stride_b ,per_nb_cols_wsize ); 788 } 789 } 790 } 791 }else { 792for (int64_t valid_id = ith_es ;valid_id < valid_ep_count_t ;valid_id += nth_es ) { 793const int64_t cur_a = valid_matrix_row_counts [valid_id ]; 794const int64_t cne1 = matrix_row_counts [cur_a ]; 795 796int64_t src1_cur_start = 0 ; 797int64_t src1_cur_end = cne1 ; 798 799int64_t src0_cur_start = (ith_n * ne01 ) /nth_n ; 800int64_t src0_cur_end = MIN (((ith_n + 1 )* ne01 ) /nth_n ,ne01 ); 801 802if (src1_cur_start >=src1_cur_end || src0_cur_start >=src0_cur_end ) { 803continue ; 804 } 805 806src0_cur_start = 807 (src0_cur_start %NB_COLS ) ?src0_cur_start + NB_COLS - (src0_cur_start %NB_COLS ) :src0_cur_start ; 808src0_cur_end = 809 (src0_cur_end %NB_COLS ) ?src0_cur_end + NB_COLS - (src0_cur_end %NB_COLS ) :src0_cur_end ; 810 811auto * src0_cur = (uint8_t * )src0 -> data + cur_a * expert_b_stride + src0_cur_start * row_stride_b ; 812uint8_t * b_col_zp = block_type_has_zp < BLOC_TYPE > () ?src0_cur :nullptr ; 813 814size_t extra_tcm_buffer_size = tcm_buffer_size ; 815void * extra_tcm_buffer = tcm_buffer ; 816if (tcm_buffer != nullptr && (src1_cur_end - src1_cur_start ) >=4 && 817 (src0_cur_end - src0_cur_start )* row_stride_b <=tcm_buffer_size ) { 818 spacemit_kernels::rvv::memcpy1d (tcm_buffer ,src0_cur , 819 (src0_cur_end - src0_cur_start )* row_stride_b ); 820src0_cur = reinterpret_cast < uint8_t *> (tcm_buffer ); 821b_col_zp = block_type_has_zp < BLOC_TYPE > () ?src0_cur :nullptr ; 822extra_tcm_buffer_size -= (src0_cur_end - src0_cur_start )* row_stride_b ; 823extra_tcm_buffer = reinterpret_cast < void *> (reinterpret_cast < uintptr_t > (tcm_buffer )+ 824 (src0_cur_end - src0_cur_start )* row_stride_b ); 825 } 826 827int ir1 = src1_cur_start ; 828 829if (extra_tcm_buffer_size >=nbw1 && extra_tcm_buffer != nullptr ) { 830int64_t quant_a_tile_size = extra_tcm_buffer_size /nbw1 ; 831do { 832quant_a_tile_size = MIN (quant_a_tile_size ,src1_cur_end - ir1 ); 833 834uint8_t * quant_a_tile_buffer = reinterpret_cast < uint8_t *> (extra_tcm_buffer ); 835 836int iir1 = ir1 ; 837for (;iir1 < (ir1 + quant_a_tile_size );++ iir1 ) { 838mmid_row_mapping row_mapping = MMID_MATRIX_ROW (cur_a ,iir1 ); 839 840const int id = row_mapping .i1 ;// selected expert index 841 842const int64_t i11 = id %ne11 ; 843const int64_t i12 = row_mapping .i2 ;// row index in src1 844 845auto * src1_col = quant_a_buffer + (i11 * nbw1 + i12 * nbw2 ); 846 spacemit_kernels::rvv::memcpy1d (quant_a_tile_buffer ,src1_col ,nbw1 ); 847quant_a_tile_buffer = quant_a_tile_buffer + nbw1 ; 848 } 849 850quant_a_tile_buffer = reinterpret_cast < uint8_t *> (extra_tcm_buffer ); 851iir1 = ir1 ; 852 853if (moe_gemm_kernel_m2 != nullptr ) { 854for (;iir1 < (ir1 + quant_a_tile_size - 1 );iir1 += 2 ,quant_a_tile_buffer += 2 * nbw1 ) { 855mmid_row_mapping row_mapping_0 = MMID_MATRIX_ROW (cur_a ,iir1 ); 856mmid_row_mapping row_mapping_1 = MMID_MATRIX_ROW (cur_a ,iir1 + 1 ); 857 858src_workspaces [0 ]= quant_a_tile_buffer ; 859src_workspaces [1 ]= quant_a_tile_buffer + nbw1 ; 860 861dst_workspaces [0 ]= 862 (float * ) ((char * )dst -> data + (row_mapping_0 .i1 * nb1 + row_mapping_0 .i2 * nb2 ))+ 863src0_cur_start ; 864dst_workspaces [1 ]= (float * ) ((char * )dst -> data + 865 ((row_mapping_1 .i1 )* nb1 + (row_mapping_1 .i2 )* nb2 ))+ 866src0_cur_start ; 867moe_gemm_kernel_m2 (b_blk_len ,src_workspaces .data (),src0_cur ,b_col_zp , 868dst_workspaces .data (),1 ,src0_cur_end - src0_cur_start ,b_k_blks , 869ne01 ); 870 } 871 } 872 873for (;iir1 < (ir1 + quant_a_tile_size );iir1 ++ ,quant_a_tile_buffer += nbw1 ) { 874mmid_row_mapping row_mapping_0 = MMID_MATRIX_ROW (cur_a ,iir1 ); 875 876gemm_kernel ( 877b_blk_len ,quant_a_tile_buffer ,src0_cur ,b_col_zp , 878 (float * ) ((char * )dst -> data + (row_mapping_0 .i1 * nb1 + row_mapping_0 .i2 * nb2 ))+ 879src0_cur_start , 8801 ,src0_cur_end - src0_cur_start ,b_k_blks ,ne01 ); 881 } 882 883ir1 += quant_a_tile_size ; 884 }while (ir1 < src1_cur_end ); 885 }else { 886if (moe_gemm_kernel_m2 != nullptr ) { 887for (;ir1 < src1_cur_end - 1 ;ir1 += 2 ) { 888for (int iir1 = 0 ;iir1 < 2 ;++ iir1 ) { 889mmid_row_mapping row_mapping = MMID_MATRIX_ROW (cur_a ,ir1 + iir1 ); 890 891const int id = row_mapping .i1 ;// selected expert index 892 893const int64_t i11 = id %ne11 ; 894const int64_t i12 = row_mapping .i2 ;// row index in src1 895 896const int64_t i1 = id ;// selected expert index 897const int64_t i2 = i12 ;// row 898 899src_workspaces [iir1 ]= quant_a_buffer + (i11 * nbw1 + i12 * nbw2 ); 900 901dst_workspaces [iir1 ]= 902 (float * ) ((char * )dst -> data + (i1 * nb1 + i2 * nb2 ))+ src0_cur_start ; 903 } 904 905moe_gemm_kernel_m2 (b_blk_len ,src_workspaces .data (),src0_cur ,b_col_zp , 906dst_workspaces .data (),1 ,src0_cur_end - src0_cur_start ,b_k_blks ,ne01 ); 907 } 908 } 909 910for (;ir1 < src1_cur_end ;ir1 ++ ) { 911mmid_row_mapping row_mapping = MMID_MATRIX_ROW (cur_a ,ir1 ); 912 913const int id = row_mapping .i1 ;// selected expert index 914 915const int64_t i11 = id %ne11 ; 916const int64_t i12 = row_mapping .i2 ;// row index in src1 917 918const int64_t i1 = id ;// selected expert index 919const int64_t i2 = i12 ;// row 920 921auto * src1_col = quant_a_buffer + (i11 * nbw1 + i12 * nbw2 ); 922 923gemm_kernel (b_blk_len ,src1_col ,src0_cur ,b_col_zp , 924 (float * ) ((char * )dst -> data + (i1 * nb1 + i2 * nb2 ))+ src0_cur_start ,1 , 925src0_cur_end - src0_cur_start ,b_k_blks ,ne01 ); 926 } 927 } 928 } 929 } 930#undef MMID_MATRIX_ROW 931 } 932 933int repack (ggml_tensor * t ,const void * data ,size_t data_size )override { 934GGML_LOG_DEBUG ("%s: repack tensor %s with %s_%dx%d\n" ,__func__ ,t -> name ,ggml_type_name (t -> type ), 935 (int )NB_COLS , (int )INTER_SIZE ); 936return ggml::cpu::riscv64_spacemit::repack < BLOC_TYPE ,INTER_SIZE ,NB_COLS > (t ,data ,data_size ); 937 } 938}; 939 940class tensor_traits_common :public tensor_traits_base { 941bool work_size (int n_threads ,const ggml_tensor * op ,size_t & size )override { 942switch (op -> op ) { 943case GGML_OP_FLASH_ATTN_EXT : 944 { 945const int n_tasks = n_threads ; 946const int64_t neq2 = op -> src [0 ]-> ne [2 ];// number of query heads 947const int64_t DK = op -> src [1 ]-> ne [0 ]; 948const int64_t DV = op -> src [2 ]-> ne [0 ];// DV 949 950// Tiled flash attention scratch (tile sizes defined in common.h) 951// Per-thread: Q_q + KQ + mask + VKQ32 + V32 + K_f32 + padding 952size_t prefill = sizeof (float )* 953 (GGML_FA_TILE_Q * DK + 2 * GGML_FA_TILE_Q * GGML_FA_TILE_KV + GGML_FA_TILE_Q * DV + 954GGML_FA_TILE_KV * DV + GGML_FA_TILE_KV * DK )* 955n_tasks ; 956 957// Decode path: n_kv_chunks = n_tasks (one chunk per thread) 958// Per-thread: VKQ accmulator (DV), partial M, partial S + intra-thread scratch for V, Q and VKQ 959size_t n_chunks = n_tasks ; 960size_t decode = sizeof (float )* (neq2 * n_chunks * (2 + DV )+ n_tasks * (DK + 2 * DV )); 961 962size = MAX (prefill ,decode ); 963 } 964return true; 965default : 966break ; 967 } 968return false; 969 } 970 971bool compute_forward (ggml_compute_params * params ,ggml_tensor * op )override { 972switch (op -> op ) { 973case GGML_OP_NORM : 974switch (op -> src [0 ]-> type ) { 975case GGML_TYPE_F32 : 976 spacemit_kernels::rvv::forward_norm_f32 (params ,op ); 977return true; 978default : 979GGML_ABORT ("fatal error" ); 980 } 981case GGML_OP_RMS_NORM : 982switch (op -> src [0 ]-> type ) { 983case GGML_TYPE_F32 : 984 spacemit_kernels::rvv::forward_rms_norm_f32 (params ,op ); 985return true; 986default : 987GGML_ABORT ("fatal error" ); 988 } 989case GGML_OP_ADD : 990switch (op -> src [0 ]-> type ) { 991case GGML_TYPE_F32 : 992 spacemit_kernels::rvv::forward_binary < GGML_OP_ADD ,float > (params ,op ); 993return true; 994case GGML_TYPE_F16 : 995 spacemit_kernels::rvv::forward_binary < GGML_OP_ADD ,_Float16 > (params ,op ); 996return true; 997default : 998ggml_compute_forward_add (params ,op ); 999return true; 1000 } 1001case GGML_OP_SUB : 1002switch (op -> src [0 ]-> type ) { 1003case GGML_TYPE_F32 : 1004 spacemit_kernels::rvv::forward_binary < GGML_OP_SUB ,float > (params ,op ); 1005return true; 1006case GGML_TYPE_F16 : 1007 spacemit_kernels::rvv::forward_binary < GGML_OP_SUB ,_Float16 > (params ,op ); 1008return true; 1009default : 1010ggml_compute_forward_sub (params ,op ); 1011return true; 1012 } 1013case GGML_OP_MUL : 1014switch (op -> src [0 ]-> type ) { 1015case GGML_TYPE_F32 : 1016 spacemit_kernels::rvv::forward_binary < GGML_OP_MUL ,float > (params ,op ); 1017return true; 1018case GGML_TYPE_F16 : 1019 spacemit_kernels::rvv::forward_binary < GGML_OP_MUL ,_Float16 > (params ,op ); 1020return true; 1021default : 1022ggml_compute_forward_mul (params ,op ); 1023return true; 1024 } 1025case GGML_OP_DIV : 1026switch (op -> src [0 ]-> type ) { 1027case GGML_TYPE_F32 : 1028 spacemit_kernels::rvv::forward_binary < GGML_OP_DIV ,float > (params ,op ); 1029return true; 1030case GGML_TYPE_F16 : 1031 spacemit_kernels::rvv::forward_binary < GGML_OP_DIV ,_Float16 > (params ,op ); 1032return true; 1033default : 1034ggml_compute_forward_div (params ,op ); 1035return true; 1036 } 1037case GGML_OP_FLASH_ATTN_EXT : 1038forward_flash_attn_ext_f16 (params ,op ); 1039return true; 1040case GGML_OP_CONT : 1041 { 1042const ggml_tensor * src0 = op -> src [0 ]; 1043if (op -> type == src0 -> type && op -> nb [0 ]!= src0 -> nb [0 ]&& op -> nb [0 ]== src0 -> nb [1 ]&& 1044op -> ne [3 ]* op -> ne [2 ]* op -> nb [2 ]== src0 -> ne [3 ]* src0 -> ne [2 ]* src0 -> nb [2 ]) { 1045 spacemit_kernels::rvv::forward_cont_with_permute (params ,op ); 1046 }else { 1047ggml_compute_forward_cont (params ,op ); 1048 } 1049return true; 1050 } 1051case GGML_OP_CPY : 1052 { 1053const ggml_tensor * src0 = op -> src [0 ]; 1054if (op -> type == src0 -> type && op -> nb [0 ]== src0 -> nb [1 ]&& src0 -> nb [0 ]!= src0 -> nb [1 ]&& 1055ggml_nelements (src0 )== ggml_nelements (op )) { 1056 spacemit_kernels::rvv::forward_cpy_with_permute (params ,op ); 1057 }else { 1058ggml_compute_forward_cpy (params ,op ); 1059 } 1060return true; 1061 } 1062case GGML_OP_REPEAT : 1063 { 1064const bool rows_equal = ggml_nrows (op -> src [0 ])== ggml_nrows (op ); 1065const bool broadcast_or_equal = op -> src [0 ]-> ne [0 ]== 1 || op -> src [0 ]-> ne [0 ]== op -> ne [0 ]; 1066 1067if (rows_equal && broadcast_or_equal ) { 1068switch (op -> src [0 ]-> type ) { 1069case GGML_TYPE_F32 : 1070 spacemit_kernels::rvv::forward_repeat_nrows < int32_t > (params ,op ); 1071return true; 1072case GGML_TYPE_F16 : 1073 spacemit_kernels::rvv::forward_repeat_nrows < int16_t > (params ,op ); 1074return true; 1075default : 1076break ; 1077 } 1078 } 1079 1080if (op -> src [0 ]-> ne [1 ]== 1 && op -> src [0 ]-> ne [0 ]== op -> ne [0 ]) { 1081switch (op -> src [0 ]-> type ) { 1082case GGML_TYPE_F32 : 1083 spacemit_kernels::rvv::forward_repeat_dim1 < int32_t > (params ,op ); 1084return true; 1085case GGML_TYPE_F16 : 1086 spacemit_kernels::rvv::forward_repeat_dim1 < int16_t > (params ,op ); 1087return true; 1088default : 1089break ; 1090 } 1091 } 1092 1093ggml_compute_forward_repeat (params ,op ); 1094 } 1095return true; 1096case GGML_OP_SUM_ROWS : 1097 { 1098if (op -> src [0 ]-> type == GGML_TYPE_F32 && op -> type == GGML_TYPE_F32 ) { 1099 spacemit_kernels::rvv::forward_sum_rows < float > (params ,op ); 1100 }else { 1101ggml_compute_forward_sum_rows (params ,op ); 1102 } 1103 } 1104return true; 1105case GGML_OP_GET_ROWS : 1106 { 1107if (op -> src [0 ]-> type == op -> type ) { 1108switch (op -> src [0 ]-> type ) { 1109case GGML_TYPE_F32 : 1110 spacemit_kernels::rvv::forward_get_rows < int32_t > (params ,op ); 1111return true; 1112case GGML_TYPE_F16 : 1113 spacemit_kernels::rvv::forward_get_rows < int16_t > (params ,op ); 1114return true; 1115default : 1116break ; 1117 } 1118 } 1119 1120ggml_compute_forward_get_rows (params ,op ); 1121 } 1122return true; 1123case GGML_OP_CONCAT : 1124 { 1125const int32_t dim = ggml_get_op_params_i32 (op ,0 ); 1126if (dim == 0 && op -> type == op -> src [0 ]-> type ) { 1127switch (op -> src [0 ]-> type ) { 1128case GGML_TYPE_F32 : 1129 spacemit_kernels::rvv::forward_concat < int32_t > (params ,op ); 1130return true; 1131case GGML_TYPE_F16 : 1132 spacemit_kernels::rvv::forward_concat < int16_t > (params ,op ); 1133return true; 1134default : 1135break ; 1136 } 1137 } 1138 1139ggml_compute_forward_concat (params ,op ); 1140 } 1141return true; 1142// TODO For GGML_OP_GATED_DELTA_NET 1143// case GGML_OP_GATED_DELTA_NET: 1144// return true; 1145default : 1146break ; 1147 } 1148return false; 1149 } 1150 1151void forward_flash_attn_ext_f16 (const ggml_compute_params * params ,ggml_tensor * dst ) { 1152const ggml_tensor * q = dst -> src [0 ]; 1153const ggml_tensor * k = dst -> src [1 ]; 1154const ggml_tensor * v = dst -> src [2 ]; 1155 1156GGML_TENSOR_LOCALS (int64_t ,neq ,q ,ne ) 1157GGML_TENSOR_LOCALS (size_t ,nbq ,q ,nb ) 1158GGML_TENSOR_LOCALS (int64_t ,nek ,k ,ne ) 1159GGML_TENSOR_LOCALS (size_t ,nbk ,k ,nb ) 1160GGML_TENSOR_LOCALS (int64_t ,nev ,v ,ne ) 1161GGML_TENSOR_LOCALS (size_t ,nbv ,v ,nb ) 1162GGML_TENSOR_LOCALS (int64_t ,ne ,dst ,ne ) 1163GGML_TENSOR_LOCALS (size_t ,nb ,dst ,nb ) 1164 1165const int64_t DK = nek0 ; 1166const int64_t DV = nev0 ; 1167 1168const bool supported_prec = (dst -> op_params [3 ]== GGML_PREC_F32 || dst -> op_params [3 ]== GGML_PREC_DEFAULT ); 1169const bool supported_types = (q -> type == GGML_TYPE_F32 && k -> type == GGML_TYPE_F16 && v -> type == GGML_TYPE_F16 ); 1170const bool supported_shape = (DK > 0 && DK <=128 && DV > 0 && DV <=128 ); 1171const bool supported_vlen = (__riscv_vlenb ()== 128 ); 1172 1173if (!(supported_prec && supported_types && supported_shape && supported_vlen )) { 1174ggml_compute_forward_flash_attn_ext (params ,dst ); 1175return ; 1176 } 1177 1178// total rows in q 1179const int64_t nr = neq1 * neq2 * neq3 ; 1180 1181// rows per thread 1182const int ith = params -> ith ; 1183const int nth = params -> nth ; 1184 1185static constexpr int64_t Q_TILE_SZ = ggml_fa_tile_config::Q ; 1186const bool use_tiled = !params -> use_ref && (neq1 >=Q_TILE_SZ ); 1187 1188// 4x chunks per thread 1189// int nth_scaled = nth * 4; 1190// int64_t chunk_size = (nr + nth_scaled - 1) / nth_scaled; 1191// int64_t nchunk = (nr + chunk_size - 1) / chunk_size; 1192 1193// if (nth == 1 || nchunk < nth) { 1194// nchunk = nth; 1195// } 1196 1197int64_t nchunk = nth ; 1198 1199if (ith == 0 ) { 1200// Every thread starts at ith, so the first unprocessed chunk is nth. This save a bit of coordination right at the start. 1201ggml_threadpool_chunk_set (params -> threadpool ,nth ); 1202 } 1203 1204ggml_barrier (params -> threadpool ); 1205 1206// The number of elements in each chunk 1207const int64_t dr = (nr + nchunk - 1 ) /nchunk ; 1208 1209// The first chunk comes from our thread_id, the rest will get auto-assigned. 1210int current_chunk = ith ; 1211 1212while (current_chunk < nchunk ) { 1213const int64_t ir0 = dr * current_chunk ; 1214const int64_t ir1 = MIN (ir0 + dr ,nr ); 1215 1216if (use_tiled ) { 1217 spacemit_kernels::rvv::forward_flash_attn_ext_f16_tiled_vlen1024_vf16 ( 1218params ,dst ,ir0 ,ir1 , ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer , 1219 ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer_size ); 1220 }else { 1221 spacemit_kernels::rvv::forward_flash_attn_ext_f16_one_chunk_vlen1024_vf16 ( 1222params ,dst ,ir0 ,ir1 , ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer , 1223 ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer_size ); 1224 } 1225 1226current_chunk = ggml_threadpool_chunk_add (params -> threadpool ,1 ); 1227 } 1228 } 1229 1230int repack (ggml_tensor * t ,const void * data ,size_t data_size )override { 1231memcpy (t -> data ,data ,data_size ); 1232return 0 ; 1233 } 1234}; 1235 1236// Impl By IME1 1237static const tensor_traits < block_q4_0 ,32 ,16 > q4_0_16x32_q8_0 ; 1238static const tensor_traits < block_q4_1 ,32 ,16 > q4_1_16x32_q8_0 ; 1239static const tensor_traits < block_q4_K ,32 ,16 > q4_k_16x32_q8_0 ; 1240// Impl By IME2 1241static const tensor_traits < block_q2_K ,256 ,32 > q2_k_32x256_q8_0 ; 1242static const tensor_traits < block_q3_K ,256 ,32 > q3_k_32x256_q8_0 ; 1243static const tensor_traits < block_q4_0 ,32 ,32 > q4_0_32x32_q8_0 ; 1244static const tensor_traits < block_q4_1 ,32 ,32 > q4_1_32x32_q8_0 ; 1245static const tensor_traits < block_q4_0 ,256 ,32 > q4_0_32x256_q8_0 ; 1246static const tensor_traits < block_q4_1 ,256 ,32 > q4_1_32x256_q8_0 ; 1247static const tensor_traits < block_q4_K ,32 ,32 > q4_k_32x32_q8_0 ; 1248static const tensor_traits < block_q6_K ,32 ,32 > q6_k_32x32_q8_0 ; 1249static const tensor_traits < block_q8_0 ,32 ,32 > q8_0_32x32_q8_0 ; 1250static const tensor_traits < block_mxfp4 ,32 ,32 > mxfp4_32x32_q8_0 ; 1251static const tensor_traits < block_q5_K ,32 ,32 > q5_k_32x32_q8_0 ; 1252static const tensor_traits < block_q5_1 ,32 ,32 > q5_1_32x32_q8_0 ; 1253static const tensor_traits < block_q5_0 ,32 ,32 > q5_0_32x32_q8_0 ; 1254// Impl By RVV 1255static const tensor_traits_common rvv_impl ; 1256 1257}// namespace ggml::cpu::riscv64_spacemit 1258 1259static const ggml::cpu::tensor_traits * ggml_riscv64_spacemit_get_optimal_repack_type (const ggml_tensor * cur ) { 1260switch (cur -> type ) { 1261case GGML_TYPE_Q2_K : 1262 { 1263#if defined(RISCV64_SPACEMIT_IME2 ) 1264if (cur -> ne [1 ] %32 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 )) { 1265return & ggml::cpu::riscv64_spacemit::q2_k_32x256_q8_0 ; 1266 } 1267#endif 1268 } 1269break ; 1270case GGML_TYPE_Q3_K : 1271 { 1272#if defined(RISCV64_SPACEMIT_IME2 ) 1273if (cur -> ne [1 ] %32 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 )) { 1274return & ggml::cpu::riscv64_spacemit::q3_k_32x256_q8_0 ; 1275 } 1276#endif 1277 } 1278break ; 1279case GGML_TYPE_Q4_0 : 1280 { 1281#if defined(RISCV64_SPACEMIT_IME2 ) 1282if (cur -> ne [1 ] %32 == 0 && cur -> ne [0 ] %256 == 0 && 1283 (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 )) { 1284return & ggml::cpu::riscv64_spacemit::q4_0_32x256_q8_0 ; 1285 } 1286 1287if (cur -> ne [1 ] %32 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 )) { 1288return & ggml::cpu::riscv64_spacemit::q4_0_32x32_q8_0 ; 1289 } 1290#endif 1291 1292#if defined(RISCV64_SPACEMIT_IME1 ) 1293if (cur -> ne [1 ] %16 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime1 )) { 1294return & ggml::cpu::riscv64_spacemit::q4_0_16x32_q8_0 ; 1295 } 1296#endif 1297 } 1298break ; 1299case GGML_TYPE_Q4_1 : 1300 { 1301#if defined(RISCV64_SPACEMIT_IME2 ) 1302// TODO 1303// if (cur->ne[1] % 32 == 0 && cur->ne[0] % 256 == 0 && 1304// (ggml::cpu::riscv64_spacemit::global_spine_env_info.use_ime2)) { 1305// return &ggml::cpu::riscv64_spacemit::q4_1_32x256_q8_0; 1306// } 1307 1308if (cur -> ne [1 ] %32 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 )) { 1309return & ggml::cpu::riscv64_spacemit::q4_1_32x32_q8_0 ; 1310 } 1311#endif 1312 1313#if defined(RISCV64_SPACEMIT_IME1 ) 1314if (cur -> ne [1 ] %16 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime1 )) { 1315return & ggml::cpu::riscv64_spacemit::q4_1_16x32_q8_0 ; 1316 } 1317#endif 1318 } 1319break ; 1320case GGML_TYPE_Q4_K : 1321 { 1322#if defined(RISCV64_SPACEMIT_IME2 ) 1323if (cur -> ne [1 ] %32 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 )) { 1324return & ggml::cpu::riscv64_spacemit::q4_k_32x32_q8_0 ; 1325 } 1326#endif 1327 1328#if defined(RISCV64_SPACEMIT_IME1 ) 1329if (cur -> ne [1 ] %16 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime1 )) { 1330return & ggml::cpu::riscv64_spacemit::q4_k_16x32_q8_0 ; 1331 } 1332#endif 1333 } 1334break ; 1335case GGML_TYPE_Q6_K : 1336 { 1337#if defined(RISCV64_SPACEMIT_IME2 ) 1338if ((ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 )) { 1339return & ggml::cpu::riscv64_spacemit::q6_k_32x32_q8_0 ; 1340 } 1341#endif 1342 } 1343break ; 1344case GGML_TYPE_Q8_0 : 1345 { 1346#if defined(RISCV64_SPACEMIT_IME2 ) 1347if ((ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 )) { 1348return & ggml::cpu::riscv64_spacemit::q8_0_32x32_q8_0 ; 1349 } 1350#endif 1351 } 1352break ; 1353case GGML_TYPE_MXFP4 : 1354 { 1355#if defined(RISCV64_SPACEMIT_IME2 ) 1356// TODO 1357// if (cur->ne[1] % 32 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info.use_ime2)) { 1358// return &ggml::cpu::riscv64_spacemit::mxfp4_32x32_q8_0; 1359// } 1360#endif 1361 } 1362break ; 1363case GGML_TYPE_Q5_K : 1364 { 1365#if defined(RISCV64_SPACEMIT_IME2 ) 1366if (cur -> ne [1 ] %32 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 )) { 1367return & ggml::cpu::riscv64_spacemit::q5_k_32x32_q8_0 ; 1368 } 1369#endif 1370 } 1371break ; 1372case GGML_TYPE_Q5_1 : 1373 { 1374#if defined(RISCV64_SPACEMIT_IME2 ) 1375if (cur -> ne [1 ] %32 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 )) { 1376return & ggml::cpu::riscv64_spacemit::q5_1_32x32_q8_0 ; 1377 } 1378#endif 1379 } 1380break ; 1381case GGML_TYPE_Q5_0 : 1382 { 1383#if defined(RISCV64_SPACEMIT_IME2 ) 1384if (cur -> ne [1 ] %32 == 0 && (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 )) { 1385return & ggml::cpu::riscv64_spacemit::q5_0_32x32_q8_0 ; 1386 } 1387#endif 1388 } 1389break ; 1390default : 1391break ; 1392 } 1393 1394return nullptr ; 1395} 1396 1397static enum ggml_status ggml_backend_riscv64_spacemit_buffer_init_tensor (ggml_backend_buffer_t buffer , 1398ggml_tensor * tensor ) { 1399tensor -> extra = 1400 (void * )const_cast < ggml::cpu::tensor_traits *> (ggml_riscv64_spacemit_get_optimal_repack_type (tensor )); 1401 1402GGML_UNUSED (buffer ); 1403 1404return GGML_STATUS_SUCCESS ; 1405} 1406 1407static void ggml_backend_riscv64_spacemit_buffer_free_buffer (ggml_backend_buffer_t buffer ) { 1408GGML_ASSERT (buffer ); 1409 1410void * base = buffer -> context ; 1411if (base == nullptr ) { 1412return ; 1413 } 1414 1415 ggml::cpu::riscv64_spacemit::spine_mem_pool_free (base ); 1416} 1417 1418static void * ggml_backend_riscv64_spacemit_buffer_get_base (ggml_backend_buffer_t buffer ) { 1419GGML_ASSERT (buffer ); 1420 1421void * base = buffer -> context ; 1422GGML_ASSERT (base != nullptr ); 1423return base ; 1424} 1425 1426static void ggml_backend_riscv64_spacemit_buffer_memset_tensor (ggml_backend_buffer_t buffer , 1427ggml_tensor * tensor , 1428uint8_t value , 1429size_t offset , 1430size_t size ) { 1431GGML_ASSERT (tensor ); 1432memset ((char * )tensor -> data + offset ,value ,size ); 1433 1434GGML_UNUSED (buffer ); 1435} 1436 1437static void ggml_backend_riscv64_spacemit_buffer_clear (ggml_backend_buffer_t buffer ,uint8_t value ) { 1438GGML_ASSERT (buffer ); 1439 1440void * base = buffer -> context ; 1441GGML_ASSERT (base != nullptr ); 1442memset (base ,value ,buffer -> size ); 1443} 1444 1445static void ggml_backend_riscv64_spacemit_buffer_set_tensor (ggml_backend_buffer_t buffer , 1446ggml_tensor * tensor , 1447const void * data , 1448size_t offset , 1449size_t size ) { 1450GGML_ASSERT (offset == 0 ); 1451GGML_ASSERT (size == ggml_nbytes (tensor )); 1452 1453auto tensor_traits = (ggml::cpu::riscv64_spacemit::tensor_traits_base * )tensor -> extra ; 1454if (tensor_traits ) { 1455auto OK = tensor_traits -> repack (tensor ,data ,size ); 1456GGML_ASSERT (OK == 0 ); 1457 } 1458 1459GGML_UNUSED (buffer ); 1460} 1461 1462static const ggml_backend_buffer_i ggml_backend_riscv64_spacemit_buffer_i = { 1463/* .free_buffer = */ ggml_backend_riscv64_spacemit_buffer_free_buffer , 1464/* .get_base = */ ggml_backend_riscv64_spacemit_buffer_get_base , 1465/* .init_tensor = */ ggml_backend_riscv64_spacemit_buffer_init_tensor , 1466/* .memset_tensor = */ ggml_backend_riscv64_spacemit_buffer_memset_tensor , 1467/* .set_tensor = */ ggml_backend_riscv64_spacemit_buffer_set_tensor , 1468/* .get_tensor = */ nullptr , 1469/* .set_tensor_2d = */ nullptr , 1470/* .get_tensor_2d = */ nullptr , 1471/* .cpy_tensor = */ nullptr , 1472/* .clear = */ ggml_backend_riscv64_spacemit_buffer_clear , 1473/* .reset = */ nullptr , 1474}; 1475 1476static const char * ggml_backend_cpu_riscv64_spacemit_buffer_type_get_name (ggml_backend_buffer_type_t buft ) { 1477return "CPU_RISCV64_SPACEMIT" ; 1478 1479GGML_UNUSED (buft ); 1480} 1481 1482static ggml_backend_buffer_t ggml_backend_cpu_riscv64_spacemit_buffer_type_alloc_buffer (ggml_backend_buffer_type_t buft , 1483size_t size ) { 1484void * base = ggml::cpu::riscv64_spacemit::spine_mem_pool_alloc (size ,64 ); 1485if (base == nullptr ) { 1486return nullptr ; 1487 } 1488 1489return ggml_backend_buffer_init (buft ,ggml_backend_riscv64_spacemit_buffer_i ,base ,size ); 1490} 1491 1492static size_t ggml_backend_cpu_riscv64_spacemit_buffer_type_get_alignment (ggml_backend_buffer_type_t buft ) { 1493return 64 ; 1494 1495GGML_UNUSED (buft ); 1496} 1497 1498static size_t ggml_backend_cpu_riscv64_spacemit_nbytes (ggml_backend_buffer_type_t buft ,const ggml_tensor * tensor ) { 1499for (int i = 0 ;i < GGML_MAX_DIMS ;++ i ) { 1500if (tensor -> ne [i ] <=0 ) { 1501return 0 ; 1502 } 1503 } 1504 1505GGML_UNUSED (buft ); 1506 1507const auto plain_nbytes = [& ]() { 1508size_t total = ggml_type_size (tensor -> type ); 1509for (int i = 0 ;i < GGML_MAX_DIMS ;++ i ) { 1510total += (tensor -> ne [i ]- 1 )* tensor -> nb [i ]; 1511 } 1512return total ; 1513 }; 1514 1515const size_t blck_size = ggml_blck_size (tensor -> type ); 1516if (blck_size == 1 ) { 1517return plain_nbytes (); 1518 } 1519 1520const size_t row_nbytes = tensor -> ne [0 ]* tensor -> nb [0 ] /blck_size ; 1521 1522const auto add_strided_nbytes = [& ](size_t total ,size_t src_block_size ,size_t dst_block_size ) { 1523for (int i = 1 ;i < GGML_MAX_DIMS ;++ i ) { 1524total += (tensor -> ne [i ]- 1 )* (tensor -> nb [i ] /src_block_size )* dst_block_size ; 1525 } 1526return total ; 1527 }; 1528 1529const auto remap_block_nbytes = [& ](size_t src_block_size ,size_t dst_block_size ,int64_t padded_rows = 0 ) { 1530GGML_ASSERT (row_nbytes %src_block_size == 0 ); 1531 1532size_t total = 1533add_strided_nbytes ((row_nbytes /src_block_size )* dst_block_size ,src_block_size ,dst_block_size ); 1534 1535if (padded_rows > 0 && tensor -> ne [1 ] %padded_rows != 0 ) { 1536total += (padded_rows - tensor -> ne [1 ] %padded_rows )* (tensor -> nb [1 ] /src_block_size )* dst_block_size ; 1537 } 1538 1539return total ; 1540 }; 1541 1542size_t nbytes = row_nbytes ; 1543switch (tensor -> type ) { 1544case GGML_TYPE_Q4_K : 1545nbytes = remap_block_nbytes (sizeof (block_q4_K ),sizeof (block_q4_1 )* 8 ); 1546break ; 1547case GGML_TYPE_Q6_K : 1548nbytes = remap_block_nbytes (sizeof (block_q6_K ),sizeof (block_q8_0 )* 8 ,32 ); 1549break ; 1550case GGML_TYPE_Q8_0 : 1551nbytes = remap_block_nbytes (sizeof (block_q8_0 ),sizeof (block_q8_0 ),32 ); 1552break ; 1553case GGML_TYPE_Q2_K : 1554nbytes = remap_block_nbytes (sizeof (block_q2_K ),sizeof (spacemit_kernels::nrow_block_q2_k < 1 > )); 1555break ; 1556case GGML_TYPE_Q3_K : 1557nbytes = remap_block_nbytes (sizeof (block_q3_K ),sizeof (spacemit_kernels::nrow_block_q3_k < 1 > )); 1558break ; 1559case GGML_TYPE_MXFP4 : 1560nbytes = remap_block_nbytes (sizeof (block_mxfp4 ),sizeof (spacemit_kernels::nrow_block_mxfp4 < 1 > )); 1561break ; 1562case GGML_TYPE_Q5_K : 1563nbytes = remap_block_nbytes (sizeof (block_q5_K ),sizeof (spacemit_kernels::nrow_block_q5_1 < 1 > )* 8 ); 1564break ; 1565case GGML_TYPE_Q5_1 : 1566nbytes = remap_block_nbytes (sizeof (block_q5_1 ),sizeof (spacemit_kernels::nrow_block_q5_1 < 1 > )); 1567break ; 1568case GGML_TYPE_Q5_0 : 1569nbytes = remap_block_nbytes (sizeof (block_q5_0 ),sizeof (spacemit_kernels::nrow_block_q5_0 < 1 > )); 1570break ; 1571default : 1572nbytes = add_strided_nbytes (row_nbytes ,1 ,1 ); 1573break ; 1574 } 1575 1576return nbytes ; 1577} 1578 1579namespace ggml::cpu::riscv64_spacemit { 1580 1581class extra_buffer_type : ggml::cpu::extra_buffer_type { 1582bool supports_op (ggml_backend_dev_t ,const ggml_tensor * op )override { 1583switch (op -> op ) { 1584case GGML_OP_MUL_MAT : 1585if (op -> src [0 ]-> buffer && (ggml_n_dims (op -> src [0 ])== 2 )&& 1586op -> src [0 ]-> buffer -> buft == ggml_backend_cpu_riscv64_spacemit_buffer_type ()&& 1587ggml_riscv64_spacemit_get_optimal_repack_type (op -> src [0 ])) { 1588if (op -> src [1 ]-> buffer && !ggml_backend_buft_is_host (op -> src [1 ]-> buffer -> buft )) { 1589return false; 1590 } 1591if (op -> src [1 ]-> type == GGML_TYPE_F32 ) { 1592return true; 1593 } 1594 } 1595break ; 1596case GGML_OP_MUL_MAT_ID : 1597if (op -> src [0 ]-> buffer && (ggml_n_dims (op -> src [0 ])== 3 )&& 1598op -> src [0 ]-> buffer -> buft == ggml_backend_cpu_riscv64_spacemit_buffer_type ()&& 1599ggml_riscv64_spacemit_get_optimal_repack_type (op -> src [0 ])) { 1600if (op -> src [1 ]-> buffer && !ggml_backend_buft_is_host (op -> src [1 ]-> buffer -> buft )) { 1601return false; 1602 } 1603if (op -> src [1 ]-> type == GGML_TYPE_F32 ) { 1604return true; 1605 } 1606 } 1607break ; 1608default : 1609// GGML_ABORT("fatal error"); 1610break ; 1611 } 1612return false; 1613 } 1614 1615 ggml::cpu::tensor_traits * get_tensor_traits (const ggml_tensor * op )override { 1616switch (op -> op ) { 1617case GGML_OP_MUL_MAT : 1618case GGML_OP_MUL_MAT_ID : 1619if (op -> src [0 ]-> buffer && op -> src [0 ]-> buffer -> buft == ggml_backend_cpu_riscv64_spacemit_buffer_type ()) { 1620return (ggml::cpu::tensor_traits * )op -> src [0 ]-> extra ; 1621 } 1622break ; 1623case GGML_OP_NORM : 1624case GGML_OP_RMS_NORM : 1625case GGML_OP_ADD : 1626case GGML_OP_SUB : 1627case GGML_OP_MUL : 1628case GGML_OP_DIV : 1629case GGML_OP_FLASH_ATTN_EXT : 1630case GGML_OP_CONT : 1631case GGML_OP_CPY : 1632case GGML_OP_REPEAT : 1633case GGML_OP_SUM_ROWS : 1634case GGML_OP_GET_ROWS : 1635case GGML_OP_CONCAT : 1636// case GGML_OP_GATED_DELTA_NET: 1637return (ggml::cpu::tensor_traits * ) (& ggml::cpu::riscv64_spacemit::rvv_impl ); 1638default : 1639// GGML_ABORT("fatal error"); 1640break ; 1641 } 1642 1643return nullptr ; 1644 } 1645}; 1646 1647}// namespace ggml::cpu::riscv64_spacemit 1648 1649ggml_backend_buffer_type_t ggml_backend_cpu_riscv64_spacemit_buffer_type (void ) { 1650static ggml_backend_buffer_type ggml_backend_cpu_buffer_type_riscv64_spacemit = { 1651/* .iface = */ 1652 { 1653/* .get_name = */ ggml_backend_cpu_riscv64_spacemit_buffer_type_get_name , 1654/* .alloc_buffer = */ ggml_backend_cpu_riscv64_spacemit_buffer_type_alloc_buffer , 1655/* .get_alignment = */ ggml_backend_cpu_riscv64_spacemit_buffer_type_get_alignment , 1656/* .get_max_size = */ nullptr , 1657/* .get_alloc_size = */ ggml_backend_cpu_riscv64_spacemit_nbytes , 1658/* .is_host = */ nullptr , 1659 }, 1660/* .device = */ 1661ggml_backend_reg_dev_get (ggml_backend_cpu_reg (),0 ), 1662/* .context = */ 1663new ggml::cpu::riscv64_spacemit::extra_buffer_type (), 1664 }; 1665 1666return & ggml_backend_cpu_buffer_type_riscv64_spacemit ; 1667} 1668 1669extern "C" { 1670static int bind_ai_thread () { 1671int fd ,bytes ; 1672char str [32 ]; 1673 1674fd = open ("/proc/set_ai_thread" ,O_WRONLY ); 1675if (fd < 0 ) { 1676GGML_LOG_ERROR ("try open /proc/set_ai_thread failed\n" ); 1677return -1 ; 1678 } 1679 1680snprintf (str ,16 ,"%d" ,0 ); 1681bytes = write (fd ,str ,strlen (str )); 1682if (bytes < 0 ) { 1683GGML_LOG_ERROR ("try write /proc/set_ai_thread failed\n" ); 1684close (fd ); 1685return -1 ; 1686 } 1687 1688close (fd ); 1689return 0 ; 1690} 1691 1692void ggml_backend_cpu_riscv64_spacemit_set_numa_thread_affinity (int thread_n ) { 1693int cpu_id = sched_getcpu (); 1694if (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_ime2 && 1695 !((1 <<cpu_id )& ggml::cpu::riscv64_spacemit::global_spine_env_info .cpu_mask )) { 1696GGML_PRINT_DEBUG ("bind_ai_thread for thread %d, pid %d\n" ,thread_n ,getpid ()); 1697bind_ai_thread (); 1698 } 1699 1700if (ggml::cpu::riscv64_spacemit::global_spine_env_info .use_tcm && 1701 ggml::cpu::riscv64_spacemit::tls_context .cpu_id == -1 ) { 1702CPU_ZERO (& (ggml::cpu::riscv64_spacemit::tls_context .cpuset )); 1703pthread_t main_thread = pthread_self (); 1704const auto & perfer_core_ids = ggml::cpu::riscv64_spacemit::global_spine_env_info .perfer_core_ids ; 1705if (thread_n < 0 || static_cast < size_t > (thread_n ) >=perfer_core_ids .size ()) { 1706GGML_ABORT ("thread_n %d exceeds perfer_core_ids size %zu\n" ,thread_n ,perfer_core_ids .size ()); 1707 } 1708auto perfer_cpu_id = perfer_core_ids [static_cast < size_t > (thread_n )]; 1709CPU_SET (perfer_cpu_id ,& (ggml::cpu::riscv64_spacemit::tls_context .cpuset )); 1710int s = 1711pthread_setaffinity_np (main_thread ,sizeof (cpu_set_t ),& (ggml::cpu::riscv64_spacemit::tls_context .cpuset )); 1712if (s != 0 ) { 1713GGML_ABORT ("set thread affinity error for thread_n %d, cpu_id %d\n" ,thread_n ,perfer_cpu_id ); 1714 } 1715 1716int ai_cpu_id = perfer_cpu_id - ggml::cpu::riscv64_spacemit::global_spine_env_info .aicpu_id_offset ; 1717 ggml::cpu::riscv64_spacemit::tls_context .cpu_id = ai_cpu_id ; 1718 ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer = 1719 ggml::cpu::riscv64_spacemit::spine_mem_pool_tcm_mem_get (ai_cpu_id ); 1720 ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer_size = 1721 ggml::cpu::riscv64_spacemit::global_spine_env_info .tcm_blk_size ; 1722 } 1723 1724if (ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer != nullptr ) { 1725void * rt = 1726 ggml::cpu::riscv64_spacemit::spine_mem_pool_tcm_mem_wait (ggml::cpu::riscv64_spacemit::tls_context .cpu_id ); 1727if (rt == nullptr ) { 1728GGML_ABORT ("wait tcm buffer failed for cpu_id: %d" , ggml::cpu::riscv64_spacemit::tls_context .cpu_id ); 1729 } 1730 } 1731} 1732 1733void ggml_backend_cpu_riscv64_spacemit_clear_numa_thread_affinity_threaded (int thread_n ) { 1734if (ggml::cpu::riscv64_spacemit::tls_context .tcm_buffer != nullptr ) { 1735auto rt = ggml::cpu::riscv64_spacemit::spine_mem_pool_tcm_mem_release ( 1736 ggml::cpu::riscv64_spacemit::tls_context .cpu_id ); 1737if (rt != 0 ) { 1738GGML_ABORT ("release tcm buffer failed for cpu_id: %d" , ggml::cpu::riscv64_spacemit::tls_context .cpu_id ); 1739 } 1740 } 1741} 1742}