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

GELU activation kernels with SIMD (SSE/AVX/AVX512) More...

#include <math.h>
#include <stddef.h>
#include <pthread.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include "bf16_utils.h"
#include "ck_threadpool.h"
#include "ckernel_quant.h"

Go to the source code of this file.

Macros

#define _GNU_SOURCE
 

Typedefs

typedef void(* ck_gelu_ggml_cpu_init_fn) (void)
 
typedef float(* ck_gelu_ggml_fp16_to_fp32_fn) (ck_half)
 
typedef ck_half(* ck_gelu_ggml_fp32_to_fp16_fn) (float)
 
typedef float(* ck_gelu_math_f32_fn) (float)
 
typedef double(* ck_gelu_math_f64_fn) (double)
 

Functions

static void ck_gelu_erf_fp64_parallel_work (int ith, int nth, void *opaque)
 
static void ck_gelu_ggml_runtime_init (void)
 
static void ck_gelu_ggml_table_init (void)
 
static void ck_gelu_reference_math_init (void)
 
static ck_gelu_math_f64_fn ck_gelu_system_erf (void)
 
static ck_gelu_math_f32_fn ck_gelu_system_tanhf (void)
 
static float ck_gelu_tanh_f32 (float x)
 
static float ck_gelu_tanh_ggml_reference_f32 (float x)
 
static void ck_gelu_try_bind_runtime (void *handle)
 
void gelu_backward_exact (const float *input, const float *d_output, float *d_input, size_t n)
 
void gelu_backward_fast (const float *input, const float *d_output, float *d_input, size_t n)
 
void gelu_backward_scalar (const float *input, const float *d_output, float *d_input, size_t n)
 
void gelu_erf_bf16_storage (float *data, size_t n)
 
void gelu_erf_fp64_f32_inplace (float *data, size_t n)
 
void gelu_erf_fp64_f32_parallel_dispatch (float *data, size_t n)
 
void gelu_exact_inplace (float *data, size_t n)
 
void gelu_fast_inplace (float *data, size_t n)
 
void gelu_ggml_inplace (float *data, size_t n)
 
void gelu_ggml_native_inplace (float *data, size_t n)
 
void gelu_pytorch_erf_f32_inplace (float *data, size_t n)
 
void gelu_pytorch_erf_sleef_bf16_storage (float *data, size_t n)
 
void gelu_pytorch_tanh_bf16_storage (float *data, size_t n)
 

Variables

static pthread_once_t ck_gelu_ggml_runtime_once = PTHREAD_ONCE_INIT
 
static ck_half ck_gelu_ggml_table_f16 [1u<< 16]
 
static pthread_once_t ck_gelu_ggml_table_once = PTHREAD_ONCE_INIT
 
static ck_gelu_math_f64_fn ck_gelu_reference_erf = NULL
 
static pthread_once_t ck_gelu_reference_math_once = PTHREAD_ONCE_INIT
 
static ck_gelu_math_f32_fn ck_gelu_reference_tanhf = NULL
 
static ck_gelu_ggml_fp16_to_fp32_fn ck_gelu_runtime_fp16_to_fp32 = NULL
 
static ck_gelu_ggml_fp32_to_fp16_fn ck_gelu_runtime_fp32_to_fp16 = NULL
 
static void * ck_gelu_runtime_handle = NULL
 
static int ck_gelu_runtime_ready = 0
 
static const ck_half * ck_gelu_runtime_table_f16 = NULL
 

Detailed Description

GELU activation kernels with SIMD (SSE/AVX/AVX512)

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

GELU: y = x * 0.5 * (1 + erf(x / sqrt(2))) Fast approx: y = x * sigmoid(1.702 * x)

Definition in file gelu_kernels.c.

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 19 of file gelu_kernels.c.

Typedef Documentation

◆ ck_gelu_ggml_cpu_init_fn

typedef void(* ck_gelu_ggml_cpu_init_fn) (void)

Definition at line 49 of file gelu_kernels.c.

◆ ck_gelu_ggml_fp16_to_fp32_fn

typedef float(* ck_gelu_ggml_fp16_to_fp32_fn) (ck_half)

Definition at line 51 of file gelu_kernels.c.

◆ ck_gelu_ggml_fp32_to_fp16_fn

typedef ck_half(* ck_gelu_ggml_fp32_to_fp16_fn) (float)

Definition at line 50 of file gelu_kernels.c.

◆ ck_gelu_math_f32_fn

typedef float(* ck_gelu_math_f32_fn) (float)

Definition at line 52 of file gelu_kernels.c.

◆ ck_gelu_math_f64_fn

typedef double(* ck_gelu_math_f64_fn) (double)

Definition at line 53 of file gelu_kernels.c.

Function Documentation

◆ ck_gelu_erf_fp64_parallel_work()

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

Definition at line 585 of file gelu_kernels.c.

586{
587 const double inv_sqrt_2 = 0.707106781186547524400844362104849039;
588 ck_gelu_erf_fp64_parallel_args_t *args =
589 (ck_gelu_erf_fp64_parallel_args_t *)opaque;
590 const size_t width = args->n / (size_t)nth;
591 const size_t remainder = args->n % (size_t)nth;
592 const size_t begin = (size_t)ith * width +
593 ((size_t)ith < remainder ? (size_t)ith : remainder);
594 const size_t end = begin + width + ((size_t)ith < remainder ? 1u : 0u);
595
596 for (size_t i = begin; i < end; ++i) {
597 const float x = args->data[i];
598 const double scaled = (double)x * inv_sqrt_2;
599 const double erf_value = args->reference_erf
600 ? args->reference_erf(scaled)
601 : erf(scaled);
602 args->data[i] = (float)(0.5 * (double)x * (1.0 + erf_value));
603 }
604}
uint32_t end
Definition utf8.c:215

References end.

Referenced by gelu_erf_fp64_f32_parallel_dispatch().

◆ ck_gelu_ggml_runtime_init()

static void ck_gelu_ggml_runtime_init ( void  )
static

Definition at line 120 of file gelu_kernels.c.

120 {
123 return;
124 }
125
126 ck_gelu_runtime_handle = dlopen("llama.cpp/build/bin/libggml-cpu.so", RTLD_LAZY | RTLD_LOCAL);
129 }
130}
#define RTLD_DEFAULT
static void * ck_gelu_runtime_handle
static int ck_gelu_runtime_ready
static void ck_gelu_try_bind_runtime(void *handle)

