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

GeGLU kernels split from gelu_kernels.c. More...

#include <math.h>
#include <stddef.h>
#include <stdint.h>
#include "ckernel_engine.h"
#include "bf16_utils.h"

Go to the source code of this file.

Functions

static float ck_gelu_tanh_parity_f32 (float x)
 
void geglu_backward_bf16_mixed (const uint16_t *x, const uint16_t *d_out, float *d_x, int tokens, int dim)
 
void geglu_backward_fp32 (const float *x, const float *d_out, float *d_x, int tokens, int dim)
 
void geglu_forward_bf16 (const uint16_t *x, uint16_t *out, int tokens, int dim, float *scratch)
 
void geglu_forward_exact (const float *x, float *out, int tokens, int dim)
 
void geglu_forward_fp32 (const float *x, float *out, int tokens, int dim)
 
void geglu_forward_ggml_native (const float *x, float *out, int tokens, int dim)
 
void gelu_fast_inplace (float *data, size_t n)
 
void gelu_ggml_native_inplace (float *data, size_t n)
 

Detailed Description

GeGLU kernels split from gelu_kernels.c.

Definition in file geglu_kernels.c.

Function Documentation

◆ ck_gelu_tanh_parity_f32()

static float ck_gelu_tanh_parity_f32 ( float  x)
inlinestatic

Definition at line 33 of file geglu_kernels.c.

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

Referenced by geglu_forward_exact().

◆ geglu_backward_bf16_mixed()

void geglu_backward_bf16_mixed ( const uint16_t *  x,
const uint16_t *  d_out,
float *  d_x,
int  tokens,
int  dim 
)

Definition at line 139 of file geglu_kernels.c.

144{
145 if (!x || !d_out || !d_x || tokens <= 0 || dim <= 0) {
146 return;
147 }
148
149 const float sqrt_2_over_pi = 0.7978845608f;
150 const float coeff = 0.044715f;
151 const int inner_dim = dim * 2;
152
153 for (int t = 0; t < tokens; ++t) {
154 const uint16_t *x_ptr = x + (size_t)t * (size_t)inner_dim;
155 const uint16_t *d_out_ptr = d_out + (size_t)t * (size_t)dim;
156 float *d_x_ptr = d_x + (size_t)t * (size_t)inner_dim;
157
158 for (int d = 0; d < dim; ++d) {
159 const float a = bf16_to_float(x_ptr[d]);
160 const float b = bf16_to_float(x_ptr[dim + d]);
161 const float dout = bf16_to_float(d_out_ptr[d]);
162
163 const float a2 = a * a;
164 const float a3 = a2 * a;
165 const float g = sqrt_2_over_pi * (a + coeff * a3);
166 const float tanh_g = tanhf(g);
167 const float sech2_g = 1.0f - tanh_g * tanh_g;
168 const float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * a2);
169
170 const float d_gelu = 0.5f * (1.0f + tanh_g) + 0.5f * a * sech2_g * g_prime;
171 d_x_ptr[d] = dout * d_gelu * b;
172
173 const float gelu_a = 0.5f * a * (1.0f + tanh_g);
174 d_x_ptr[dim + d] = dout * gelu_a;
175 }
176 }
177}
static float bf16_to_float(uint16_t v)
Definition bf16_utils.h:38

References bf16_to_float().

◆ geglu_backward_fp32()

void geglu_backward_fp32 ( const float *  x,
const float *  d_out,
float *  d_x,
int  tokens,
int  dim 
)

Definition at line 99 of file geglu_kernels.c.

104{
105 if (!x || !d_out || !d_x || tokens <= 0 || dim <= 0) {
106 return;
107 }
108
109 const float sqrt_2_over_pi = 0.7978845608f;
110 const float coeff = 0.044715f;
111 const int inner_dim = dim * 2;
112
113 for (int t = 0; t < tokens; ++t) {
114 const float *x_ptr = x + (size_t)t * (size_t)inner_dim;
115 const float *d_out_ptr = d_out + (size_t)t * (size_t)dim;
116 float *d_x_ptr = d_x + (size_t)t * (size_t)inner_dim;
117
118 for (int d = 0; d < dim; ++d) {
119 float a = x_ptr[d];
120 float b = x_ptr[dim + d];
121 float dout = d_out_ptr[d];
122
123 float a2 = a * a;
124 float a3 = a2 * a;
125 float g = sqrt_2_over_pi * (a + coeff * a3);
126 float tanh_g = tanhf(g);
127 float sech2_g = 1.0f - tanh_g * tanh_g;
128 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * a2);
129
130 float d_gelu = 0.5f * (1.0f + tanh_g) + 0.5f * a * sech2_g * g_prime;
131 d_x_ptr[d] = dout * d_gelu * b;
132
133 float gelu_a = 0.5f * a * (1.0f + tanh_g);
134 d_x_ptr[dim + d] = dout * gelu_a;
135 }
136 }
137}

◆ geglu_forward_bf16()

void geglu_forward_bf16 ( const uint16_t *  x,
uint16_t *  out,
int  tokens,
int  dim,
float *  scratch 
)

