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

ReLU activation kernels with SIMD (SSE/AVX/AVX512) More...

#include <math.h>
#include <stddef.h>
#include <stdint.h>

Go to the source code of this file.

Functions

void relu2_backward (const float *input, const float *d_output, float *d_input, size_t n)
 
void relu2_forward (const float *input, float *output, size_t n)
 
void relu_backward (const float *input, const float *d_output, float *d_input, size_t n)
 
void relu_forward (const float *input, float *output, size_t n)
 
void relu_forward_inplace (float *data, size_t n)
 

Detailed Description

ReLU activation kernels with SIMD (SSE/AVX/AVX512)

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

ReLU: y = max(0, x)

Definition in file relu_kernels.c.

Function Documentation

◆ relu2_backward()

void relu2_backward ( const float *  input,
const float *  d_output,
float *  d_input,
size_t  n 
)

Definition at line 147 of file relu_kernels.c.

151{
152 size_t i = 0;
153
154#if defined(__AVX512F__)
155 const __m512 vzero = _mm512_setzero_ps();
156 const __m512 vtwo = _mm512_set1_ps(2.0f);
157 for (; i + 15 < n; i += 16) {
158 const __m512 vx = _mm512_loadu_ps(input + i);
159 const __m512 vdy = _mm512_loadu_ps(d_output + i);
160 const __mmask16 mask = _mm512_cmp_ps_mask(vx, vzero, _CMP_GT_OQ);
161 const __m512 vdx = _mm512_mul_ps(_mm512_mul_ps(vtwo, vx), vdy);
162 _mm512_storeu_ps(d_input + i, _mm512_maskz_mov_ps(mask, vdx));
163 }
164#elif defined(__AVX2__) || defined(__AVX__)
165 const __m256 vzero = _mm256_setzero_ps();
166 const __m256 vtwo = _mm256_set1_ps(2.0f);
167 for (; i + 7 < n; i += 8) {
168 const __m256 vx = _mm256_loadu_ps(input + i);
169 const __m256 vdy = _mm256_loadu_ps(d_output + i);
170 const __m256 mask = _mm256_cmp_ps(vx, vzero, _CMP_GT_OQ);
171 const __m256 vdx = _mm256_mul_ps(_mm256_mul_ps(vtwo, vx), vdy);
172 _mm256_storeu_ps(d_input + i, _mm256_and_ps(mask, vdx));
173 }
174#endif
175
176 for (; i < n; ++i) {
177 const float x = input[i];
178 d_input[i] = (x > 0.0f) ? d_output[i] * 2.0f * x : 0.0f;
179 }
180}
int32_t int32_t int32_t int32_t int32_t mask
Definition tokenizer.h:234

References mask.

◆ relu2_forward()

void relu2_forward ( const float *  input,
float *  output,
size_t  n 
)

Definition at line 120 of file relu_kernels.c.

121{
122 size_t i = 0;
123
124#if defined(__AVX512F__)
125 const __m512 vzero = _mm512_setzero_ps();
126 for (; i + 15 < n; i += 16) {
127 const __m512 vx = _mm512_loadu_ps(input + i);
128 const __m512 vr = _mm512_max_ps(vx, vzero);
129 _mm512_storeu_ps(output + i, _mm512_mul_ps(vr, vr));
130 }
131#elif defined(__AVX2__) || defined(__AVX__)
132 const __m256 vzero = _mm256_setzero_ps();
133 for (; i + 7 < n; i += 8) {
134 const __m256 vx = _mm256_loadu_ps(input + i);
135 const __m256 vr = _mm256_max_ps(vx, vzero);
136 _mm256_storeu_ps(output + i, _mm256_mul_ps(vr, vr));
137 }
138#endif
139
140 for (; i < n; ++i) {
141 const float x = input[i];
142 output[i] = (x > 0.0f) ? x * x : 0.0f;
143 }
144}

◆ relu_backward()

void relu_backward ( const float *  input,
const float *  d_output,
float *  d_input,
size_t  n 
)

Definition at line 84 of file relu_kernels.c.

88{
89 size_t i = 0;
90
91#if defined(__AVX512F__)
92 __m512 vzero = _mm512_setzero_ps();
93 for (; i + 15 < n; i += 16) {
94 __m512 vx = _mm512_loadu_ps(input + i);
95 __m512 vdy = _mm512_loadu_ps(d_output + i);
96 __mmask16 mask = _mm512_cmp_ps_mask(vx, vzero, _CMP_GT_OQ);
97 __m512 vdx = _mm512_maskz_mov_ps(mask, vdy);
98 _mm512_storeu_ps(d_input + i, vdx);
99 }
100#elif defined(__AVX2__) || defined(__AVX__)
101 __m256 vzero = _mm256_setzero_ps();
102 for (; i + 7 < n; i += 8) {
103 __m256 vx = _mm256_loadu_ps(input + i);
104 __m256 vdy = _mm256_loadu_ps(d_output + i);
105 // Result is all 1s (0xFFFFFFFF) if true, 0 if false.
106 __m256 mask = _mm256_cmp_ps(vx, vzero, _CMP_GT_OQ);
107 __m256 vdx = _mm256_and_ps(mask, vdy);
108 _mm256_storeu_ps(d_input + i, vdx);
109 }
110#endif
111
112 // Scalar fallback
113 for (; i < n; ++i) {
114 d_input[i] = (input[i] > 0.0f) ? d_output[i] : 0.0f;
115 }
116}

References mask.

◆ relu_forward()

void relu_forward ( const float *  input,
float *  output,
size_t  n 
)

Definition at line 26 of file relu_kernels.c.

27{
28 size_t i = 0;
29
30#if defined(__AVX512F__)
31 __m512 vzero = _mm512_setzero_ps();
32 for (; i + 15 < n; i += 16) {
33 __m512 vx = _mm512_loadu_ps(input + i);
34 __m512 vy = _mm512_max_ps(vx, vzero);
35 _mm512_storeu_ps(output + i, vy);
36 }
37#elif defined(__AVX2__) || defined(__AVX__)
38 __m256 vzero = _mm256_setzero_ps();
39 for (; i + 7 < n; i += 8) {
40 __m256 vx = _mm256_loadu_ps(input + i);
41 __m256 vy = _mm256_max_ps(vx, vzero);
42 _mm256_storeu_ps(output + i, vy);
43 }
44#endif
45
46 // Scalar fallback
47 for (; i < n; ++i) {
48 float x = input[i];
49 output[i] = (x > 0.0f) ? x : 0.0f;
50 }
51}

◆ relu_forward_inplace()

void relu_forward_inplace ( float *  data,
size_t  n 
)

Definition at line 54 of file relu_kernels.c.

55{
56 size_t i = 0;
57
58#if defined(__AVX512F__)
59 __m512 vzero = _mm512_setzero_ps();
60 for (; i + 15 < n; i += 16) {
61 __m512 vx = _mm512_loadu_ps(data + i);
62 __m512 vy = _mm512_max_ps(vx, vzero);
63 _mm512_storeu_ps(data + i, vy);
64 }
65#elif defined(__AVX2__) || defined(__AVX__)
66 __m256 vzero = _mm256_setzero_ps();
67 for (; i + 7 < n; i += 8) {
68 __m256 vx = _mm256_loadu_ps(data + i);
69 __m256 vy = _mm256_max_ps(vx, vzero);
70 _mm256_storeu_ps(data + i, vy);
71 }
72#endif
73
74 // Scalar fallback
75 for (; i < n; ++i) {
76 float x = data[i];
77 if (x < 0.0f) {
78 data[i] = 0.0f;
79 }
80 }
81}