References ck_gelu_runtime_handle, ck_gelu_runtime_ready, ck_gelu_try_bind_runtime(), and RTLD_DEFAULT.

Referenced by gelu_ggml_inplace().

◆ ck_gelu_ggml_table_init()

static void ck_gelu_ggml_table_init ( void  )
static

Definition at line 132 of file gelu_kernels.c.

132 {
133 for (uint32_t i = 0; i < (1u << 16); ++i) {
134 const ck_half x_fp16 = (ck_half) i;
135 const float x = ggml_fp16_to_fp32(x_fp16);
136 const float y = ck_gelu_tanh_ggml_reference_f32(x);
138 }
139}
#define ggml_fp32_to_fp16
uint16_t ck_half
#define ggml_fp16_to_fp32
static ck_half ck_gelu_ggml_table_f16[1u<< 16]
static float ck_gelu_tanh_ggml_reference_f32(float x)

References ck_gelu_ggml_table_f16, ck_gelu_tanh_ggml_reference_f32(), ggml_fp16_to_fp32, and ggml_fp32_to_fp16.

Referenced by gelu_ggml_inplace(), and gelu_ggml_native_inplace().

◆ ck_gelu_reference_math_init()

static void ck_gelu_reference_math_init ( void  )
static

Definition at line 64 of file gelu_kernels.c.

64 {
65#if defined(__linux__)
66 void *handle = dlopen("libm.so.6", RTLD_NOW | RTLD_LOCAL);
67 if (handle) {
68 ck_gelu_reference_tanhf = (ck_gelu_math_f32_fn) dlsym(handle, "tanhf");
69 ck_gelu_reference_erf = (ck_gelu_math_f64_fn) dlsym(handle, "erf");
70 }
71#endif
72}
double(* ck_gelu_math_f64_fn)(double)
float(* ck_gelu_math_f32_fn)(float)
static ck_gelu_math_f32_fn ck_gelu_reference_tanhf
static ck_gelu_math_f64_fn ck_gelu_reference_erf

References ck_gelu_reference_erf, and ck_gelu_reference_tanhf.

Referenced by ck_gelu_system_erf(), and ck_gelu_system_tanhf().

◆ ck_gelu_system_erf()

static ck_gelu_math_f64_fn ck_gelu_system_erf ( void  )
static

Definition at line 79 of file gelu_kernels.c.

79 {
82}
static void ck_gelu_reference_math_init(void)
static pthread_once_t ck_gelu_reference_math_once

References ck_gelu_reference_erf, ck_gelu_reference_math_init(), and ck_gelu_reference_math_once.

Referenced by gelu_erf_bf16_storage(), gelu_erf_fp64_f32_inplace(), and gelu_erf_fp64_f32_parallel_dispatch().

◆ ck_gelu_system_tanhf()

static ck_gelu_math_f32_fn ck_gelu_system_tanhf ( void  )
static

◆ ck_gelu_tanh_f32()

static float ck_gelu_tanh_f32 ( float  x)
inlinestatic

Definition at line 37 of file gelu_kernels.c.

37 {
38 const float sqrt_2_over_pi = 0.7978845608f;
39 const float coeff = 0.044715f;
40 const float x3 = x * x * x;
41 const float inner = sqrt_2_over_pi * (x + coeff * x3);
42 return 0.5f * x * (1.0f + tanhf(inner));
43}

Referenced by gelu_exact_inplace().

◆ ck_gelu_tanh_ggml_reference_f32()

static float ck_gelu_tanh_ggml_reference_f32 ( float  x)
static

Definition at line 87 of file gelu_kernels.c.

87 {
88 const float gelu_coef_a = 0.044715f;
89 const float sqrt_2_over_pi = 0.79788456080286535588f;
90 ck_gelu_math_f32_fn reference_tanhf = ck_gelu_system_tanhf();
91 const float inner = sqrt_2_over_pi * x * (1.0f + gelu_coef_a * x * x);
92 const float tanh_value = reference_tanhf ? reference_tanhf(inner) : tanhf(inner);
93 return 0.5f * x * (1.0f + tanh_value);
94}
static ck_gelu_math_f32_fn ck_gelu_system_tanhf(void)

References ck_gelu_system_tanhf().

Referenced by ck_gelu_ggml_table_init().

◆ ck_gelu_try_bind_runtime()

static void ck_gelu_try_bind_runtime ( void *  handle)
static

Definition at line 99 of file gelu_kernels.c.

99 {
100 ck_gelu_ggml_cpu_init_fn cpu_init_fn =
101 (ck_gelu_ggml_cpu_init_fn) dlsym(handle, "ggml_cpu_init");
102 ck_gelu_ggml_fp32_to_fp16_fn fp32_to_fp16_fn =
103 (ck_gelu_ggml_fp32_to_fp16_fn) dlsym(handle, "ggml_fp32_to_fp16");
104 ck_gelu_ggml_fp16_to_fp32_fn fp16_to_fp32_fn =
105 (ck_gelu_ggml_fp16_to_fp32_fn) dlsym(handle, "ggml_fp16_to_fp32");
106 const ck_half *table =
107 (const ck_half *) dlsym(handle, "ggml_table_gelu_f16");
108
109 if (!cpu_init_fn || !fp32_to_fp16_fn || !fp16_to_fp32_fn || !table) {
110 return;
111 }
112
113 cpu_init_fn();
115 ck_gelu_runtime_fp32_to_fp16 = fp32_to_fp16_fn;
116 ck_gelu_runtime_fp16_to_fp32 = fp16_to_fp32_fn;
118}
float(* ck_gelu_ggml_fp16_to_fp32_fn)(ck_half)
static const ck_half * ck_gelu_runtime_table_f16
ck_half(* ck_gelu_ggml_fp32_to_fp16_fn)(float)
static ck_gelu_ggml_fp32_to_fp16_fn ck_gelu_runtime_fp32_to_fp16
static ck_gelu_ggml_fp16_to_fp32_fn ck_gelu_runtime_fp16_to_fp32
void(* ck_gelu_ggml_cpu_init_fn)(void)

References ck_gelu_runtime_fp16_to_fp32, ck_gelu_runtime_fp32_to_fp16, ck_gelu_runtime_ready, and ck_gelu_runtime_table_f16.

Referenced by ck_gelu_ggml_runtime_init().

◆ gelu_backward_exact()

