← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
geglu_kernels.c
Go to the documentation of this file.
1/**
2 * @file geglu_kernels.c
3 * @brief GeGLU kernels split from gelu_kernels.c
4 */
5
6#include <math.h>
7#include <stddef.h>
8#include <stdint.h>
9
10#include "ckernel_engine.h"
11#include "bf16_utils.h"
12
13/* Reuse existing optimized GELU implementation from gelu_kernels.c. */
14extern void gelu_fast_inplace(float *data, size_t n);
15extern void gelu_ggml_native_inplace(float *data, size_t n);
16
17void geglu_forward_ggml_native(const float *x, float *out, int tokens, int dim)
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}
32
33static inline float ck_gelu_tanh_parity_f32(float x)
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}
41
42void geglu_forward_exact(const float *x, float *out, int tokens, int dim)
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}
54
55void geglu_forward_fp32(const float *x, float *out, int tokens, int dim)
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}
82
83void geglu_forward_bf16(const uint16_t *x, uint16_t *out, int tokens, int dim, float *scratch)
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}
98
99void geglu_backward_fp32(const float *x,
100 const float *d_out,
101 float *d_x,
102 int tokens,
103 int dim)
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}
138
139void geglu_backward_bf16_mixed(const uint16_t *x,
140 const uint16_t *d_out,
141 float *d_x,
142 int tokens,
143 int dim)
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 void float_tensor_to_bf16(const float *src, uint16_t *dst, size_t count)
Definition bf16_utils.h:271
static float bf16_to_float(uint16_t v)
Definition bf16_utils.h:38
static void bf16_tensor_to_float(const uint16_t *src, float *dst, size_t count)
Definition bf16_utils.h:250
int ck_strict_parity_enabled(void)
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_forward_exact(const float *x, float *out, 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_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_ggml_native_inplace(float *data, size_t n)
void gelu_fast_inplace(float *data, size_t n)
void geglu_forward_bf16(const uint16_t *x, uint16_t *out, int tokens, int dim, float *scratch)