char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
57b50e1f6
char/aliceai-t5-moe
1#pragma once 2 3// Computes C[M x N] += A[M x K] * B[K x N] 4 5#include "simd-mappings.h" 6 7// TODO: add support for sizeless vector types 8#if defined(GGML_SIMD )&& !defined(__ARM_FEATURE_SVE )&& !defined(__riscv_v_intrinsic ) 9 10// TODO: untested on avx512 11// These are in units of GGML_F32_EPR 12#if defined(__AVX512F__ )|| defined (__ARM_NEON__ ) 13static constexprint GEMM_RM = 4 ; 14static constexprint GEMM_RN = 4 ;// 16+4+1 = 25/32 15#elif defined(__AVX2__ )|| defined(__AVX__ ) 16static constexprint GEMM_RM = 6 ; 17static constexprint GEMM_RN = 2 ;// 12+2+1 = 15/16 18#else 19static constexprint GEMM_RM = 2 ; 20static constexprint GEMM_RN = 2 ; 21#endif 22 23template < int RM ,int RN > 24static inline void simd_gemm_ukernel ( 25float * GGML_RESTRICT C , 26const float * GGML_RESTRICT A , 27const float * GGML_RESTRICT B , 28int K ,int N ) 29{ 30static constexprint KN = GGML_F32_EPR ; 31 32GGML_F32_VEC acc [RM ][RN ]; 33for (int64_t i = 0 ;i < RM ;i ++ ) { 34for (int r = 0 ;r < RN ;r ++ ) { 35acc [i ][r ]= GGML_F32_VEC_LOAD (C + i * N + r * KN ); 36 } 37 } 38 39for (int64_t kk = 0 ;kk < K ;kk ++ ) { 40GGML_F32_VEC Bv [RN ]; 41for (int r = 0 ;r < RN ;r ++ ) { 42Bv [r ]= GGML_F32_VEC_LOAD (B + kk * N + r * KN ); 43 } 44for (int64_t i = 0 ;i < RM ;i ++ ) { 45GGML_F32_VEC p = GGML_F32_VEC_SET1 (A [i * K + kk ]); 46for (int r = 0 ;r < RN ;r ++ ) { 47acc [i ][r ]= GGML_F32_VEC_FMA (acc [i ][r ],Bv [r ],p ); 48 } 49 } 50 } 51 52for (int64_t i = 0 ;i < RM ;i ++ ) { 53for (int r = 0 ;r < RN ;r ++ ) { 54GGML_F32_VEC_STORE (C + i * N + r * KN ,acc [i ][r ]); 55 } 56 } 57} 58 59// C[M x N] += A[M x K] * B[K x N] 60static void simd_gemm ( 61float * GGML_RESTRICT C , 62const float * GGML_RESTRICT A , 63const float * GGML_RESTRICT B , 64int M ,int K ,int N ) 65{ 66static constexprint KN = GGML_F32_EPR ; 67 68int64_t ii = 0 ; 69for (;ii + GEMM_RM <=M ;ii += GEMM_RM ) { 70int64_t jj = 0 ; 71for (;jj + GEMM_RN * KN <=N ;jj += GEMM_RN * KN ) { 72simd_gemm_ukernel < GEMM_RM ,GEMM_RN > (C + jj ,A ,B + jj ,K ,N ); 73 } 74for (;jj + KN <=N ;jj += KN ) { 75simd_gemm_ukernel < GEMM_RM ,1 > (C + jj ,A ,B + jj ,K ,N ); 76 } 77for (;jj < N ;jj ++ ) { 78for (int64_t i = 0 ;i < GEMM_RM ;i ++ ) { 79float a = C [i * N + jj ]; 80for (int64_t kk = 0 ;kk < K ;kk ++ ) { 81a += A [i * K + kk ]* B [kk * N + jj ]; 82 } 83C [i * N + jj ]= a ; 84 } 85 } 86 87A += GEMM_RM * K ; 88C += GEMM_RM * N ; 89 } 90 91// Tail rows: one at a time 92for (;ii < M ;ii ++ ) { 93int64_t jj = 0 ; 94for (;jj + GEMM_RN * KN <=N ;jj += GEMM_RN * KN ) { 95simd_gemm_ukernel < 1 ,GEMM_RN > (C + jj ,A ,B + jj ,K ,N ); 96 } 97for (;jj + KN <=N ;jj += KN ) { 98simd_gemm_ukernel < 1 ,1 > (C + jj ,A ,B + jj ,K ,N ); 99 } 100for (;jj < N ;jj ++ ) { 101float a = C [jj ]; 102for (int64_t kk = 0 ;kk < K ;kk ++ ) { 103a += A [kk ]* B [kk * N + jj ]; 104 } 105C [jj ]= a ; 106 } 107 108A += K ; 109C += N ; 110 } 111} 112#elif defined(GGML_SIMD )&& defined(__riscv_v_intrinsic ) 113// RM accumulators + 1 B vector = RM + 1 <= 8 => RM <= 7 114// Microkernel: C[RM x vl] += A[RM x K] * B[K x N] 115template < int RM > 116static inline void rvv_simd_gemm_ukernel ( 117float * GGML_RESTRICT C , 118const float * GGML_RESTRICT A , 119const float * GGML_RESTRICT B , 120int K ,int N ,size_t vl ) 121{ 122static_assert (RM >=1 && RM <=7 ,"RM must be 1..7 for LMUL=4" ); 123 124vfloat32m4_t acc_0 = __riscv_vle32_v_f32m4 (C + 0 * N ,vl ); 125vfloat32m4_t acc_1 ,acc_2 ,acc_3 ,acc_4 ,acc_5 ,acc_6 ; 126if constexpr (RM > 1 )acc_1 = __riscv_vle32_v_f32m4 (C + 1 * N ,vl ); 127if constexpr (RM > 2 )acc_2 = __riscv_vle32_v_f32m4 (C + 2 * N ,vl ); 128if constexpr (RM > 3 )acc_3 = __riscv_vle32_v_f32m4 (C + 3 * N ,vl ); 129if constexpr (RM > 4 )acc_4 = __riscv_vle32_v_f32m4 (C + 4 * N ,vl ); 130if constexpr (RM > 5 )acc_5 = __riscv_vle32_v_f32m4 (C + 5 * N ,vl ); 131if constexpr (RM > 6 )acc_6 = __riscv_vle32_v_f32m4 (C + 6 * N ,vl ); 132 133for (int kk = 0 ;kk < K ;kk ++ ) { 134vfloat32m4_t b_0 = __riscv_vle32_v_f32m4 (B + kk * N ,vl ); 135 136acc_0 = __riscv_vfmacc_vf_f32m4 (acc_0 ,A [0 * K + kk ],b_0 ,vl ); 137if constexpr (RM > 1 )acc_1 = __riscv_vfmacc_vf_f32m4 (acc_1 ,A [1 * K + kk ],b_0 ,vl ); 138if constexpr (RM > 2 )acc_2 = __riscv_vfmacc_vf_f32m4 (acc_2 ,A [2 * K + kk ],b_0 ,vl ); 139if constexpr (RM > 3 )acc_3 = __riscv_vfmacc_vf_f32m4 (acc_3 ,A [3 * K + kk ],b_0 ,vl ); 140if constexpr (RM > 4 )acc_4 = __riscv_vfmacc_vf_f32m4 (acc_4 ,A [4 * K + kk ],b_0 ,vl ); 141if constexpr (RM > 5 )acc_5 = __riscv_vfmacc_vf_f32m4 (acc_5 ,A [5 * K + kk ],b_0 ,vl ); 142if constexpr (RM > 6 )acc_6 = __riscv_vfmacc_vf_f32m4 (acc_6 ,A [6 * K + kk ],b_0 ,vl ); 143 } 144 145__riscv_vse32_v_f32m4 (C + 0 * N ,acc_0 ,vl ); 146if constexpr (RM > 1 )__riscv_vse32_v_f32m4 (C + 1 * N ,acc_1 ,vl ); 147if constexpr (RM > 2 )__riscv_vse32_v_f32m4 (C + 2 * N ,acc_2 ,vl ); 148if constexpr (RM > 3 )__riscv_vse32_v_f32m4 (C + 3 * N ,acc_3 ,vl ); 149if constexpr (RM > 4 )__riscv_vse32_v_f32m4 (C + 4 * N ,acc_4 ,vl ); 150if constexpr (RM > 5 )__riscv_vse32_v_f32m4 (C + 5 * N ,acc_5 ,vl ); 151if constexpr (RM > 6 )__riscv_vse32_v_f32m4 (C + 6 * N ,acc_6 ,vl ); 152} 153 154template < int RM > 155static inline void rvv_simd_gemm_dispatch_tail ( 156float * GGML_RESTRICT C , 157const float * GGML_RESTRICT A , 158const float * GGML_RESTRICT B , 159int K ,int N ,int KN ,int remaining_rows ) 160{ 161if constexpr (RM > 0 ) { 162if (remaining_rows == RM ) { 163int64_t jj = 0 ; 164for (;jj + KN <=N ;jj += KN ) { 165rvv_simd_gemm_ukernel < RM > (C + jj ,A ,B + jj ,K ,N ,KN ); 166 } 167if (jj < N ) { 168rvv_simd_gemm_ukernel < RM > (C + jj ,A ,B + jj ,K ,N ,N - jj ); 169 } 170 }else { 171rvv_simd_gemm_dispatch_tail < RM - 1 > (C ,A ,B ,K ,N ,KN ,remaining_rows ); 172 } 173 } 174} 175 176static constexprint GEMM_RM = 7 ; 177 178// C[M x N] += A[M x K] * B[K x N] 179static void simd_gemm ( 180float * GGML_RESTRICT C , 181const float * GGML_RESTRICT A , 182const float * GGML_RESTRICT B , 183int M ,int K ,int N ) 184{ 185const int KN = (int )__riscv_vlenb (); 186int64_t ii = 0 ; 187for (;ii + GEMM_RM <=M ;ii += GEMM_RM ) { 188int64_t jj = 0 ; 189for (;jj + KN <=N ;jj += KN ) { 190rvv_simd_gemm_ukernel < GEMM_RM > (C + jj ,A ,B + jj ,K ,N ,KN ); 191 } 192if (jj < N ) { 193rvv_simd_gemm_ukernel < GEMM_RM > (C + jj ,A ,B + jj ,K ,N ,N - jj ); 194 } 195A += GEMM_RM * K ; 196C += GEMM_RM * N ; 197 } 198 199int remaining_rows = M - ii ; 200rvv_simd_gemm_dispatch_tail < GEMM_RM - 1 > (C ,A ,B ,K ,N ,KN ,remaining_rows ); 201} 202 203#if defined(__GNUC__ )&& !defined(__clang__ ) 204#pragma GCC diagnostic pop 205#endif 206 207#else // scalar path 208 209static void simd_gemm ( 210float * GGML_RESTRICT C , 211const float * GGML_RESTRICT A , 212const float * GGML_RESTRICT B , 213int M ,int K ,int N ) 214{ 215for (int64_t i = 0 ;i < M ;i ++ ) { 216for (int64_t j = 0 ;j < N ;j ++ ) { 217float sum = C [i * N + j ]; 218for (int64_t kk = 0 ;kk < K ;kk ++ ) { 219sum += A [i * K + kk ]* B [kk * N + j ]; 220 } 221C [i * N + j ]= sum ; 222 } 223 } 224} 225 226#endif // GGML_SIMD