void gelu_backward_exact ( const float *  input,
const float *  d_output,
float *  d_input,
size_t  n 
)

Definition at line 369 of file gelu_kernels.c.

373{
374 const float sqrt_2_over_pi = 0.7978845608f;
375 const float coeff = 0.044715f;
376
377#if defined(__AVX512F__)
378 const __m512 sqrt_2_pi_vec = _mm512_set1_ps(sqrt_2_over_pi);
379 const __m512 coeff_vec = _mm512_set1_ps(coeff);
380 const __m512 coeff3_vec = _mm512_set1_ps(3.0f * coeff);
381 const __m512 half_vec = _mm512_set1_ps(0.5f);
382 const __m512 one_vec = _mm512_set1_ps(1.0f);
383
384 size_t i = 0;
385 for (; i + 16 <= n; i += 16) {
386 __m512 x = _mm512_loadu_ps(&input[i]);
387 __m512 dy = _mm512_loadu_ps(&d_output[i]);
388
389 __m512 x2 = _mm512_mul_ps(x, x);
390 __m512 x3 = _mm512_mul_ps(x2, x);
391
392 // g = sqrt(2/pi) * (x + 0.044715 * x^3)
393 __m512 g = _mm512_fmadd_ps(coeff_vec, x3, x);
394 g = _mm512_mul_ps(sqrt_2_pi_vec, g);
395
396 __m512 tanh_g = tanh512_fast(g);
397
398 // g' = sqrt(2/pi) * (1 + 3 * 0.044715 * x^2)
399 __m512 g_prime = _mm512_fmadd_ps(coeff3_vec, x2, one_vec);
400 g_prime = _mm512_mul_ps(sqrt_2_pi_vec, g_prime);
401
402 // sech^2(g) = 1 - tanh^2(g)
403 __m512 sech2_g = _mm512_fnmadd_ps(tanh_g, tanh_g, one_vec);
404
405 // gelu_derivative = 0.5 * (1 + tanh_g) + 0.5 * x * sech2_g * g_prime
406 __m512 term1 = _mm512_mul_ps(half_vec, _mm512_add_ps(one_vec, tanh_g));
407 __m512 term2 = _mm512_mul_ps(half_vec, _mm512_mul_ps(x, _mm512_mul_ps(sech2_g, g_prime)));
408 __m512 gelu_deriv = _mm512_add_ps(term1, term2);
409
410 __m512 result = _mm512_mul_ps(dy, gelu_deriv);
411 _mm512_storeu_ps(&d_input[i], result);
412 }
413 // Handle remaining elements
414 for (; i < n; ++i) {
415 float x = input[i];
416 float x3 = x * x * x;
417 float g = sqrt_2_over_pi * (x + coeff * x3);
418 float tanh_g = tanhf(g);
419 float x2 = x * x;
420 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * x2);
421 float sech2_g = 1.0f - tanh_g * tanh_g;
422 float gelu_derivative = 0.5f * (1.0f + tanh_g) + 0.5f * x * sech2_g * g_prime;
423 d_input[i] = d_output[i] * gelu_derivative;
424 }
425
426#elif defined(__AVX2__)
427 const __m256 sqrt_2_pi_vec = _mm256_set1_ps(sqrt_2_over_pi);
428 const __m256 coeff_vec = _mm256_set1_ps(coeff);
429 const __m256 coeff3_vec = _mm256_set1_ps(3.0f * coeff);
430 const __m256 half_vec = _mm256_set1_ps(0.5f);
431 const __m256 one_vec = _mm256_set1_ps(1.0f);
432
433 size_t i = 0;
434 for (; i + 8 <= n; i += 8) {
435 __m256 x = _mm256_loadu_ps(&input[i]);
436 __m256 dy = _mm256_loadu_ps(&d_output[i]);
437
438 __m256 x2 = _mm256_mul_ps(x, x);
439 __m256 x3 = _mm256_mul_ps(x2, x);
440
441 // g = sqrt(2/pi) * (x + 0.044715 * x^3)
442 __m256 g = _mm256_fmadd_ps(coeff_vec, x3, x);
443 g = _mm256_mul_ps(sqrt_2_pi_vec, g);
444
445 __m256 tanh_g = tanh256_fast(g);
446
447 // g' = sqrt(2/pi) * (1 + 3 * 0.044715 * x^2)
448 __m256 g_prime = _mm256_fmadd_ps(coeff3_vec, x2, one_vec);
449 g_prime = _mm256_mul_ps(sqrt_2_pi_vec, g_prime);
450
451 // sech^2(g) = 1 - tanh^2(g)
452 __m256 sech2_g = _mm256_fnmadd_ps(tanh_g, tanh_g, one_vec);
453
454 // gelu_derivative = 0.5 * (1 + tanh_g) + 0.5 * x * sech2_g * g_prime
455 __m256 term1 = _mm256_mul_ps(half_vec, _mm256_add_ps(one_vec, tanh_g));
456 __m256 term2 = _mm256_mul_ps(half_vec, _mm256_mul_ps(x, _mm256_mul_ps(sech2_g, g_prime)));
457 __m256 gelu_deriv = _mm256_add_ps(term1, term2);
458
459 __m256 result = _mm256_mul_ps(dy, gelu_deriv);
460 _mm256_storeu_ps(&d_input[i], result);
461 }
462 // Handle remaining elements
463 for (; i < n; ++i) {
464 float x = input[i];
465 float x3 = x * x * x;
466 float g = sqrt_2_over_pi * (x + coeff * x3);
467 float tanh_g = tanhf(g);
468 float x2 = x * x;
469 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * x2);
470 float sech2_g = 1.0f - tanh_g * tanh_g;
471 float gelu_derivative = 0.5f * (1.0f + tanh_g) + 0.5f * x * sech2_g * g_prime;
472 d_input[i] = d_output[i] * gelu_derivative;
473 }
474
475#elif defined(__AVX__)
476 // AVX1: Vectorize arithmetic, use scalar tanh
477 const __m256 sqrt_2_pi_vec = _mm256_set1_ps(sqrt_2_over_pi);
478 const __m256 coeff_vec = _mm256_set1_ps(coeff);
479 const __m256 coeff3_vec = _mm256_set1_ps(3.0f * coeff);
480 const __m256 half_vec = _mm256_set1_ps(0.5f);
481 const __m256 one_vec = _mm256_set1_ps(1.0f);
482
483 size_t i = 0;
484 float g_arr[8] __attribute__((aligned(32)));
485 float tanh_arr[8] __attribute__((aligned(32)));
486
487 for (; i + 8 <= n; i += 8) {
488 __m256 x = _mm256_loadu_ps(&input[i]);
489 __m256 dy = _mm256_loadu_ps(&d_output[i]);
490
491 __m256 x2 = _mm256_mul_ps(x, x);
492 __m256 x3 = _mm256_mul_ps(x2, x);
493
494 // g = sqrt(2/pi) * (x + 0.044715 * x^3)
495 __m256 coeff_x3 = _mm256_mul_ps(coeff_vec, x3);
496 __m256 g = _mm256_mul_ps(sqrt_2_pi_vec, _mm256_add_ps(x, coeff_x3));
497
498 // Compute tanh scalarly
499 _mm256_store_ps(g_arr, g);
500 for (int j = 0; j < 8; ++j) {
501 tanh_arr[j] = tanhf(g_arr[j]);
502 }
503 __m256 tanh_g = _mm256_load_ps(tanh_arr);
504
505 // g' = sqrt(2/pi) * (1 + 3 * 0.044715 * x^2)
506 __m256 coeff3_x2 = _mm256_mul_ps(coeff3_vec, x2);
507 __m256 g_prime = _mm256_mul_ps(sqrt_2_pi_vec, _mm256_add_ps(one_vec, coeff3_x2));
508
509 // sech^2(g) = 1 - tanh^2(g)
510 __m256 tanh_g_sq = _mm256_mul_ps(tanh_g, tanh_g);
511 __m256 sech2_g = _mm256_sub_ps(one_vec, tanh_g_sq);
512
513 // gelu_derivative = 0.5 * (1 + tanh_g) + 0.5 * x * sech2_g * g_prime
514 __m256 term1 = _mm256_mul_ps(half_vec, _mm256_add_ps(one_vec, tanh_g));
515 __m256 term2 = _mm256_mul_ps(half_vec, _mm256_mul_ps(x, _mm256_mul_ps(sech2_g, g_prime)));
516 __m256 gelu_deriv = _mm256_add_ps(term1, term2);
517
518 __m256 result = _mm256_mul_ps(dy, gelu_deriv);
519 _mm256_storeu_ps(&d_input[i], result);
520 }
521 // Handle remaining elements
522 for (; i < n; ++i) {
523 float x = input[i];
524 float x3 = x * x * x;
525 float g = sqrt_2_over_pi * (x + coeff * x3);
526 float tanh_g = tanhf(g);
527 float x2 = x * x;
528 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * x2);
529 float sech2_g = 1.0f - tanh_g * tanh_g;
530 float gelu_derivative = 0.5f * (1.0f + tanh_g) + 0.5f * x * sech2_g * g_prime;
531 d_input[i] = d_output[i] * gelu_derivative;
532 }
533
534#else
535 // Scalar fallback
536 for (size_t i = 0; i < n; ++i) {
537 float x = input[i];
538
539 float x3 = x * x * x;
540 float g = sqrt_2_over_pi * (x + coeff * x3);
541 float tanh_g = tanhf(g);
542
543 float x2 = x * x;
544 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * x2);
545
546 float sech2_g = 1.0f - tanh_g * tanh_g;
547 float gelu_derivative =
548 0.5f * (1.0f + tanh_g) + 0.5f * x * sech2_g * g_prime;
549
550 d_input[i] = d_output[i] * gelu_derivative;
551 }
552#endif
553}
__attribute__((visibility("default"))) CKTokenizer *ck_tokenizer_create(CKTokenizerType type)

