← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
gemm_kernels_f16.c File Reference

GEMM kernels with FP16 (half-precision) weights. More...

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "ckernel_quant.h"
#include "ckernel_engine.h"
#include "ck_threadpool.h"
#include "ggml_runtime_compat.h"
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>

Go to the source code of this file.

Macros

#define _GNU_SOURCE
 
#define fp16_to_fp32(x)   ggml_fp16_to_fp32(x)
 
#define fp32_to_fp16(x)   ggml_fp32_to_fp16(x)
 

Typedefs

typedef void(* ck_f16_ggml_build_forward_expand_fn) (struct ggml_cgraph *, struct ggml_tensor *)
 
typedef void(* ck_f16_ggml_cpu_init_fn) (void)
 
typedef void(* ck_f16_ggml_free_fn) (struct ggml_context *)
 
typedef float *(* ck_f16_ggml_get_data_f32_fn) (const struct ggml_tensor *)
 
typedef void *(* ck_f16_ggml_get_data_fn) (const struct ggml_tensor *)
 
typedef enum ggml_status(* ck_f16_ggml_graph_compute_with_ctx_fn) (struct ggml_context *, struct ggml_cgraph *, int)
 
typedef struct ggml_context *(* ck_f16_ggml_init_fn) (struct ggml_init_params)
 
typedef struct ggml_tensor *(* ck_f16_ggml_mul_mat_fn) (struct ggml_context *, struct ggml_tensor *, struct ggml_tensor *)
 
typedef struct ggml_cgraph *(* ck_f16_ggml_new_graph_fn) (struct ggml_context *)
 
typedef struct ggml_tensor *(* ck_f16_ggml_new_tensor_2d_fn) (struct ggml_context *, enum ggml_type, int64_t, int64_t)
 

Functions

static float ck_dot_f16_f16_local (const uint16_t *w, const uint16_t *x, int k)
 
static ck_f16_ggml_build_forward_expand_fn ck_f16_resolve_ggml_build_forward_expand (void)
 
static ck_f16_ggml_cpu_init_fn ck_f16_resolve_ggml_cpu_init (void)
 
static ck_f16_ggml_free_fn ck_f16_resolve_ggml_free (void)
 
static ck_f16_ggml_get_data_fn ck_f16_resolve_ggml_get_data (void)
 
static ck_f16_ggml_get_data_f32_fn ck_f16_resolve_ggml_get_data_f32 (void)
 
static ck_f16_ggml_graph_compute_with_ctx_fn ck_f16_resolve_ggml_graph_compute_with_ctx (void)
 
static ck_f16_ggml_init_fn ck_f16_resolve_ggml_init (void)
 
static ck_f16_ggml_mul_mat_fn ck_f16_resolve_ggml_mul_mat (void)
 
static ck_f16_ggml_new_graph_fn ck_f16_resolve_ggml_new_graph (void)
 
static ck_f16_ggml_new_tensor_2d_fn ck_f16_resolve_ggml_new_tensor_2d (void)
 
static void ck_f32_to_f16_row_local (uint16_t *dst, const float *src, int n)
 
static void ck_gemm_f16_input_fp16_work (int ith, int nth, void *opaque)
 
static int ck_gemm_f16_pick_active_threads (const ck_threadpool_t *pool, int M, int N, int K)
 
static int ck_gemm_f16_threadpool_enabled (int M, int N, int K)
 
