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

Element-wise addition kernels for BF16 tensors. More...

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

Go to the source code of this file.

Functions

void add_backward_bf16 (const uint16_t *d_y, uint16_t *d_a, uint16_t *d_b, size_t n)
 
void add_forward_2d_bf16 (const uint16_t *a, const uint16_t *b, uint16_t *y, int tokens, int dim, int aligned_dim)
 
void add_forward_bf16 (const uint16_t *a, const uint16_t *b, uint16_t *y, size_t n)
 
void add_forward_f32 (const float *a, const float *b, float *y, size_t n)
 
void add_inplace_bf16 (uint16_t *a, const uint16_t *b, size_t n)
 
void add_inplace_f32 (float *a, const float *b, size_t n)
 
void add_scaled_forward_bf16 (const uint16_t *a, const uint16_t *b, uint16_t *y, float alpha, size_t n)
 
void add_scaled_inplace_bf16 (uint16_t *a, const uint16_t *b, float alpha, size_t n)
 
void ck_residual_add_token_major_bf16_storage (const float *a, const float *b, float *out, int tokens, int aligned_embed_dim)
 

Detailed Description

Element-wise addition kernels for BF16 tensors.

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

Used for residual connections in transformer models: residual = x + sublayer_output

Supports:

  • Forward: y = a + b
  • Forward with scale: y = a + alpha * b
  • Backward: d_a = d_y, d_b = d_y (gradient flows through unchanged)
  • In-place: a += b

Definition in file add_kernels_bf16.c.

Function Documentation

◆ add_backward_bf16()

void add_backward_bf16 ( const uint16_t *  d_y,
uint16_t *  d_a,
uint16_t *  d_b,
size_t  n 
)

Definition at line 187 of file add_kernels_bf16.c.

191{
192 if (!d_y || n == 0) {
193 return;
194 }
195
196 size_t i = 0;
197
198 /* Copy to d_a if not in-place */
199 if (d_a && d_a != d_y) {
200#if defined(__AVX512F__)
201 for (; i + 32 <= n; i += 32) {
202 __m512i values = _mm512_loadu_si512((const __m512i*)&d_y[i]);
203 _mm512_storeu_si512((__m512i*)&d_a[i], values);
204 }
205#endif
206 for (; i < n; ++i) {
207 d_a[i] = d_y[i];
208 }
209 }
210
211 /* Copy to d_b if not in-place */
212 i = 0;
213 if (d_b && d_b != d_y) {
214#if defined(__AVX512F__)
215 for (; i + 32 <= n; i += 32) {
216 __m512i values = _mm512_loadu_si512((const __m512i*)&d_y[i]);
217 _mm512_storeu_si512((__m512i*)&d_b[i], values);
218 }
219#endif
220 for (; i < n; ++i) {
221 d_b[i] = d_y[i];
222 }
223 }
224}

◆ add_forward_2d_bf16()

void add_forward_2d_bf16 ( const uint16_t *  a,
const uint16_t *  b,
uint16_t *  y,
int  tokens,
int  dim,
int  aligned_dim 
)

Definition at line 231 of file add_kernels_bf16.c.

237{
238 if (!a || !b || !y || tokens <= 0 || dim <= 0) {
239 return;
240 }
241
242 for (int t = 0; t < tokens; ++t) {
243 const uint16_t *a_row = a + (size_t)t * aligned_dim;
244 const uint16_t *b_row = b + (size_t)t * aligned_dim;
245 uint16_t *y_row = y + (size_t)t * aligned_dim;
246
247 int d = 0;
248
249#if defined(__AVX512F__)
250 for (; d + 16 <= dim; d += 16) {
251 __m512 av = bf16_loadu_cvt_fp32(&a_row[d]);
252 __m512 bv = bf16_loadu_cvt_fp32(&b_row[d]);
253 __m512 yv = _mm512_add_ps(av, bv);
254 fp32_cvt_storeu_bf16(&y_row[d], yv);
255 }
256#endif
257
258 for (; d < dim; ++d) {
259 float af = bf16_to_float(a_row[d]);
260 float bf = bf16_to_float(b_row[d]);
261 y_row[d] = float_to_bf16(af + bf);
262 }
263 }
264}
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