References __attribute__().

◆ gelu_backward_fast()

void gelu_backward_fast ( const float *  input,
const float *  d_output,
float *  d_input,
size_t  n 
)

Definition at line 870 of file gelu_kernels.c.

874{
875 const float beta = 1.702f;
876
877#if defined(__AVX512F__)
878 const __m512 beta_vec = _mm512_set1_ps(beta);
879 const __m512 one_vec = _mm512_set1_ps(1.0f);
880 const __m512 neg_beta_vec = _mm512_set1_ps(-beta);
881
882 size_t i = 0;
883 for (; i + 16 <= n; i += 16) {
884 __m512 x = _mm512_loadu_ps(&input[i]);
885 __m512 dy = _mm512_loadu_ps(&d_output[i]);
886
887 // s = sigmoid(beta * x) = 1 / (1 + exp(-beta * x))
888 __m512 neg_beta_x = _mm512_mul_ps(neg_beta_vec, x);
889 __m512 exp_neg = exp512_fast(neg_beta_x);
890 __m512 s = _mm512_div_ps(one_vec, _mm512_add_ps(one_vec, exp_neg));
891
892 // gelu_derivative = s * (1 + x * (1 - s) * beta)
893 __m512 one_minus_s = _mm512_sub_ps(one_vec, s);
894 __m512 inner = _mm512_fmadd_ps(_mm512_mul_ps(x, one_minus_s), beta_vec, one_vec);
895 __m512 gelu_deriv = _mm512_mul_ps(s, inner);
896
897 __m512 result = _mm512_mul_ps(dy, gelu_deriv);
898 _mm512_storeu_ps(&d_input[i], result);
899 }
900 // Handle remaining elements
901 for (; i < n; ++i) {
902 float x = input[i];
903 float s = 1.0f / (1.0f + expf(-beta * x));
904 float gelu_derivative = s * (1.0f + x * (1.0f - s) * beta);
905 d_input[i] = d_output[i] * gelu_derivative;
906 }
907
908#elif defined(__AVX2__)
909 const __m256 beta_vec = _mm256_set1_ps(beta);
910 const __m256 one_vec = _mm256_set1_ps(1.0f);
911 const __m256 neg_beta_vec = _mm256_set1_ps(-beta);
912
913 size_t i = 0;
914 for (; i + 8 <= n; i += 8) {
915 __m256 x = _mm256_loadu_ps(&input[i]);
916 __m256 dy = _mm256_loadu_ps(&d_output[i]);
917
918 // s = sigmoid(beta * x) = 1 / (1 + exp(-beta * x))
919 __m256 neg_beta_x = _mm256_mul_ps(neg_beta_vec, x);
920 __m256 exp_neg = exp256_fast(neg_beta_x);
921 __m256 s = _mm256_div_ps(one_vec, _mm256_add_ps(one_vec, exp_neg));
922
923 // gelu_derivative = s * (1 + x * (1 - s) * beta)
924 __m256 one_minus_s = _mm256_sub_ps(one_vec, s);
925 __m256 inner = _mm256_fmadd_ps(_mm256_mul_ps(x, one_minus_s), beta_vec, one_vec);
926 __m256 gelu_deriv = _mm256_mul_ps(s, inner);
927
928 __m256 result = _mm256_mul_ps(dy, gelu_deriv);
929 _mm256_storeu_ps(&d_input[i], result);
930 }
931 // Handle remaining elements
932 for (; i < n; ++i) {
933 float x = input[i];
934 float s = 1.0f / (1.0f + expf(-beta * x));
935 float gelu_derivative = s * (1.0f + x * (1.0f - s) * beta);
936 d_input[i] = d_output[i] * gelu_derivative;
937 }
938
939#elif defined(__AVX__)
940 // AVX1: Vectorize arithmetic, use scalar exp
941 const __m256 beta_vec = _mm256_set1_ps(beta);
942 const __m256 one_vec = _mm256_set1_ps(1.0f);
943 const __m256 neg_beta_vec = _mm256_set1_ps(-beta);
944
945 size_t i = 0;
946 float neg_beta_x_arr[8] __attribute__((aligned(32)));
947 float exp_arr[8] __attribute__((aligned(32)));
948
949 for (; i + 8 <= n; i += 8) {
950 __m256 x = _mm256_loadu_ps(&input[i]);
951 __m256 dy = _mm256_loadu_ps(&d_output[i]);
952
953 // s = sigmoid(beta * x) = 1 / (1 + exp(-beta * x))
954 __m256 neg_beta_x = _mm256_mul_ps(neg_beta_vec, x);
955
956 // Compute exp scalarly
957 _mm256_store_ps(neg_beta_x_arr, neg_beta_x);
958 for (int j = 0; j < 8; ++j) {
959 exp_arr[j] = expf(neg_beta_x_arr[j]);
960 }
961 __m256 exp_neg = _mm256_load_ps(exp_arr);
962
963 __m256 s = _mm256_div_ps(one_vec, _mm256_add_ps(one_vec, exp_neg));
964
965 // gelu_derivative = s * (1 + x * (1 - s) * beta)
966 __m256 one_minus_s = _mm256_sub_ps(one_vec, s);
967 __m256 x_one_minus_s = _mm256_mul_ps(x, one_minus_s);
968 __m256 x_one_minus_s_beta = _mm256_mul_ps(x_one_minus_s, beta_vec);
969 __m256 inner = _mm256_add_ps(one_vec, x_one_minus_s_beta);
970 __m256 gelu_deriv = _mm256_mul_ps(s, inner);
971
972 __m256 result = _mm256_mul_ps(dy, gelu_deriv);
973 _mm256_storeu_ps(&d_input[i], result);
974 }
975 // Handle remaining elements
976 for (; i < n; ++i) {
977 float x = input[i];
978 float s = 1.0f / (1.0f + expf(-beta * x));
979 float gelu_derivative = s * (1.0f + x * (1.0f - s) * beta);
980 d_input[i] = d_output[i] * gelu_derivative;
981 }
982
983#else
984 // Scalar fallback
985 for (size_t i = 0; i < n; ++i) {
986 float x = input[i];
987 float s = 1.0f / (1.0f + expf(-beta * x));
988 float gelu_derivative = s * (1.0f + x * (1.0f - s) * beta);
989 d_input[i] = d_output[i] * gelu_derivative;
990 }
991#endif
992}