int ck_gemm_nt_f16_ggml_oracle (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
int ck_gemm_nt_f16_simd_lanes (void)
 
void convert_f16_to_f32 (float *dst, const uint16_t *src, size_t count)
 Convert FP16 tensor to FP32.
 
void convert_f32_to_f16 (uint16_t *dst, const float *src, size_t count)
 Convert FP32 tensor to FP16.
 
float dot_f16 (const uint16_t *w_f16, const float *x, int K)
 
void gemm_f16 (float *Y, const uint16_t *W, const float *X, int M, int N, int K)
 Auto-dispatch GEMM based on available SIMD.
 
void gemm_f16_backward (float *dX, const uint16_t *W, const float *dY, int M, int N, int K)
 Batched backward pass.
 
static void gemm_f16_input_fp16_ref (float *Y, const uint16_t *W, const float *X, int M, int N, int K)
 
static int gemm_f16_input_fp16_threadpool (float *Y, const uint16_t *W, const float *X, int M, int N, int K)
 
void gemm_f16_ref (float *Y, const uint16_t *W, const float *X, int M, int N, int K)
 Matrix-matrix multiply with FP16 weights (scalar reference)
 
void gemm_nt_f16 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 NT GEMM wrapper for FP16 weights with the engine's standard ABI.
 
void gemm_nt_f16_clipped (const float *A, const void *B, const float *bias, const float *input_min, const float *input_max, const float *output_min, const float *output_max, float *C, int M, int N, int K)
 
static int gemm_nt_f16_ggml_strict (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemv_f16 (float *y, const uint16_t *W, const float *x, int M, int K)
 Auto-dispatch GEMV based on available SIMD.
 
void gemv_f16_backward (float *dX, const uint16_t *W, const float *dY, int M, int K)
 Auto-dispatch backward.
 
void gemv_f16_backward_ref (float *dX, const uint16_t *W, const float *dY, int M, int K)
 Backward pass: compute input gradient (scalar reference)
 
void gemv_f16_ref (float *y, const uint16_t *W, const float *x, int M, int K)
 Matrix-vector multiply with FP16 weights (scalar reference)
 

Detailed Description

GEMM kernels with FP16 (half-precision) weights.

CK-ENGINE KERNEL RULES:

  1. NO malloc/free - memory via bump allocator, pointers passed in
  2. NO OpenMP - parallelization at orchestrator/codegen layer
  3. API must define: inputs, outputs, workspace, and memory layouts
  4. Pure computation - deterministic, no side effects

After changes: make test && make llamacpp-parity-full

Implements matrix multiplication where:

  • Weights: FP16 (IEEE half-precision, used by vision encoders)
  • Activations: FP32
  • Output: FP32

Used for multimodal projection layers (mmproj-*.gguf files).

Definition in file gemm_kernels_f16.c.

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 23 of file gemm_kernels_f16.c.

◆ fp16_to_fp32

#define fp16_to_fp32 (   x)    ggml_fp16_to_fp32(x)

Definition at line 279 of file gemm_kernels_f16.c.

◆ fp32_to_fp16

#define fp32_to_fp16 (   x)    ggml_fp32_to_fp16(x)

Definition at line 280 of file gemm_kernels_f16.c.

Typedef Documentation

◆ ck_f16_ggml_build_forward_expand_fn

typedef void(* ck_f16_ggml_build_forward_expand_fn) (struct ggml_cgraph *, struct ggml_tensor *)

Definition at line 47 of file gemm_kernels_f16.c.

◆ ck_f16_ggml_cpu_init_fn

typedef void(* ck_f16_ggml_cpu_init_fn) (void)

Definition at line 49 of file gemm_kernels_f16.c.

◆ ck_f16_ggml_free_fn

typedef void(* ck_f16_ggml_free_fn) (struct ggml_context *)

Definition at line 43 of file gemm_kernels_f16.c.

◆ ck_f16_ggml_get_data_f32_fn

typedef float *(* ck_f16_ggml_get_data_f32_fn) (const struct ggml_tensor *)

Definition at line 51 of file gemm_kernels_f16.c.

◆ ck_f16_ggml_get_data_fn

typedef void *(* ck_f16_ggml_get_data_fn) (const struct ggml_tensor *)

Definition at line 50 of file gemm_kernels_f16.c.

◆ ck_f16_ggml_graph_compute_with_ctx_fn

typedef enum ggml_status(* ck_f16_ggml_graph_compute_with_ctx_fn) (struct ggml_context *, struct ggml_cgraph *, int)

Definition at line 47 of file gemm_kernels_f16.c.

◆ ck_f16_ggml_init_fn

typedef struct ggml_context *(* ck_f16_ggml_init_fn) (struct ggml_init_params)

Definition at line 1 of file gemm_kernels_f16.c.

◆ ck_f16_ggml_mul_mat_fn

typedef struct ggml_tensor *(* ck_f16_ggml_mul_mat_fn) (struct ggml_context *, struct ggml_tensor *, struct ggml_tensor *)

Definition at line 43 of file gemm_kernels_f16.c.

◆ ck_f16_ggml_new_graph_fn

typedef struct ggml_cgraph *(* ck_f16_ggml_new_graph_fn) (struct ggml_context *)

Definition at line 43 of file gemm_kernels_f16.c.

◆ ck_f16_ggml_new_tensor_2d_fn

typedef struct ggml_tensor *(* ck_f16_ggml_new_tensor_2d_fn) (struct ggml_context *, enum ggml_type, int64_t, int64_t)

Definition at line 43 of file gemm_kernels_f16.c.

Function Documentation

◆ ck_dot_f16_f16_local()

static float ck_dot_f16_f16_local ( const uint16_t *  w,
const uint16_t *  x,
int  k 
)
inlinestatic

Definition at line 568 of file gemm_kernels_f16.c.

569{
570#if defined(__AVX512F__) && defined(__F16C__)
571 return ck_dot_f16_f16_avx512(w, x, k);
572#elif defined(__F16C__) && defined(__AVX__)
573 return ck_dot_f16_f16_avx(w, x, k);
574#else
575 float sum = 0.0f;
576 for (int i = 0; i < k; ++i) {
577 sum += fp16_to_fp32(w[i]) * fp16_to_fp32(x[i]);
578 }
579 return sum;
580#endif
581}
#define fp16_to_fp32(x)

References fp16_to_fp32.

Referenced by ck_gemm_f16_input_fp16_work(), and gemm_f16_input_fp16_ref().

◆ ck_f16_resolve_ggml_build_forward_expand()

static ck_f16_ggml_build_forward_expand_fn ck_f16_resolve_ggml_build_forward_expand ( void  )
static

Definition at line 108 of file gemm_kernels_f16.c.

109{
110 static int tried = 0;
112 if (!tried) {
113 tried = 1;
114 fn = (ck_f16_ggml_build_forward_expand_fn) dlsym(RTLD_DEFAULT, "ggml_build_forward_expand");
115 }
116 return fn;
117}
#define RTLD_DEFAULT
void(* ck_f16_ggml_build_forward_expand_fn)(struct ggml_cgraph *, struct ggml_tensor *)

References RTLD_DEFAULT.

Referenced by gemm_nt_f16_ggml_strict().

◆ ck_f16_resolve_ggml_cpu_init()

static ck_f16_ggml_cpu_init_fn ck_f16_resolve_ggml_cpu_init ( void  )
static

Definition at line 130 of file gemm_kernels_f16.c.

131{
132 static int tried = 0;
133 static ck_f16_ggml_cpu_init_fn fn = NULL;
134 if (!tried) {
135 tried = 1;
136 fn = (ck_f16_ggml_cpu_init_fn) dlsym(RTLD_DEFAULT, "ggml_cpu_init");
137 }
138 return fn;
139}
void(* ck_f16_ggml_cpu_init_fn)(void)

References RTLD_DEFAULT.

Referenced by gemm_nt_f16_ggml_strict().

◆ ck_f16_resolve_ggml_free()

static ck_f16_ggml_free_fn ck_f16_resolve_ggml_free ( void  )
static

Definition at line 64 of file gemm_kernels_f16.c.

65{
66 static int tried = 0;
67 static ck_f16_ggml_free_fn fn = NULL;
68 if (!tried) {
69 tried = 1;
70 fn = (ck_f16_ggml_free_fn) dlsym(RTLD_DEFAULT, "ggml_free");
71 }
72 return fn;
73}
void(* ck_f16_ggml_free_fn)(struct ggml_context *)

References RTLD_DEFAULT.

Referenced by gemm_nt_f16_ggml_strict().

◆ ck_f16_resolve_ggml_get_data()

static ck_f16_ggml_get_data_fn ck_f16_resolve_ggml_get_data ( void  )
static

Definition at line 141 of file gemm_kernels_f16.c.

142{
143 static int tried = 0;
144 static ck_f16_ggml_get_data_fn fn = NULL;
145 if (!tried) {
146 tried = 1;
147 fn = (ck_f16_ggml_get_data_fn) dlsym(RTLD_DEFAULT, "ggml_get_data");
148 }
149 return fn;
150}
void *(* ck_f16_ggml_get_data_fn)(const struct ggml_tensor *)

References RTLD_DEFAULT.

Referenced by gemm_nt_f16_ggml_strict().

◆ ck_f16_resolve_ggml_get_data_f32()

static ck_f16_ggml_get_data_f32_fn ck_f16_resolve_ggml_get_data_f32 ( void  )
static

Definition at line 152 of file gemm_kernels_f16.c.

153{
154 static int tried = 0;
155 static ck_f16_ggml_get_data_f32_fn fn = NULL;
156 if (!tried) {
157 tried = 1;
158 fn = (ck_f16_ggml_get_data_f32_fn) dlsym(RTLD_DEFAULT, "ggml_get_data_f32");
159 }
160 return fn;
161}
float *(* ck_f16_ggml_get_data_f32_fn)(const struct ggml_tensor *)

References RTLD_DEFAULT.

Referenced by gemm_nt_f16_ggml_strict().

◆ ck_f16_resolve_ggml_graph_compute_with_ctx()

static ck_f16_ggml_graph_compute_with_ctx_fn ck_f16_resolve_ggml_graph_compute_with_ctx ( void  )
static

Definition at line 119 of file gemm_kernels_f16.c.

120{
121 static int tried = 0;
123 if (!tried) {
124 tried = 1;
125 fn = (ck_f16_ggml_graph_compute_with_ctx_fn) dlsym(RTLD_DEFAULT, "ggml_graph_compute_with_ctx");
126 }
127 return fn;
128}
enum ggml_status(* ck_f16_ggml_graph_compute_with_ctx_fn)(struct ggml_context *, struct ggml_cgraph *, int)

References RTLD_DEFAULT.

Referenced by gemm_nt_f16_ggml_strict().

◆ ck_f16_resolve_ggml_init()

static ck_f16_ggml_init_fn ck_f16_resolve_ggml_init ( void  )
static

Definition at line 53 of file gemm_kernels_f16.c.

54{
55 static int tried = 0;
56 static ck_f16_ggml_init_fn fn = NULL;
57 if (!tried) {
58 tried = 1;
59 fn = (ck_f16_ggml_init_fn) dlsym(RTLD_DEFAULT, "ggml_init");
60 }
61 return fn;
62}
struct ggml_context *(* ck_f16_ggml_init_fn)(struct ggml_init_params)

References RTLD_DEFAULT.

Referenced by gemm_nt_f16_ggml_strict().

◆ ck_f16_resolve_ggml_mul_mat()

static ck_f16_ggml_mul_mat_fn ck_f16_resolve_ggml_mul_mat ( void  )
static

Definition at line 86 of file gemm_kernels_f16.c.

87{
88 static int tried = 0;
89 static ck_f16_ggml_mul_mat_fn fn = NULL;
90 if (!tried) {
91 tried = 1;
92 fn = (ck_f16_ggml_mul_mat_fn) dlsym(RTLD_DEFAULT, "ggml_mul_mat");
93 }
94 return fn;
95}
struct ggml_tensor *(* ck_f16_ggml_mul_mat_fn)(struct ggml_context *, struct ggml_tensor *, struct ggml_tensor *)

References RTLD_DEFAULT.

Referenced by gemm_nt_f16_ggml_strict().

◆ ck_f16_resolve_ggml_new_graph()

static ck_f16_ggml_new_graph_fn ck_f16_resolve_ggml_new_graph ( void  )
static

Definition at line 97 of file gemm_kernels_f16.c.

98{
99 static int tried = 0;
100 static ck_f16_ggml_new_graph_fn fn = NULL;
101 if (!tried) {
102 tried = 1;
103 fn = (ck_f16_ggml_new_graph_fn) dlsym(RTLD_DEFAULT, "ggml_new_graph");
104 }
105 return fn;
106}
struct ggml_cgraph *(* ck_f16_ggml_new_graph_fn)(struct ggml_context *)

References RTLD_DEFAULT.

Referenced by gemm_nt_f16_ggml_strict().

◆ ck_f16_resolve_ggml_new_tensor_2d()

static ck_f16_ggml_new_tensor_2d_fn ck_f16_resolve_ggml_new_tensor_2d ( void  )
static

Definition at line 75 of file gemm_kernels_f16.c.

76{
77 static int tried = 0;
78 static ck_f16_ggml_new_tensor_2d_fn fn = NULL;
79 if (!tried) {
80 tried = 1;
81 fn = (ck_f16_ggml_new_tensor_2d_fn) dlsym(RTLD_DEFAULT, "ggml_new_tensor_2d");
82 }
83 return fn;
84}
struct ggml_tensor *(* ck_f16_ggml_new_tensor_2d_fn)(struct ggml_context *, enum ggml_type, int64_t, int64_t)

References RTLD_DEFAULT.

Referenced by gemm_nt_f16_ggml_strict().

◆ ck_f32_to_f16_row_local()

static void ck_f32_to_f16_row_local ( uint16_t *  dst,
const float *  src,
int  n 
)
inlinestatic

Definition at line 292 of file gemm_kernels_f16.c.

293{
294#ifdef __AVX512F__
295 int i = 0;
296 const int n16 = (n / 16) * 16;
297 for (; i < n16; i += 16) {
298 const __m512 v = _mm512_loadu_ps(src + i);
299 const __m256i h = _mm512_cvtps_ph(v, 0);
300 _mm256_storeu_si256((__m256i *)(dst + i), h);
301 }
302 for (; i < n; ++i) {
303 dst[i] = fp32_to_fp16(src[i]);
304 }
305#elif defined(__F16C__) && defined(__AVX__)
306 int i = 0;
307 const int n8 = (n / 8) * 8;
308 for (; i < n8; i += 8) {
309 const __m256 v = _mm256_loadu_ps(src + i);
310 const __m128i h = _mm256_cvtps_ph(v, 0);
311 _mm_storeu_si128((__m128i *)(dst + i), h);
312 }
313 for (; i < n; ++i) {
314 dst[i] = fp32_to_fp16(src[i]);
315 }
316#else
317 for (int i = 0; i < n; ++i) {
318 dst[i] = fp32_to_fp16(src[i]);
319 }
320#endif
321}
#define fp32_to_fp16(x)

References fp32_to_fp16.

Referenced by ck_gemm_f16_input_fp16_work(), and gemm_f16_input_fp16_ref().

◆ ck_gemm_f16_input_fp16_work()

static void ck_gemm_f16_input_fp16_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 818 of file gemm_kernels_f16.c.

819{
820 ck_gemm_f16_input_fp16_args_t *args = (ck_gemm_f16_input_fp16_args_t *) opaque;
821 const int M = args->M;
822 const int N = args->N;
823 const int K = args->K;
824
825 const int token_groups = (N + 3) / 4;
826 for (int group = ith; group < token_groups; group += nth) {
827 const int n0 = group * 4;
828 const int token_count = N - n0 < 4 ? N - n0 : 4;
829#if defined(__F16C__) && defined(__AVX__) && !defined(__AVX512F__)
830 if (token_count == 4 && ck_gemm_f16_m4n2_enabled()) {
831 uint16_t x_f16[4][K];
832 for (int t = 0; t < 4; ++t) {
834 x_f16[t], args->X + (size_t)(n0 + t) * (size_t)K, K);
835 }
836
837 int row = 0;
838 for (; row + 1 < M; row += 2) {
839 float sums[4][2];
840 const uint16_t *w0 = args->W + (size_t)row * (size_t)K;
841 ck_dot_f16_f16_avx_m4n2(
842 w0, w0 + K,
843 x_f16[0], x_f16[1], x_f16[2], x_f16[3], K, sums);
844 for (int t = 0; t < 4; ++t) {
845 float *out = args->Y + (size_t)(n0 + t) * (size_t)M + (size_t)row;
846 out[0] = sums[t][0];
847 out[1] = sums[t][1];
848 }
849 }
850 for (; row < M; ++row) {
851 const uint16_t *w = args->W + (size_t)row * (size_t)K;
852 for (int t = 0; t < 4; ++t) {
853 args->Y[(size_t)(n0 + t) * (size_t)M + (size_t)row] =
854 ck_dot_f16_f16_local(w, x_f16[t], K);
855 }
856 }
857 continue;
858 }
859#endif
860 for (int n = n0; n < n0 + token_count; ++n) {
861 const float *x_row = args->X + (size_t)n * (size_t)K;
862 uint16_t x_f16[K];
863
864 ck_f32_to_f16_row_local(x_f16, x_row, K);
865
866 int row = 0;
867#if defined(__AVX512F__) && defined(__F16C__)
868 for (; row + 3 < M; row += 4) {
869 float sums[4];
870 ck_dot_f16_f16_avx512_4(
871 args->W + (size_t)row * (size_t)K, x_f16, K, sums);
872 args->Y[(size_t)n * (size_t)M + (size_t)row] = sums[0];
873 args->Y[(size_t)n * (size_t)M + (size_t)row + 1] = sums[1];
874 args->Y[(size_t)n * (size_t)M + (size_t)row + 2] = sums[2];
875 args->Y[(size_t)n * (size_t)M + (size_t)row + 3] = sums[3];
876 }
877#elif defined(__F16C__) && defined(__AVX__)
878 for (; row + 3 < M; row += 4) {
879 float sums[4];
880 ck_dot_f16_f16_avx4(
881 args->W + (size_t)row * (size_t)K, x_f16, K, sums);
882 args->Y[(size_t)n * (size_t)M + (size_t)row] = sums[0];
883 args->Y[(size_t)n * (size_t)M + (size_t)row + 1] = sums[1];
884 args->Y[(size_t)n * (size_t)M + (size_t)row + 2] = sums[2];
885 args->Y[(size_t)n * (size_t)M + (size_t)row + 3] = sums[3];
886 }
887#endif
888 for (; row < M; ++row) {
889 const uint16_t *w_row = args->W + (size_t)row * (size_t)K;
890 const float sum = ck_dot_f16_f16_local(w_row, x_f16, K);
891 args->Y[(size_t)n * (size_t)M + (size_t)row] = sum;
892 }
893 }
894 }
895}
static float ck_dot_f16_f16_local(const uint16_t *w, const uint16_t *x, int k)
static void ck_f32_to_f16_row_local(uint16_t *dst, const float *src, int n)

References ck_dot_f16_f16_local(), and ck_f32_to_f16_row_local().

Referenced by gemm_f16_input_fp16_threadpool().

◆ ck_gemm_f16_pick_active_threads()

static int ck_gemm_f16_pick_active_threads ( const ck_threadpool_t *  pool,
int  M,
int  N,
int  K 
)
static

Definition at line 913 of file gemm_kernels_f16.c.

914{
915 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
916 if (nth <= 1) return 1;
917
918 const char *cap_env = getenv("CK_F16_GEMM_THREAD_CAP");
919 int cap = cap_env && cap_env[0] ? atoi(cap_env) : 24;
920 if (cap < 1) cap = 1;
921 if (cap > nth) cap = nth;
922
923 int active = N;
924 if (M >= 1024 && K >= 1024 && active < 8) active = 8;
925 if (active > cap) active = cap;
926 if (active > nth) active = nth;
927 return active < 1 ? 1 : active;
928}
int ck_threadpool_n_threads(const ck_threadpool_t *pool)

References ck_threadpool_n_threads().

Referenced by gemm_f16_input_fp16_threadpool().

◆ ck_gemm_f16_threadpool_enabled()

static int ck_gemm_f16_threadpool_enabled ( int  M,
int  N,
int  K 
)
static

Definition at line 897 of file gemm_kernels_f16.c.

898{
899 const char *disable = getenv("CK_DISABLE_F16_GEMM_THREADPOOL");
900 if (disable && disable[0] && strcmp(disable, "0") != 0) return 0;
901 if (M < 256 || N < 16 || K < 256) return 0;
902 return 1;
903}

Referenced by gemm_f16_input_fp16_threadpool().

◆ ck_gemm_nt_f16_ggml_oracle()

int ck_gemm_nt_f16_ggml_oracle ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 262 of file gemm_kernels_f16.c.

269{
270 return gemm_nt_f16_ggml_strict(A, B, bias, C, M, N, K);
271}
static int gemm_nt_f16_ggml_strict(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
#define C(color)
Definition show_config.c:39

References C, and gemm_nt_f16_ggml_strict().

◆ ck_gemm_nt_f16_simd_lanes()

int ck_gemm_nt_f16_simd_lanes ( void  )

Definition at line 583 of file gemm_kernels_f16.c.

584{
585#if defined(__AVX512F__) && defined(__F16C__)
586 return 16;
587#elif defined(__F16C__) && defined(__AVX__)
588 return 8;
589#else
590 return 1;
591#endif
592}

◆ convert_f16_to_f32()

void convert_f16_to_f32 ( float *  dst,
const uint16_t *  src,
size_t  count 
)

Convert FP16 tensor to FP32.

Definition at line 1047 of file gemm_kernels_f16.c.

1048{
1049#ifdef __AVX512F__
1050 const size_t count16 = count / 16 * 16;
1051
1052 for (size_t i = 0; i < count16; i += 16) {
1053 __m256i f16 = _mm256_loadu_si256((const __m256i *)&src[i]);
1054 __m512 f32 = _mm512_cvtph_ps(f16);
1055 _mm512_storeu_ps(&dst[i], f32);
1056 }
1057
1058 for (size_t i = count16; i < count; i++) {
1059 dst[i] = fp16_to_fp32(src[i]);
1060 }
1061#else
1062 for (size_t i = 0; i < count; i++) {
1063 dst[i] = fp16_to_fp32(src[i]);
1064 }
1065#endif
1066}

References fp16_to_fp32.

◆ convert_f32_to_f16()

void convert_f32_to_f16 ( uint16_t *  dst,
const float *  src,
size_t  count 
)

Convert FP32 tensor to FP16.

Definition at line 1071 of file gemm_kernels_f16.c.

1072{
1073#ifdef __AVX512F__
1074 const size_t count16 = count / 16 * 16;
1075
1076 for (size_t i = 0; i < count16; i += 16) {
1077 __m512 f32 = _mm512_loadu_ps(&src[i]);
1078 __m256i f16 = _mm512_cvtps_ph(f32, 0);
1079 _mm256_storeu_si256((__m256i *)&dst[i], f16);
1080 }
1081
1082 for (size_t i = count16; i < count; i++) {
1083 dst[i] = fp32_to_fp16(src[i]);
1084 }
1085#else
1086 for (size_t i = 0; i < count; i++) {
1087 dst[i] = fp32_to_fp16(src[i]);
1088 }
1089#endif
1090}

References fp32_to_fp16.

◆ dot_f16()

float dot_f16 ( const uint16_t *  w_f16,
const float *  x,
int  K 
)

Definition at line 1208 of file gemm_kernels_f16.c.

1209{
1210 float result;
1211 gemv_f16(&result, w_f16, x, 1, K);
1212 return result;
1213}
void gemv_f16(float *y, const uint16_t *W, const float *x, int M, int K)
Auto-dispatch GEMV based on available SIMD.

References gemv_f16().

◆ gemm_f16()

void gemm_f16 ( float *  Y,
const uint16_t *  W,
const float *  X,
int  M,
int  N,
int  K 
)

Auto-dispatch GEMM based on available SIMD.

Definition at line 752 of file gemm_kernels_f16.c.

756{
757#ifdef __AVX512F__
758 gemm_f16_avx512(Y, W, X, M, N, K);
759#else
760 gemm_f16_ref(Y, W, X, M, N, K);
761#endif
762}
void gemm_f16_ref(float *Y, const uint16_t *W, const float *X, int M, int N, int K)
Matrix-matrix multiply with FP16 weights (scalar reference)

References gemm_f16_ref().

◆ gemm_f16_backward()

void gemm_f16_backward ( float *  dX,
const uint16_t *  W,
const float *  dY,
int  M,
int  N,
int  K 
)

Batched backward pass.

Definition at line 1194 of file gemm_kernels_f16.c.

1198{
1199 for (int n = 0; n < N; n++) {
1200 gemv_f16_backward(&dX[n * K], W, &dY[n * M], M, K);
1201 }
1202}
void gemv_f16_backward(float *dX, const uint16_t *W, const float *dY, int M, int K)
Auto-dispatch backward.

References gemv_f16_backward().

◆ gemm_f16_input_fp16_ref()

static void gemm_f16_input_fp16_ref ( float *  Y,
const uint16_t *  W,
const float *  X,
int  M,
int  N,
int  K 
)
static

Definition at line 764 of file gemm_kernels_f16.c.

768{
769#pragma omp parallel for schedule(static) if(N > 1)
770 for (int n = 0; n < N; ++n) {
771 const float *x_row = &X[(size_t)n * (size_t)K];
772 uint16_t x_f16[K];
773
774 ck_f32_to_f16_row_local(x_f16, x_row, K);
775
776 int row = 0;
777#if defined(__AVX512F__) && defined(__F16C__)
778 for (; row + 3 < M; row += 4) {
779 float sums[4];
780 ck_dot_f16_f16_avx512_4(
781 &W[(size_t)row * (size_t)K], x_f16, K, sums);
782 Y[(size_t)n * (size_t)M + (size_t)row] = sums[0];
783 Y[(size_t)n * (size_t)M + (size_t)row + 1] = sums[1];
784 Y[(size_t)n * (size_t)M + (size_t)row + 2] = sums[2];
785 Y[(size_t)n * (size_t)M + (size_t)row + 3] = sums[3];
786 }
787#elif defined(__F16C__) && defined(__AVX__)
788 for (; row + 3 < M; row += 4) {
789 float sums[4];
790 ck_dot_f16_f16_avx4(&W[(size_t)row * (size_t)K], x_f16, K, sums);
791 Y[(size_t)n * (size_t)M + (size_t)row] = sums[0];
792 Y[(size_t)n * (size_t)M + (size_t)row + 1] = sums[1];
793 Y[(size_t)n * (size_t)M + (size_t)row + 2] = sums[2];
794 Y[(size_t)n * (size_t)M + (size_t)row + 3] = sums[3];
795 }
796#endif
797 for (; row < M; ++row) {
798 const uint16_t *w_row = &W[(size_t)row * (size_t)K];
799 const float sum = ck_dot_f16_f16_local(w_row, x_f16, K);
800 Y[(size_t)n * (size_t)M + (size_t)row] = sum;
801 }
802 }
803}

References ck_dot_f16_f16_local(), and ck_f32_to_f16_row_local().

Referenced by gemm_nt_f16().

◆ gemm_f16_input_fp16_threadpool()

static int gemm_f16_input_fp16_threadpool ( float *  Y,
const uint16_t *  W,
const float *  X,
int  M,
int  N,
int  K 
)
static

Definition at line 930 of file gemm_kernels_f16.c.

934{
935 if (!ck_gemm_f16_threadpool_enabled(M, N, K)) {
936 return 0;
937 }
938
939 ck_threadpool_t *pool = ck_threadpool_global();
940 const int active = ck_gemm_f16_pick_active_threads(pool, M, N, K);
941 if (!pool || active <= 1) {
942 return 0;
943 }
944
945 ck_gemm_f16_input_fp16_args_t args = {
946 .Y = Y,
947 .W = W,
948 .X = X,
949 .M = M,
950 .N = N,
951 .K = K,
952 };
954 return 1;
955}
void ck_threadpool_dispatch_n(ck_threadpool_t *pool, int active_threads, ck_work_fn_t fn, void *args)
ck_threadpool_t * ck_threadpool_global(void)
static int ck_gemm_f16_pick_active_threads(const ck_threadpool_t *pool, int M, int N, int K)
static void ck_gemm_f16_input_fp16_work(int ith, int nth, void *opaque)
static int ck_gemm_f16_threadpool_enabled(int M, int N, int K)

References ck_gemm_f16_input_fp16_work(), ck_gemm_f16_pick_active_threads(), ck_gemm_f16_threadpool_enabled(), ck_threadpool_dispatch_n(), and ck_threadpool_global().

Referenced by gemm_nt_f16().

◆ gemm_f16_ref()

void gemm_f16_ref ( float *  Y,
const uint16_t *  W,
const float *  X,
int  M,
int  N,
int  K 
)

Matrix-matrix multiply with FP16 weights (scalar reference)

Parameters
YOutput matrix [M x N]
WWeight matrix in FP16 [M x K]
XInput matrix [K x N]
MNumber of output rows
NBatch size
KHidden dimension

Definition at line 699 of file gemm_kernels_f16.c.

703{
704 for (int n = 0; n < N; n++) {
705 gemv_f16_ref(&Y[n * M], W, &X[n * K], M, K);
706 }
707}
void gemv_f16_ref(float *y, const uint16_t *W, const float *x, int M, int K)
Matrix-vector multiply with FP16 weights (scalar reference)

References gemv_f16_ref().

Referenced by gemm_f16().

◆ gemm_nt_f16()

void gemm_nt_f16 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

NT GEMM wrapper for FP16 weights with the engine's standard ABI.

Contract: A: [M, K] fp32 activation matrix B: [N, K] fp16 weight matrix stored row-major (transposed layout) C: [M, N] fp32 output matrix

This wrapper follows llama.cpp's CPU F16 mul_mat contract: activation rows are rounded to FP16 first, then the dot runs as F16 x F16 with FP32 output accumulation. The lower-level gemm_f16() helper remains the direct F16-weight x FP32-activation operator for generic use.

Definition at line 970 of file gemm_kernels_f16.c.

975{
977 gemm_nt_f16_ggml_strict(A, B, bias, C, M, N, K)) {
978 return;
979 }
980
981 if (!gemm_f16_input_fp16_threadpool(C, (const uint16_t *)B, A, N, M, K)) {
982 gemm_f16_input_fp16_ref(C, (const uint16_t *)B, A, N, M, K);
983 }
984
985 if (!bias) {
986 return;
987 }
988
989#pragma omp parallel for schedule(static) if(M > 1)
990 for (int i = 0; i < M; ++i) {
991 float *c_row = C + (size_t)i * (size_t)N;
992 for (int j = 0; j < N; ++j) {
993 c_row[j] += bias[j];
994 }
995 }
996}
int ck_strict_parity_enabled(void)
static void gemm_f16_input_fp16_ref(float *Y, const uint16_t *W, const float *X, int M, int N, int K)
static int gemm_f16_input_fp16_threadpool(float *Y, const uint16_t *W, const float *X, int M, int N, int K)

References C, ck_strict_parity_enabled(), gemm_f16_input_fp16_ref(), gemm_f16_input_fp16_threadpool(), and gemm_nt_f16_ggml_strict().

◆ gemm_nt_f16_clipped()

void gemm_nt_f16_clipped ( const float *  A,
const void *  B,
const float *  bias,
const float *  input_min,
const float *  input_max,
const float *  output_min,
const float *  output_max,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 998 of file gemm_kernels_f16.c.

1007{
1008 const float in_min = input_min ? input_min[0] : -3.4028234663852886e38f;
1009 const float in_max = input_max ? input_max[0] : 3.4028234663852886e38f;
1010 const float out_min = output_min ? output_min[0] : -3.4028234663852886e38f;
1011 const float out_max = output_max ? output_max[0] : 3.4028234663852886e38f;
1012 const uint16_t *W = (const uint16_t *)B;
1013
1014#pragma omp parallel for schedule(static) if(M > 1)
1015 for (int m = 0; m < M; ++m) {
1016 const float *a_row = A + (size_t)m * (size_t)K;
1017 uint16_t a_f16[K];
1018
1019 for (int k = 0; k < K; ++k) {
1020 float x = a_row[k];
1021 if (x < in_min) x = in_min;
1022 if (x > in_max) x = in_max;
1023 a_f16[k] = fp32_to_fp16(x);
1024 }
1025
1026 float *c_row = C + (size_t)m * (size_t)N;
1027 for (int n = 0; n < N; ++n) {
1028 const uint16_t *w_row = W + (size_t)n * (size_t)K;
1029 float sum = bias ? bias[n] : 0.0f;
1030 for (int k = 0; k < K; ++k) {
1031 sum += fp16_to_fp32(w_row[k]) * fp16_to_fp32(a_f16[k]);
1032 }
1033 if (sum < out_min) sum = out_min;
1034 if (sum > out_max) sum = out_max;
1035 c_row[n] = sum;
1036 }
1037 }
1038}

References C, fp16_to_fp32, and fp32_to_fp16.

◆ gemm_nt_f16_ggml_strict()

static int gemm_nt_f16_ggml_strict ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)
static

Definition at line 163 of file gemm_kernels_f16.c.

170{
181
182 if (!ggml_cpu_init_fn || !ggml_init_fn || !ggml_free_fn || !ggml_new_tensor_2d_fn ||
183 !ggml_mul_mat_fn || !ggml_new_graph_fn || !ggml_build_forward_expand_fn ||
184 !ggml_graph_compute_with_ctx_fn || !ggml_get_data_fn || !ggml_get_data_f32_fn) {
185 return 0;
186 }
187
188 ggml_cpu_init_fn();
189
190 const size_t output_bytes = (size_t) M * (size_t) N * sizeof(float);
191 const size_t mem_size = ((size_t) 128 * 1024 * 1024) + output_bytes;
192
193 struct ggml_init_params params = {
195 .mem_buffer = NULL,
196 .no_alloc = false,
197 };
198 struct ggml_context *ctx = ggml_init_fn(params);
199 if (!ctx) {
200 return 0;
201 }
202
203 int ok = 0;
204 struct ggml_tensor *w = ggml_new_tensor_2d_fn(ctx, GGML_TYPE_F16, K, N);
205 struct ggml_tensor *x = ggml_new_tensor_2d_fn(ctx, GGML_TYPE_F32, K, M);
206 if (!w || !x) {
207 ggml_free_fn(ctx);
208 return 0;
209 }
210
211 {
212 void *w_data = ggml_get_data_fn(w);
213 void *x_data = ggml_get_data_fn(x);
214 if (!w_data || !x_data) {
215 ggml_free_fn(ctx);
216 return 0;
217 }
218 memcpy(w_data, B, (size_t) K * (size_t) N * sizeof(uint16_t));
219 memcpy(x_data, A, (size_t) K * (size_t) M * sizeof(float));
220 }
221
222 struct ggml_tensor *y = ggml_mul_mat_fn(ctx, w, x);
223 if (!y) {
224 ggml_free_fn(ctx);
225 return 0;
226 }
227
228 struct ggml_cgraph *gf = ggml_new_graph_fn(ctx);
229 if (!gf) {
230 ggml_free_fn(ctx);
231 return 0;
232 }
233 ggml_build_forward_expand_fn(gf, y);
234 if (ggml_graph_compute_with_ctx_fn(ctx, gf, 1) != GGML_STATUS_SUCCESS) {
235 ggml_free_fn(ctx);
236 return 0;
237 }
238
239 {
240 const float *src = ggml_get_data_f32_fn(y);
241 if (!src) {
242 ggml_free_fn(ctx);
243 return 0;
244 }
245 for (int m = 0; m < M; ++m) {
246 memcpy(C + (size_t) m * (size_t) N,
247 src + (size_t) m * (size_t) N,
248 (size_t) N * sizeof(float));
249 if (bias) {
250 for (int n = 0; n < N; ++n) {
251 C[(size_t) m * (size_t) N + (size_t) n] += bias[n];
252 }
253 }
254 }
255 }
256
257 ok = 1;
258 ggml_free_fn(ctx);
259 return ok;
260}
static ck_f16_ggml_init_fn ck_f16_resolve_ggml_init(void)
static ck_f16_ggml_graph_compute_with_ctx_fn ck_f16_resolve_ggml_graph_compute_with_ctx(void)
static ck_f16_ggml_cpu_init_fn ck_f16_resolve_ggml_cpu_init(void)
static ck_f16_ggml_build_forward_expand_fn ck_f16_resolve_ggml_build_forward_expand(void)
static ck_f16_ggml_get_data_f32_fn ck_f16_resolve_ggml_get_data_f32(void)
static ck_f16_ggml_new_tensor_2d_fn ck_f16_resolve_ggml_new_tensor_2d(void)
static ck_f16_ggml_mul_mat_fn ck_f16_resolve_ggml_mul_mat(void)
static ck_f16_ggml_get_data_fn ck_f16_resolve_ggml_get_data(void)
static ck_f16_ggml_new_graph_fn ck_f16_resolve_ggml_new_graph(void)
static ck_f16_ggml_free_fn ck_f16_resolve_ggml_free(void)
@ GGML_STATUS_SUCCESS
@ GGML_TYPE_F32
@ GGML_TYPE_F16

References C, ck_f16_resolve_ggml_build_forward_expand(), ck_f16_resolve_ggml_cpu_init(), ck_f16_resolve_ggml_free(), ck_f16_resolve_ggml_get_data(), ck_f16_resolve_ggml_get_data_f32(), ck_f16_resolve_ggml_graph_compute_with_ctx(), ck_f16_resolve_ggml_init(), ck_f16_resolve_ggml_mul_mat(), ck_f16_resolve_ggml_new_graph(), ck_f16_resolve_ggml_new_tensor_2d(), GGML_STATUS_SUCCESS, GGML_TYPE_F16, GGML_TYPE_F32, and ggml_init_params::mem_size.

Referenced by ck_gemm_nt_f16_ggml_oracle(), and gemm_nt_f16().

◆ gemv_f16()

void gemv_f16 ( float *  y,
const uint16_t *  W,
const float *  x,
int  M,
int  K 
)

Auto-dispatch GEMV based on available SIMD.

Definition at line 673 of file gemm_kernels_f16.c.

677{
678#ifdef __AVX512F__
679 gemv_f16_avx512(y, W, x, M, K);
680#else
681 gemv_f16_ref(y, W, x, M, K);
682#endif
683}

References gemv_f16_ref().

Referenced by dot_f16().

◆ gemv_f16_backward()

void gemv_f16_backward ( float *  dX,
const uint16_t *  W,
const float *  dY,
int  M,
int  K 
)

Auto-dispatch backward.

Definition at line 1179 of file gemm_kernels_f16.c.

1183{
1184#ifdef __AVX512F__
1185 gemv_f16_backward_avx512(dX, W, dY, M, K);
1186#else
1187 gemv_f16_backward_ref(dX, W, dY, M, K);
1188#endif
1189}
void gemv_f16_backward_ref(float *dX, const uint16_t *W, const float *dY, int M, int K)
Backward pass: compute input gradient (scalar reference)

References gemv_f16_backward_ref().

Referenced by gemm_f16_backward().

◆ gemv_f16_backward_ref()

void gemv_f16_backward_ref ( float *  dX,
const uint16_t *  W,
const float *  dY,
int  M,
int  K 
)

Backward pass: compute input gradient (scalar reference)

Parameters
dXOutput gradient w.r.t. input [K]
WWeight matrix in FP16 format [M x K]
dYGradient w.r.t. output [M]
MNumber of output rows
KNumber of columns (input dimension)

Definition at line 1110 of file gemm_kernels_f16.c.

1114{
1115 /* Zero output gradient */
1116 for (int k = 0; k < K; k++) {
1117 dX[k] = 0.0f;
1118 }
1119
1120 /* Accumulate: dX += W^T @ dY */
1121 for (int row = 0; row < M; row++) {
1122 const float dy = dY[row];
1123 const uint16_t *w_row = &W[row * K];
1124
1125 for (int k = 0; k < K; k++) {
1126 float w = fp16_to_fp32(w_row[k]);
1127 dX[k] += w * dy;
1128 }
1129 }
1130}

References fp16_to_fp32.

Referenced by gemv_f16_backward().

◆ gemv_f16_ref()

void gemv_f16_ref ( float *  y,
const uint16_t *  W,
const float *  x,
int  M,
int  K 
)

Matrix-vector multiply with FP16 weights (scalar reference)

Parameters
yOutput vector [M]
WWeight matrix in FP16 [M x K]
xInput vector [K]
MNumber of output rows
KNumber of columns

Definition at line 607 of file gemm_kernels_f16.c.

611{
612 for (int row = 0; row < M; row++) {
613 float sum = 0.0f;
614 const uint16_t *w_row = &W[row * K];
615
616 for (int k = 0; k < K; k++) {
617 float w = fp16_to_fp32(w_row[k]);
618 sum += w * x[k];
619 }
620
621 y[row] = sum;
622 }
623}

References fp16_to_fp32.

Referenced by gemm_f16_ref(), and gemv_f16().