← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
relu_kernels_bf16.c
Go to the documentation of this file.
1/**
2 * @file relu_kernels_bf16.c
3 * @brief ReLU activation kernels for BF16 tensors
4 *
5 * CK-ENGINE KERNEL RULES:
6 * =======================
7 * 1. NO malloc/free - memory via bump allocator, pointers passed in
8 * 2. NO OpenMP - parallelization at orchestrator/codegen layer
9 * 3. API must define: inputs, outputs, workspace, and memory layouts
10 * 4. Pure computation - deterministic, no side effects
11 *
12 * After changes: make test && make llamacpp-parity-full
13 *
14 * ReLU: y = max(0, x)
15 */
16
17#include <stddef.h>
18#include <stdint.h>
19
20#if defined(__AVX2__)
21#include <immintrin.h>
22#endif
23
24#include "bf16_utils.h"
25#include "ckernel_engine.h"
26
27void relu_forward_bf16(const uint16_t *input, uint16_t *output, size_t n)
28{
29 if (!input || !output) {
30 return;
31 }
32
33 size_t i = 0;
34#if defined(__AVX2__)
35 const __m256i zero = _mm256_setzero_si256();
36 for (; i + 16 <= n; i += 16) {
37 const __m256i x = _mm256_loadu_si256((const __m256i *)(input + i));
38 const __m256i mask = _mm256_cmpgt_epi16(x, zero);
39 const __m256i y = _mm256_and_si256(x, mask);
40 _mm256_storeu_si256((__m256i *)(output + i), y);
41 }
42#endif
43 for (; i < n; ++i) {
44 output[i] = (input[i] & 0x8000u) ? 0u : input[i];
45 }
46}
47
48void relu_forward_inplace_bf16(uint16_t *data, size_t n)
49{
50 if (!data) {
51 return;
52 }
53
54 size_t i = 0;
55#if defined(__AVX2__)
56 const __m256i zero = _mm256_setzero_si256();
57 for (; i + 16 <= n; i += 16) {
58 const __m256i x = _mm256_loadu_si256((const __m256i *)(data + i));
59 const __m256i mask = _mm256_cmpgt_epi16(x, zero);
60 const __m256i y = _mm256_and_si256(x, mask);
61 _mm256_storeu_si256((__m256i *)(data + i), y);
62 }
63#endif
64 for (; i < n; ++i) {
65 data[i] = (data[i] & 0x8000u) ? 0u : data[i];
66 }
67}
68
69void relu_backward_bf16(const uint16_t *input,
70 const uint16_t *d_output,
71 uint16_t *d_input,
72 size_t n)
73{
74 if (!input || !d_output || !d_input) {
75 return;
76 }
77
78 size_t i = 0;
79#if defined(__AVX2__)
80 const __m256i zero = _mm256_setzero_si256();
81 for (; i + 16 <= n; i += 16) {
82 const __m256i x = _mm256_loadu_si256((const __m256i *)(input + i));
83 const __m256i dy = _mm256_loadu_si256((const __m256i *)(d_output + i));
84 const __m256i mask = _mm256_cmpgt_epi16(x, zero);
85 const __m256i dx = _mm256_and_si256(dy, mask);
86 _mm256_storeu_si256((__m256i *)(d_input + i), dx);
87 }
88#endif
89 for (; i < n; ++i) {
90 d_input[i] = ((input[i] & 0x8000u) == 0u && (input[i] & 0x7fffu) != 0u) ? d_output[i] : 0u;
91 }
92}
void relu_forward_inplace_bf16(uint16_t *data, size_t n)
void relu_forward_bf16(const uint16_t *input, uint16_t *output, size_t n)
void relu_backward_bf16(const uint16_t *input, const uint16_t *d_output, uint16_t *d_input, size_t n)
int32_t int32_t int32_t int32_t int32_t mask
Definition tokenizer.h:234