References __attribute__().

Referenced by gelu_backward_fast_bf16().

◆ gelu_backward_scalar()

void gelu_backward_scalar ( const float *  input,
const float *  d_output,
float *  d_input,
size_t  n 
)

Definition at line 846 of file gelu_kernels.c.

850{
851 const float sqrt_2_over_pi = 0.7978845608f;
852 const float coeff = 0.044715f;
853
854 for (size_t i = 0; i < n; ++i) {
855 float x = input[i];
856 float x3 = x * x * x;
857 float g = sqrt_2_over_pi * (x + coeff * x3);
858 float tanh_g = tanhf(g);
859 float x2 = x * x;
860 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * x2);
861 float sech2_g = 1.0f - tanh_g * tanh_g;
862 float gelu_derivative = 0.5f * (1.0f + tanh_g) + 0.5f * x * sech2_g * g_prime;
863 d_input[i] = d_output[i] * gelu_derivative;
864 }
865}

Referenced by gelu_backward_exact_bf16().

◆ gelu_erf_bf16_storage()

void gelu_erf_bf16_storage ( float *  data,
size_t  n 
)

Definition at line 661 of file gelu_kernels.c.

662{
663 const double inv_sqrt_2 = 0.707106781186547524400844362104849039;
664 ck_gelu_math_f64_fn reference_erf = ck_gelu_system_erf();
665 for (size_t i = 0; i < n; ++i) {
666 const float x = bf16_to_float(float_to_bf16(data[i]));
667 const double scaled = (double)x * inv_sqrt_2;
668 const double erf_value = reference_erf ? reference_erf(scaled) : erf(scaled);
669 const float output = (float)(0.5 * (double)x * (1.0 + erf_value));
670 data[i] = bf16_to_float(float_to_bf16(output));
671 }
672}
static uint16_t float_to_bf16(float f)
Definition bf16_utils.h:90
static float bf16_to_float(uint16_t v)
Definition bf16_utils.h:38
static ck_gelu_math_f64_fn ck_gelu_system_erf(void)

References bf16_to_float(), ck_gelu_system_erf(), and float_to_bf16().

◆ gelu_erf_fp64_f32_inplace()

void gelu_erf_fp64_f32_inplace ( float *  data,
size_t  n 
)

Definition at line 567 of file gelu_kernels.c.

568{
569 const double inv_sqrt_2 = 0.707106781186547524400844362104849039;
570 ck_gelu_math_f64_fn reference_erf = ck_gelu_system_erf();
571 for (size_t i = 0; i < n; ++i) {
572 const float x = data[i];
573 const double scaled = (double)x * inv_sqrt_2;
574 const double erf_value = reference_erf ? reference_erf(scaled) : erf(scaled);
575 data[i] = (float)(0.5 * (double)x * (1.0 + erf_value));
576 }
577}