References bf16_to_float(), and float_to_bf16().

◆ add_forward_bf16()

void add_forward_bf16 ( const uint16_t *  a,
const uint16_t *  b,
uint16_t *  y,
size_t  n 
)

Definition at line 38 of file add_kernels_bf16.c.

42{
43 if (!a || !b || !y || n == 0) {
44 return;
45 }
46
47 size_t i = 0;
48
49#if defined(__AVX512F__)
50 /* AVX-512: Process 16 bf16 elements at a time */
51 for (; i + 16 <= n; i += 16) {
52 __m512 av = bf16_loadu_cvt_fp32(&a[i]);
53 __m512 bv = bf16_loadu_cvt_fp32(&b[i]);
54 __m512 yv = _mm512_add_ps(av, bv);
55 fp32_cvt_storeu_bf16(&y[i], yv);
56 }
57#endif
58
59 /* Scalar fallback */
60 for (; i < n; ++i) {
61 float af = bf16_to_float(a[i]);
62 float bf = bf16_to_float(b[i]);
63 y[i] = float_to_bf16(af + bf);
64 }
65}

References bf16_to_float(), and float_to_bf16().

◆ add_forward_f32()

void add_forward_f32 ( const float *  a,
const float *  b,
float *  y,
size_t  n 
)

Element-wise add: y = a + b

Test:

test_add.py::TestAddForward::test_add_forward_f32

test_add.py::TestAddForward::test_add_inplace_f32

test_multi_layer_parity.py::TestMultiLayerParity::test_residual_add

Element-wise addition of two vectors.

After changes: make test

Definition at line 280 of file add_kernels_bf16.c.

284{
285 if (!a || !b || !y || n == 0) {
286 return;
287 }
288
289 size_t i = 0;
290
291#if defined(__AVX512F__)
292 for (; i + 16 <= n; i += 16) {
293 __m512 av = _mm512_loadu_ps(&a[i]);
294 __m512 bv = _mm512_loadu_ps(&b[i]);
295 __m512 yv = _mm512_add_ps(av, bv);
296 _mm512_storeu_ps(&y[i], yv);
297 }
298#endif
299
300#if defined(__AVX2__)
301 for (; i + 8 <= n; i += 8) {
302 __m256 av = _mm256_loadu_ps(&a[i]);
303 __m256 bv = _mm256_loadu_ps(&b[i]);
304 __m256 yv = _mm256_add_ps(av, bv);
305 _mm256_storeu_ps(&y[i], yv);
306 }
307#endif
308
309 for (; i < n; ++i) {
310 y[i] = a[i] + b[i];
311 }
312}

◆ add_inplace_bf16()

void add_inplace_bf16 ( uint16_t *  a,
const uint16_t *  b,
size_t  n 
)

Definition at line 119 of file add_kernels_bf16.c.

122{
123 if (!a || !b || n == 0) {
124 return;
125 }
126
127 size_t i = 0;
128
129#if defined(__AVX512F__)
130 for (; i + 16 <= n; i += 16) {
131 __m512 av = bf16_loadu_cvt_fp32(&a[i]);
132 __m512 bv = bf16_loadu_cvt_fp32(&b[i]);
133 __m512 yv = _mm512_add_ps(av, bv);
134 fp32_cvt_storeu_bf16(&a[i], yv);
135 }
136#endif
137
138 for (; i < n; ++i) {
139 float af = bf16_to_float(a[i]);
140 float bf = bf16_to_float(b[i]);
141 a[i] = float_to_bf16(af + bf);
142 }
143}

References bf16_to_float(), and float_to_bf16().

◆ add_inplace_f32()

void add_inplace_f32 ( float *  a,
const float *  b,
size_t  n 
)

Definition at line 314 of file add_kernels_bf16.c.

