← 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 geglu_forward_quick (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 154 of file geglu_kernels.c.

159{
160 if (!x || !d_out || !d_x || tokens <= 0 || dim <= 0) {
161 return;
162 }
163
164 const float sqrt_2_over_pi = 0.7978845608f;
165 const float coeff = 0.044715f;
166 const int inner_dim = dim * 2;
167
168 for (int t = 0; t < tokens; ++t) {
169 const uint16_t *x_ptr = x + (size_t)t * (size_t)inner_dim;
170 const uint16_t *d_out_ptr = d_out + (size_t)t * (size_t)dim;
171 float *d_x_ptr = d_x + (size_t)t * (size_t)inner_dim;
172
173 for (int d = 0; d < dim; ++d) {
174 const float a = bf16_to_float(x_ptr[d]);
175 const float b = bf16_to_float(x_ptr[dim + d]);
176 const float dout = bf16_to_float(d_out_ptr[d]);
177
178 const float a2 = a * a;
179 const float a3 = a2 * a;
180 const float g = sqrt_2_over_pi * (a + coeff * a3);
181 const float tanh_g = tanhf(g);
182 const float sech2_g = 1.0f - tanh_g * tanh_g;
183 const float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * a2);
184
185 const float d_gelu = 0.5f * (1.0f + tanh_g) + 0.5f * a * sech2_g * g_prime;
186 d_x_ptr[d] = dout * d_gelu * b;
187
188 const float gelu_a = 0.5f * a * (1.0f + tanh_g);
189 d_x_ptr[dim + d] = dout * gelu_a;
190 }
191 }
192}
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 114 of file geglu_kernels.c.

119{
120 if (!x || !d_out || !d_x || tokens <= 0 || dim <= 0) {
121 return;
122 }
123
124 const float sqrt_2_over_pi = 0.7978845608f;
125 const float coeff = 0.044715f;
126 const int inner_dim = dim * 2;
127
128 for (int t = 0; t < tokens; ++t) {
129 const float *x_ptr = x + (size_t)t * (size_t)inner_dim;
130 const float *d_out_ptr = d_out + (size_t)t * (size_t)dim;
131 float *d_x_ptr = d_x + (size_t)t * (size_t)inner_dim;
132
133 for (int d = 0; d < dim; ++d) {
134 float a = x_ptr[d];
135 float b = x_ptr[dim + d];
136 float dout = d_out_ptr[d];
137
138 float a2 = a * a;
139 float a3 = a2 * a;
140 float g = sqrt_2_over_pi * (a + coeff * a3);
141 float tanh_g = tanhf(g);
142 float sech2_g = 1.0f - tanh_g * tanh_g;
143 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * a2);
144
145 float d_gelu = 0.5f * (1.0f + tanh_g) + 0.5f * a * sech2_g * g_prime;
146 d_x_ptr[d] = dout * d_gelu * b;
147
148 float gelu_a = 0.5f * a * (1.0f + tanh_g);
149 d_x_ptr[dim + d] = dout * gelu_a;
150 }
151 }
152}

◆ geglu_forward_bf16()

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

Definition at line 98 of file geglu_kernels.c.

99{
100 if (!x || !out || !scratch || tokens <= 0 || dim <= 0) {
101 return;
102 }
103
104 const size_t fp32_size = (size_t)tokens * (size_t)dim;
105 const size_t input_size = fp32_size * 2;
106 float *fp32_input = scratch;
107 float *fp32_output = scratch + input_size;
108
109 bf16_tensor_to_float(x, fp32_input, input_size);
110 geglu_forward_fp32(fp32_input, fp32_output, tokens, dim);
111 float_tensor_to_bf16(fp32_output, out, fp32_size);
112}
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 70 of file geglu_kernels.c.

71{
72 if (!x || !out || tokens <= 0 || dim <= 0) {
73 return;
74 }
75
77 geglu_forward_exact(x, out, tokens, dim);
78 return;
79 }
80
81 const int inner_dim = dim * 2;
82 for (int t = 0; t < tokens; ++t) {
83 const float *x_ptr = x + (size_t)t * (size_t)inner_dim;
84 float *out_ptr = out + (size_t)t * (size_t)dim;
85
86 for (int d = 0; d < dim; ++d) {
87 out_ptr[d] = x_ptr[d];
88 }
89
90 gelu_fast_inplace(out_ptr, (size_t)dim);
91
92 for (int d = 0; d < dim; ++d) {
93 out_ptr[d] *= x_ptr[dim + d];
94 }
95 }
96}
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().

◆ geglu_forward_quick()

void geglu_forward_quick ( 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) return;
58 const size_t inner_dim = (size_t)dim * 2u;
59 /* Ascending compaction also permits input and output to alias. */
60 for (int t = 0; t < tokens; ++t) {
61 const float *row = x + (size_t)t * inner_dim;
62 float *dst = out + (size_t)t * (size_t)dim;
63 for (int d = 0; d < dim; ++d) {
64 const float gate = row[d];
65 dst[d] = (gate * (1.0f / (1.0f + expf(-1.702f * gate)))) * row[dim + d];
66 }
67 }
68}

◆ 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 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}
__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 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}
#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().