References ck_gelu_system_erf().

Referenced by gelu_erf_fp64_f32_parallel_dispatch(), and gelu_pytorch_erf_f32_inplace().

◆ gelu_erf_fp64_f32_parallel_dispatch()

void gelu_erf_fp64_f32_parallel_dispatch ( float *  data,
size_t  n 
)

Definition at line 606 of file gelu_kernels.c.

607{
608 const size_t minimum_elements_per_thread = 32768u;
609 ck_threadpool_t *pool = ck_threadpool_global();
610 int active = pool ? ck_threadpool_n_threads(pool) : 1;
611
612 if (!data || n == 0) return;
613 if (!pool || active <= 1 || n < 2u * minimum_elements_per_thread ||
614 ck_threadpool_thread_id(pool) > 0) {
616 return;
617 }
618
619 const size_t useful_threads =
620 (n + minimum_elements_per_thread - 1u) / minimum_elements_per_thread;
621 if ((size_t)active > useful_threads) active = (int)useful_threads;
622 ck_gelu_erf_fp64_parallel_args_t args = {
623 .data = data,
624 .n = n,
625 .reference_erf = ck_gelu_system_erf(),
626 };
628}
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)
int ck_threadpool_thread_id(const ck_threadpool_t *pool)
int ck_threadpool_n_threads(const ck_threadpool_t *pool)
void gelu_erf_fp64_f32_inplace(float *data, size_t n)
static void ck_gelu_erf_fp64_parallel_work(int ith, int nth, void *opaque)

References ck_gelu_erf_fp64_parallel_work(), ck_gelu_system_erf(), ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_thread_id(), and gelu_erf_fp64_f32_inplace().

◆ gelu_exact_inplace()

void gelu_exact_inplace ( float *  data,
size_t  n 
)

Definition at line 558 of file gelu_kernels.c.

559{
560 for (size_t i = 0; i < n; ++i) {
561 data[i] = ck_gelu_tanh_f32(data[i]);
562 }
563}
static float ck_gelu_tanh_f32(float x)

References ck_gelu_tanh_f32().

Referenced by gelu_fast_inplace_bf16(), gelu_rows_tanh_checked_f32(), and mlp_token_parallel_exact().

◆ gelu_fast_inplace()

void gelu_fast_inplace ( float *  data,
size_t  n 
)

GELU activation forward (fast approximation, in-place)

Test:

test_gelu.py::TestGELUForward::test_gelu_fast_inplace

test_gelu.py::TestGELUForward::test_gelu_vs_exact

test_parity.py::test_gelu_parity

Fast GELU approximation: 0.5 * x * (1 + tanh(sqrt(2/pi) * (x + 0.044715 * x^3))) In-place on contiguous buffer.

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

Definition at line 244 of file gelu_kernels.c.

245{
246 const float sqrt_2_over_pi = 0.7978845608f;
247 const float coeff = 0.044715f;
248
249#if defined(__AVX512F__)
250 const __m512 sqrt_2_pi_vec = _mm512_set1_ps(sqrt_2_over_pi);
251 const __m512 coeff_vec = _mm512_set1_ps(coeff);
252 const __m512 half_vec = _mm512_set1_ps(0.5f);
253 const __m512 one_vec = _mm512_set1_ps(1.0f);
254
255 size_t i = 0;
256 for (; i + 16 <= n; i += 16) {
257 __m512 x = _mm512_loadu_ps(&data[i]);
258 __m512 x2 = _mm512_mul_ps(x, x);
259 __m512 x3 = _mm512_mul_ps(x2, x);
260
261 // inner = sqrt(2/pi) * (x + 0.044715 * x^3)
262 __m512 inner = _mm512_fmadd_ps(coeff_vec, x3, x);
263 inner = _mm512_mul_ps(sqrt_2_pi_vec, inner);
264
265 // result = 0.5 * x * (1 + tanh(inner))
266 __m512 tanh_val = tanh512_fast(inner);
267 __m512 one_plus_tanh = _mm512_add_ps(one_vec, tanh_val);
268 __m512 result = _mm512_mul_ps(half_vec, _mm512_mul_ps(x, one_plus_tanh));
269
270 _mm512_storeu_ps(&data[i], result);
271 }
272 // Handle remaining elements
273 for (; i < n; ++i) {
274 float x = data[i];
275 float x3 = x * x * x;
276 float inner = sqrt_2_over_pi * (x + coeff * x3);
277 data[i] = 0.5f * x * (1.0f + tanhf(inner));
278 }
279
280#elif defined(__AVX2__)
281 const __m256 sqrt_2_pi_vec = _mm256_set1_ps(sqrt_2_over_pi);
282 const __m256 coeff_vec = _mm256_set1_ps(coeff);
283 const __m256 half_vec = _mm256_set1_ps(0.5f);
284 const __m256 one_vec = _mm256_set1_ps(1.0f);
285
286 size_t i = 0;
287 for (; i + 8 <= n; i += 8) {
288 __m256 x = _mm256_loadu_ps(&data[i]);
289 __m256 x2 = _mm256_mul_ps(x, x);
290 __m256 x3 = _mm256_mul_ps(x2, x);
291
292 // inner = sqrt(2/pi) * (x + 0.044715 * x^3)
293 __m256 inner = _mm256_fmadd_ps(coeff_vec, x3, x);
294 inner = _mm256_mul_ps(sqrt_2_pi_vec, inner);
295
296 // result = 0.5 * x * (1 + tanh(inner))
297 __m256 tanh_val = tanh256_fast(inner);
298 __m256 one_plus_tanh = _mm256_add_ps(one_vec, tanh_val);
299 __m256 result = _mm256_mul_ps(half_vec, _mm256_mul_ps(x, one_plus_tanh));
300
301 _mm256_storeu_ps(&data[i], result);
302 }
303 // Handle remaining elements
304 for (; i < n; ++i) {
305 float x = data[i];
306 float x3 = x * x * x;
307 float inner = sqrt_2_over_pi * (x + coeff * x3);
308 data[i] = 0.5f * x * (1.0f + tanhf(inner));
309 }
310
311#elif defined(__AVX__)
312 // AVX1: Vectorize arithmetic, use scalar tanh
313 const __m256 sqrt_2_pi_vec = _mm256_set1_ps(sqrt_2_over_pi);
314 const __m256 coeff_vec = _mm256_set1_ps(coeff);
315 const __m256 half_vec = _mm256_set1_ps(0.5f);
316 const __m256 one_vec = _mm256_set1_ps(1.0f);
317
318 size_t i = 0;
319 float inner_arr[8] __attribute__((aligned(32)));
320 float tanh_arr[8] __attribute__((aligned(32)));
321
322 for (; i + 8 <= n; i += 8) {
323 __m256 x = _mm256_loadu_ps(&data[i]);
324 __m256 x2 = _mm256_mul_ps(x, x);
325 __m256 x3 = _mm256_mul_ps(x2, x);
326
327 // inner = sqrt(2/pi) * (x + 0.044715 * x^3)
328 __m256 coeff_x3 = _mm256_mul_ps(coeff_vec, x3);
329 __m256 inner = _mm256_mul_ps(sqrt_2_pi_vec, _mm256_add_ps(x, coeff_x3));
330
331 // Compute tanh scalarly
332 _mm256_store_ps(inner_arr, inner);
333 for (int j = 0; j < 8; ++j) {
334 tanh_arr[j] = tanhf(inner_arr[j]);
335 }
336 __m256 tanh_val = _mm256_load_ps(tanh_arr);
337
338 // result = 0.5 * x * (1 + tanh(inner))
339 __m256 one_plus_tanh = _mm256_add_ps(one_vec, tanh_val);
340 __m256 result = _mm256_mul_ps(half_vec, _mm256_mul_ps(x, one_plus_tanh));
341
342 _mm256_storeu_ps(&data[i], result);
343 }
344 // Handle remaining elements
345 for (; i < n; ++i) {
346 float x = data[i];
347 float x3 = x * x * x;
348 float inner = sqrt_2_over_pi * (x + coeff * x3);
349 data[i] = 0.5f * x * (1.0f + tanhf(inner));
350 }
351
352#else
353 // Scalar fallback
354 for (size_t i = 0; i < n; ++i) {
355 float x = data[i];
356 float x3 = x * x * x;
357 float inner = sqrt_2_over_pi * (x + coeff * x3);
358 data[i] = 0.5f * x * (1.0f + tanhf(inner));
359 }
360#endif
361}