317{
318 if (!a || !b || n == 0) {
319 return;
320 }
321
322 size_t i = 0;
323
324#if defined(__AVX512F__)
325 for (; i + 16 <= n; i += 16) {
326 __m512 av = _mm512_loadu_ps(&a[i]);
327 __m512 bv = _mm512_loadu_ps(&b[i]);
328 __m512 yv = _mm512_add_ps(av, bv);
329 _mm512_storeu_ps(&a[i], yv);
330 }
331#endif
332
333#if defined(__AVX2__)
334 for (; i + 8 <= n; i += 8) {
335 __m256 av = _mm256_loadu_ps(&a[i]);
336 __m256 bv = _mm256_loadu_ps(&b[i]);
337 __m256 yv = _mm256_add_ps(av, bv);
338 _mm256_storeu_ps(&a[i], yv);
339 }
340#endif
341
342 for (; i < n; ++i) {
343 a[i] = a[i] + b[i];
344 }
345}

Referenced by mega_fused_outproj_mlp_prefill().

◆ add_scaled_forward_bf16()

void add_scaled_forward_bf16 ( const uint16_t *  a,
const uint16_t *  b,
uint16_t *  y,
float  alpha,
size_t  n 
)

Definition at line 86 of file add_kernels_bf16.c.

91{
92 if (!a || !b || !y || n == 0) {
93 return;
94 }
95
96 size_t i = 0;
97
98#if defined(__AVX512F__)
99 __m512 alpha_v = _mm512_set1_ps(alpha);
100 for (; i + 16 <= n; i += 16) {
101 __m512 av = bf16_loadu_cvt_fp32(&a[i]);
102 __m512 bv = bf16_loadu_cvt_fp32(&b[i]);
103 __m512 yv = _mm512_fmadd_ps(bv, alpha_v, av); /* a + alpha * b */
104 fp32_cvt_storeu_bf16(&y[i], yv);
105 }
106#endif
107
108 for (; i < n; ++i) {
109 float af = bf16_to_float(a[i]);
110 float bf = bf16_to_float(b[i]);
111 y[i] = float_to_bf16(af + alpha * bf);
112 }
113}

References bf16_to_float(), and float_to_bf16().

◆ add_scaled_inplace_bf16()

void add_scaled_inplace_bf16 ( uint16_t *  a,
const uint16_t *  b,
float  alpha,
size_t  n 
)

Definition at line 149 of file add_kernels_bf16.c.

153{
154 if (!a || !b || n == 0) {
155 return;
156 }
157
158 size_t i = 0;
159
160#if defined(__AVX512F__)
161 __m512 alpha_v = _mm512_set1_ps(alpha);
162 for (; i + 16 <= n; i += 16) {
163 __m512 av = bf16_loadu_cvt_fp32(&a[i]);
164 __m512 bv = bf16_loadu_cvt_fp32(&b[i]);
165 __m512 yv = _mm512_fmadd_ps(bv, alpha_v, av);
166 fp32_cvt_storeu_bf16(&a[i], yv);
167 }
168#endif
169
170 for (; i < n; ++i) {
171 float af = bf16_to_float(a[i]);
172 float bf = bf16_to_float(b[i]);
173 a[i] = float_to_bf16(af + alpha * bf);
174 }
175}

References bf16_to_float(), and float_to_bf16().

◆ ck_residual_add_token_major_bf16_storage()

void ck_residual_add_token_major_bf16_storage ( const float *  a,
const float *  b,
float *  out,
int  tokens,
int  aligned_embed_dim 
)

Definition at line 67 of file add_kernels_bf16.c.

72{
73 const size_t count = (size_t)tokens * (size_t)aligned_embed_dim;
74 for (size_t i = 0; i < count; ++i) {
75 const float av = bf16_to_float(float_to_bf16(a[i]));
76 const float bv = bf16_to_float(float_to_bf16(b[i]));
77 out[i] = bf16_to_float(float_to_bf16(av + bv));
78 }
79}
const uint8_t size_t count
Definition true_bpe.h:209

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