Definition at line 83 of file geglu_kernels.c.

84{
85 if (!x || !out || !scratch || tokens <= 0 || dim <= 0) {
86 return;
87 }
88
89 const size_t fp32_size = (size_t)tokens * (size_t)dim;
90 const size_t input_size = fp32_size * 2;
91 float *fp32_input = scratch;
92 float *fp32_output = scratch + input_size;
93
94 bf16_tensor_to_float(x, fp32_input, input_size);
95 geglu_forward_fp32(fp32_input, fp32_output, tokens, dim);
96 float_tensor_to_bf16(fp32_output, out, fp32_size);
97}
static void float_tensor_to_bf16(const float *src, uint16_t *dst, size_t count)
Definition bf16_utils.h:271
static void bf16_tensor_to_float(const uint16_t *src, float *dst, size_t count)
Definition bf16_utils.h:250
void geglu_forward_fp32(const float *x, float *out, int tokens, int dim)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and geglu_forward_fp32().

◆ geglu_forward_exact()

void geglu_forward_exact ( const float *  x,
float *  out,
int  tokens,
int  dim 
)

Definition at line 42 of file geglu_kernels.c.

43{
44 const int inner_dim = dim * 2;
45 for (int t = 0; t < tokens; ++t) {
46 const float *x_ptr = x + (size_t)t * (size_t)inner_dim;
47 float *out_ptr = out + (size_t)t * (size_t)dim;
48
49 for (int d = 0; d < dim; ++d) {
50 out_ptr[d] = ck_gelu_tanh_parity_f32(x_ptr[d]) * x_ptr[dim + d];
51 }
52 }
53}
static float ck_gelu_tanh_parity_f32(float x)

References ck_gelu_tanh_parity_f32().

Referenced by geglu_forward_fp32().

◆ geglu_forward_fp32()

void geglu_forward_fp32 ( const float *  x,
float *  out,
int  tokens,
int  dim 
)

Definition at line 55 of file geglu_kernels.c.

56{
57 if (!x || !out || tokens <= 0 || dim <= 0) {
58 return;
59 }
60
62 geglu_forward_exact(x, out, tokens, dim);
63 return;
64 }
65
66 const int inner_dim = dim * 2;
67 for (int t = 0; t < tokens; ++t) {
68 const float *x_ptr = x + (size_t)t * (size_t)inner_dim;
69 float *out_ptr = out + (size_t)t * (size_t)dim;
70
71 for (int d = 0; d < dim; ++d) {
72 out_ptr[d] = x_ptr[d];
73 }
74
75 gelu_fast_inplace(out_ptr, (size_t)dim);
76
77 for (int d = 0; d < dim; ++d) {
78 out_ptr[d] *= x_ptr[dim + d];
79 }
80 }
81}
int ck_strict_parity_enabled(void)
void geglu_forward_exact(const float *x, float *out, int tokens, int dim)
void gelu_fast_inplace(float *data, size_t n)

References ck_strict_parity_enabled(), geglu_forward_exact(), and gelu_fast_inplace().

Referenced by geglu_forward_bf16().

◆ geglu_forward_ggml_native()

void geglu_forward_ggml_native ( const float *  x,
float *  out,
int  tokens,
int  dim 
)

Definition at line 17 of file geglu_kernels.c.

18{
19 if (!x || !out || tokens <= 0 || dim <= 0) return;
20 /* Preserve ascending compaction when output aliases the gate/up input. */
21 for (int t = 0; t < tokens; ++t) {
22 const float *row = x + (size_t)t * (size_t)dim * 2;
23 float *dst = out + (size_t)t * dim;
24 for (int d = 0; d < dim; ++d) {
25 const float gate = row[d], up = row[dim + d];
26 float value = gate;
27 gelu_ggml_native_inplace(&value, 1);
28 dst[d] = gate <= -10.0f ? 0.0f : value * up;
29 }
30 }
31}
void gelu_ggml_native_inplace(float *data, size_t n)

References gelu_ggml_native_inplace().

◆ gelu_fast_inplace()

void gelu_fast_inplace ( float *  data,
size_t  n 
)
extern

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 243 of file gelu_kernels.c.

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

Referenced by geglu_forward_fp32().

◆ gelu_ggml_native_inplace()

void gelu_ggml_native_inplace ( float *  data,
size_t  n 
)
extern

Definition at line 741 of file gelu_kernels.c.

742{
744 for (size_t i = 0; i < n; ++i) {
745 const float x = data[i];
746 if (x <= -10.0f) data[i] = 0.0f;
747 else if (x >= 10.0f) data[i] = x;
748 else data[i] = ggml_fp16_to_fp32(
750 }
751}
#define ggml_fp32_to_fp16
#define ggml_fp16_to_fp32
static pthread_once_t ck_gelu_ggml_table_once
static void ck_gelu_ggml_table_init(void)
static ck_half ck_gelu_ggml_table_f16[1u<< 16]

Referenced by geglu_forward_ggml_native().