References __attribute__().

Referenced by geglu_forward_fp32(), and mlp_token_parallel().

◆ gelu_ggml_inplace()

void gelu_ggml_inplace ( float *  data,
size_t  n 
)

Definition at line 805 of file gelu_kernels.c.

806{
809 for (size_t i = 0; i < n; ++i) {
810 const float x = data[i];
811 if (x <= -10.0f) {
812 data[i] = 0.0f;
813 continue;
814 }
815 if (x >= 10.0f) {
816 data[i] = x;
817 continue;
818 }
819 const ck_half x_fp16 = ck_gelu_runtime_fp32_to_fp16(x);
820 const ck_half y_fp16 = ck_gelu_runtime_table_f16[(uint16_t) x_fp16];
821 data[i] = ck_gelu_runtime_fp16_to_fp32(y_fp16);
822 }
823 return;
824 }
825
827 for (size_t i = 0; i < n; ++i) {
828 const float x = data[i];
829 if (x <= -10.0f) {
830 data[i] = 0.0f;
831 continue;
832 }
833 if (x >= 10.0f) {
834 data[i] = x;
835 continue;
836 }
837 const ck_half x_fp16 = ggml_fp32_to_fp16(x);
838 const ck_half y_fp16 = ck_gelu_ggml_table_f16[(uint16_t) x_fp16];
839 data[i] = ggml_fp16_to_fp32(y_fp16);
840 }
841}
static void ck_gelu_ggml_runtime_init(void)
static pthread_once_t ck_gelu_ggml_table_once
static void ck_gelu_ggml_table_init(void)
static pthread_once_t ck_gelu_ggml_runtime_once

References ck_gelu_ggml_runtime_init(), ck_gelu_ggml_runtime_once, ck_gelu_ggml_table_f16, ck_gelu_ggml_table_init(), ck_gelu_ggml_table_once, ck_gelu_runtime_fp16_to_fp32, ck_gelu_runtime_fp32_to_fp16, ck_gelu_runtime_ready, ck_gelu_runtime_table_f16, ggml_fp16_to_fp32, and ggml_fp32_to_fp16.

◆ gelu_ggml_native_inplace()

void gelu_ggml_native_inplace ( float *  data,
size_t  n 
)

Definition at line 793 of file gelu_kernels.c.

794{
796 for (size_t i = 0; i < n; ++i) {
797 const float x = data[i];
798 if (x <= -10.0f) data[i] = 0.0f;
799 else if (x >= 10.0f) data[i] = x;
800 else data[i] = ggml_fp16_to_fp32(
802 }
803}

References ck_gelu_ggml_table_f16, ck_gelu_ggml_table_init(), ck_gelu_ggml_table_once, ggml_fp16_to_fp32, and ggml_fp32_to_fp16.

Referenced by geglu_forward_ggml_native().

◆ gelu_pytorch_erf_f32_inplace()

void gelu_pytorch_erf_f32_inplace ( float *  data,
size_t  n 
)

Definition at line 632 of file gelu_kernels.c.

633{
635}

References gelu_erf_fp64_f32_inplace().

◆ gelu_pytorch_erf_sleef_bf16_storage()

void gelu_pytorch_erf_sleef_bf16_storage ( float *  data,
size_t  n 
)

Definition at line 734 of file gelu_kernels.c.

735{
736#if defined(__AVX512F__)
737 pthread_once(&ck_pytorch_sleef_once, ck_bind_pytorch_sleef);
738 if (!ck_pytorch_sleef_expf16) {
739 fprintf(stderr,
740 "[CK] PyTorch-exact BF16 GELU requires Sleef_expf16_u10; "
741 "set CK_SLEEF_LIBRARY to libtorch_cpu.so or libsleef.so\n");
742 abort();
743 }
744
745 const __m512 alpha = _mm512_set1_ps(0.70710678118654752440f);
746 const __m512 half = _mm512_set1_ps(0.5f);
747 const __m512 one = _mm512_set1_ps(1.0f);
748 const __m512 neg_zero = _mm512_set1_ps(-0.0f);
749 const __m512 p = _mm512_set1_ps(0.3275911f);
750 const __m512 p1 = _mm512_set1_ps(0.254829592f);
751 const __m512 p2 = _mm512_set1_ps(-0.284496736f);
752 const __m512 p3 = _mm512_set1_ps(1.421413741f);
753 const __m512 p4 = _mm512_set1_ps(-1.453152027f);
754 const __m512 p5 = _mm512_set1_ps(1.061405429f);
755 size_t i = 0;
756 for (; i + 16 <= n; i += 16) {
757 __m512 x = _mm512_loadu_ps(data + i);
758 __m512 erf_arg = _mm512_mul_ps(x, alpha);
759 __m512 sign = _mm512_and_ps(neg_zero, erf_arg);
760 __m512 abs_arg = _mm512_abs_ps(erf_arg);
761 __m512 t = _mm512_div_ps(one, _mm512_fmadd_ps(p, abs_arg, one));
762 __m512 r = _mm512_fmadd_ps(p5, t, p4);
763 r = _mm512_fmadd_ps(r, t, p3);
764 r = _mm512_fmadd_ps(r, t, p2);
765 r = _mm512_fmadd_ps(r, t, p1);
766 __m512 arg_sq = _mm512_mul_ps(erf_arg, erf_arg);
767 __m512 exp_neg_sq = ck_pytorch_sleef_expf16(_mm512_xor_ps(neg_zero, arg_sq));
768 __m512 neg_exp_t = _mm512_mul_ps(_mm512_xor_ps(neg_zero, exp_neg_sq), t);
769 __m512 erf_x = _mm512_xor_ps(sign, _mm512_fmadd_ps(neg_exp_t, r, one));
770 __m512 y = _mm512_mul_ps(_mm512_mul_ps(x, half), _mm512_add_ps(one, erf_x));
771 float lanes[16];
772 _mm512_storeu_ps(lanes, y);
773 for (size_t lane = 0; lane < 16; ++lane) {
774 const uint16_t input_code = float_to_bf16(data[i + lane]);
775 const uint16_t output_code = ck_pytorch_gelu_erf_bf16_edge(
776 input_code, float_to_bf16(lanes[lane]));
777 data[i + lane] = bf16_to_float(output_code);
778 }
779 }
780 for (; i < n; ++i) {
781 const float x = bf16_to_float(float_to_bf16(data[i]));
782 const float y = (x * 0.5f) * (1.0f + erff(x * 0.70710678118654752440f));
783 data[i] = bf16_to_float(float_to_bf16(y));
784 }
785#else
786 (void)data;
787 (void)n;
788 fprintf(stderr, "[CK] PyTorch-exact BF16 GELU requires an AVX-512 build\n");
789 abort();
790#endif
791}

References bf16_to_float(), and float_to_bf16().

◆ gelu_pytorch_tanh_bf16_storage()

void gelu_pytorch_tanh_bf16_storage ( float *  data,
size_t  n 
)

Definition at line 642 of file gelu_kernels.c.

643{
644 /* PyTorch's x86 BF16 kernel widens to FP32 and evaluates tanh through
645 * SLEEF's vector u10 provider. That provider saturates at this exact
646 * inner-argument boundary; libc tanhf retains a small tail and can round
647 * to a different BF16 code before the following projection. */
648 const float sleef_tanh_saturation = 8.664339742f;
649 for (size_t i = 0; i < n; ++i) {
650 const float x = bf16_to_float(float_to_bf16(data[i]));
651 const float x3 = x * x * x;
652 const float inner = 0.7978845608f * (x + 0.044715f * x3);
653 const float tanh_inner = fabsf(inner) > sleef_tanh_saturation
654 ? copysignf(1.0f, inner)
655 : tanhf(inner);
656 const float output = 0.5f * x * (1.0f + tanh_inner);
657 data[i] = bf16_to_float(float_to_bf16(output));
658 }
659}

References bf16_to_float(), and float_to_bf16().

Variable Documentation

◆ ck_gelu_ggml_runtime_once

pthread_once_t ck_gelu_ggml_runtime_once = PTHREAD_ONCE_INIT
static

Definition at line 47 of file gelu_kernels.c.

Referenced by gelu_ggml_inplace().

◆ ck_gelu_ggml_table_f16

ck_half ck_gelu_ggml_table_f16[1u<< 16]
static

◆ ck_gelu_ggml_table_once

pthread_once_t ck_gelu_ggml_table_once = PTHREAD_ONCE_INIT
static

Definition at line 46 of file gelu_kernels.c.

Referenced by gelu_ggml_inplace(), and gelu_ggml_native_inplace().

◆ ck_gelu_reference_erf

ck_gelu_math_f64_fn ck_gelu_reference_erf = NULL
static

Definition at line 61 of file gelu_kernels.c.

Referenced by ck_gelu_reference_math_init(), and ck_gelu_system_erf().

◆ ck_gelu_reference_math_once

pthread_once_t ck_gelu_reference_math_once = PTHREAD_ONCE_INIT
static

Definition at line 62 of file gelu_kernels.c.

Referenced by ck_gelu_system_erf(), and ck_gelu_system_tanhf().

◆ ck_gelu_reference_tanhf

ck_gelu_math_f32_fn ck_gelu_reference_tanhf = NULL
static

Definition at line 60 of file gelu_kernels.c.

Referenced by ck_gelu_reference_math_init(), and ck_gelu_system_tanhf().

◆ ck_gelu_runtime_fp16_to_fp32

ck_gelu_ggml_fp16_to_fp32_fn ck_gelu_runtime_fp16_to_fp32 = NULL
static

Definition at line 57 of file gelu_kernels.c.

Referenced by ck_gelu_try_bind_runtime(), and gelu_ggml_inplace().

◆ ck_gelu_runtime_fp32_to_fp16

ck_gelu_ggml_fp32_to_fp16_fn ck_gelu_runtime_fp32_to_fp16 = NULL
static

Definition at line 56 of file gelu_kernels.c.

Referenced by ck_gelu_try_bind_runtime(), and gelu_ggml_inplace().

◆ ck_gelu_runtime_handle

void* ck_gelu_runtime_handle = NULL
static

Definition at line 58 of file gelu_kernels.c.

Referenced by ck_gelu_ggml_runtime_init().

◆ ck_gelu_runtime_ready

int ck_gelu_runtime_ready = 0
static

◆ ck_gelu_runtime_table_f16

const ck_half* ck_gelu_runtime_table_f16 = NULL
static

Definition at line 55 of file gelu_kernels.c.

Referenced by ck_gelu_try_bind_runtime(), and gelu_ggml_inplace().