26 static inline void gelu(
float *
RESTRICT x,
const size_t n)
noexcept
28 assert(n != 0 &&
"n must not be 0.");
29 assert(x !=
nullptr &&
"x must not be null.");
31 ptrdiff_t simd_end = 0;
33#if defined(__AVX512F__)
34 const __m512 ones512 = _mm512_set1_ps(1.0f);
35 const __m512 half512 = _mm512_set1_ps(0.5f);
36 const __m512 sqrt2overpi512 = _mm512_set1_ps(
MAGIC_GELU_1);
39 simd_end = (ptrdiff_t)n & ~(ptrdiff_t)15;
40 for (ptrdiff_t i = 0; i < simd_end; i += 16)
42 __m512 x512 = _mm512_loadu_ps(x + i);
43 __m512 cube512 = _mm512_mul_ps(x512, _mm512_mul_ps(x512, x512));
44 __m512 c1x512 = _mm512_mul_ps(sqrt2overpi512, x512);
45 __m512 inner512 = _mm512_fmadd_ps(cube512, gelu_coeff512, c1x512);
46 __m512 t512 = Sleef_tanhf16_u10(inner512);
47 __m512 res = _mm512_mul_ps(half512, _mm512_mul_ps(x512, _mm512_add_ps(t512, ones512)));
48 _mm512_storeu_ps(x + i, res);
51 const __m256 ones256 = _mm256_set1_ps(1.0f);
52 const __m256 half256 = _mm256_set1_ps(0.5f);
53 const __m256 sqrt2overpi256 = _mm256_set1_ps(
MAGIC_GELU_1);
56 simd_end = (ptrdiff_t)n & ~(ptrdiff_t)7;
57 for (ptrdiff_t i = 0; i < simd_end; i += 8)
59 __m256 x256 = _mm256_loadu_ps(x + i);
60 __m256 cube256 = _mm256_mul_ps(x256, _mm256_mul_ps(x256, x256));
61 __m256 c1x256 = _mm256_mul_ps(sqrt2overpi256, x256);
63 __m256 inner256 = _mm256_fmadd_ps(cube256, gelu_coeff256, c1x256);
65 __m256 inner256 = _mm256_add_ps(_mm256_mul_ps(cube256, gelu_coeff256), c1x256);
67 __m256 t256 = Sleef_tanhf8_u10(inner256);
68 __m256 res = _mm256_mul_ps(half256, _mm256_mul_ps(x256, _mm256_add_ps(t256, ones256)));
69 _mm256_storeu_ps(x + i, res);
71#elif defined(__SSE__) || defined(_M_AMD64) || defined(_M_X64)
72 const __m128 ones128 = _mm_set1_ps(1.0f);
73 const __m128 half128 = _mm_set1_ps(0.5f);
77 simd_end = (ptrdiff_t)n & ~(ptrdiff_t)3;
78 for (ptrdiff_t i = 0; i < simd_end; i += 4)
80 __m128 x128 = _mm_loadu_ps(x + i);
81 __m128 cube128 = _mm_mul_ps(x128, _mm_mul_ps(x128, x128));
82 __m128 c1x128 = _mm_mul_ps(sqrt2overpi128, x128);
84 __m128 inner128 = _mm_fmadd_ps(cube128, gelu_coeff128, c1x128);
86 __m128 inner128 = _mm_add_ps(c1x128, _mm_mul_ps(cube128, gelu_coeff128));
88 __m128 t128 = Sleef_tanhf4_u10(inner128);
89 __m128 res = _mm_mul_ps(half128, _mm_mul_ps(x128, _mm_add_ps(t128, ones128)));
90 _mm_storeu_ps(x + i, res);
93 for (ptrdiff_t i = simd_end; i < n; ++i)
97 x[i] = 0.5f * xi * (1.0f + Sleef_tanhf_u10(inner));
110 static inline void dGelu(
float *
RESTRICT x,
const size_t n,
const bool activated)
noexcept
112 assert(n != 0 &&
"n must not be 0.");
113 assert(x !=
nullptr &&
"x must not be null.");
115 ptrdiff_t simd_end = 0;
117#if defined(__AVX512F__)
118 const __m512 ones512 = _mm512_set1_ps(1.0f);
119 const __m512 half512 = _mm512_set1_ps(0.5f);
124 simd_end = (ptrdiff_t)n & ~(ptrdiff_t)15;
125 for (ptrdiff_t i = 0; i < simd_end; i += 16)
127 __m512 x512 = _mm512_loadu_ps(x + i);
128 __m512 xsq512 = _mm512_mul_ps(x512, x512);
129 __m512 xcube512 = _mm512_mul_ps(xsq512, x512);
130 __m512 c1x512 = _mm512_mul_ps(c1_512, x512);
131 __m512 inner512 = _mm512_fmadd_ps(xcube512, c2_512, c1x512);
133 __m512 t512 = Sleef_tanhf16_u10(inner512);
134 __m512 tsq512 = _mm512_mul_ps(t512, t512);
136 __m512 one_minus_tsq512 = _mm512_sub_ps(ones512, tsq512);
137 __m512 gprime512 = _mm512_fmadd_ps(xsq512, c2_x3_512, c1_512);
139 __m512 term1 = _mm512_mul_ps(half512, _mm512_add_ps(ones512, t512));
140 __m512 term2 = _mm512_mul_ps(half512, _mm512_mul_ps(x512, _mm512_mul_ps(gprime512, one_minus_tsq512)));
141 __m512 res = _mm512_add_ps(term1, term2);
142 _mm512_storeu_ps(x + i, res);
144#elif defined(__AVX__)
145 const __m256 ones256 = _mm256_set1_ps(1.0f);
146 const __m256 half256 = _mm256_set1_ps(0.5f);
151 simd_end = (ptrdiff_t)n & ~(ptrdiff_t)7;
152 for (ptrdiff_t i = 0; i < simd_end; i += 8)
154 __m256 x256 = _mm256_loadu_ps(x + i);
155 __m256 xsq256 = _mm256_mul_ps(x256, x256);
156 __m256 xcube256 = _mm256_mul_ps(xsq256, x256);
157 __m256 c1x256 = _mm256_mul_ps(c1_256, x256);
160 __m256 inner256 = _mm256_fmadd_ps(xcube256, c2_256, c1x256);
161 __m256 gprime256 = _mm256_fmadd_ps(xsq256, c2_x3_256, c1_256);
163 __m256 inner256 = _mm256_add_ps(_mm256_mul_ps(xcube256, c2_256), c1x256);
164 __m256 gprime256 = _mm256_add_ps(_mm256_mul_ps(xsq256, c2_x3_256), c1_256);
167 __m256 t256 = Sleef_tanhf8_u10(inner256);
168 __m256 tsq256 = _mm256_mul_ps(t256, t256);
169 __m256 one_minus_tsq256 = _mm256_sub_ps(ones256, tsq256);
171 __m256 term1 = _mm256_mul_ps(half256, _mm256_add_ps(ones256, t256));
172 __m256 term2 = _mm256_mul_ps(half256, _mm256_mul_ps(x256, _mm256_mul_ps(gprime256, one_minus_tsq256)));
174 _mm256_storeu_ps(x + i, _mm256_add_ps(term1, term2));
176#elif defined(__SSE__) || defined(_M_AMD64) || defined(_M_X64)
177 const __m128 ones128 = _mm_set1_ps(1.0f);
178 const __m128 half128 = _mm_set1_ps(0.5f);
183 simd_end = (ptrdiff_t)n & ~(ptrdiff_t)3;
184 for (ptrdiff_t i = 0; i < simd_end; i += 4)
186 __m128 x128 = _mm_loadu_ps(x + i);
187 __m128 xsq128 = _mm_mul_ps(x128, x128);
188 __m128 xcube128 = _mm_mul_ps(xsq128, x128);
189 __m128 c1x128 = _mm_mul_ps(c1_128, x128);
192 __m128 inner128 = _mm_fmadd_ps(xcube128, c2_128, c1x128);
193 __m128 gprime128 = _mm_fmadd_ps(xsq128, c2_x3_128, c1_128);
195 __m128 inner128 = _mm_add_ps(_mm_mul_ps(xcube128, c2_128), c1x128);
196 __m128 gprime128 = _mm_add_ps(_mm_mul_ps(xsq128, c2_x3_128), c1_128);
199 __m128 t128 = Sleef_tanhf4_u10(inner128);
200 __m128 tsq128 = _mm_mul_ps(t128, t128);
201 __m128 one_minus_tsq128 = _mm_sub_ps(ones128, tsq128);
203 __m128 term1 = _mm_mul_ps(half128, _mm_add_ps(ones128, t128));
204 __m128 term2 = _mm_mul_ps(half128, _mm_mul_ps(x128, _mm_mul_ps(gprime128, one_minus_tsq128)));
206 _mm_storeu_ps(x + i, _mm_add_ps(term1, term2));
209 for (ptrdiff_t i = simd_end; i < n; ++i)
215 float t = Sleef_tanhf_u10(inner);
219 float term1 = 0.5f * (1.0f + t);
220 float term2 = 0.5f * xi * gprime * (1.0f - t * t);
222 x[i] = term1 + term2;
231 ptrdiff_t simd_end = 0;
233#if defined(__AVX512F__)
234 const __m512 ones512 = _mm512_set1_ps(1.0f);
235 const __m512 half512 = _mm512_set1_ps(0.5f);
240 simd_end = (ptrdiff_t)n & ~(ptrdiff_t)15;
241 for (ptrdiff_t i = 0; i < simd_end; i += 16)
243 __m512 x512 = _mm512_loadu_ps(src + i);
244 __m512 xsq512 = _mm512_mul_ps(x512, x512);
245 __m512 xcube512 = _mm512_mul_ps(xsq512, x512);
246 __m512 c1x512 = _mm512_mul_ps(c1_512, x512);
247 __m512 inner512 = _mm512_fmadd_ps(xcube512, c2_512, c1x512);
249 __m512 t512 = Sleef_tanhf16_u10(inner512);
250 __m512 tsq512 = _mm512_mul_ps(t512, t512);
252 __m512 one_minus_tsq512 = _mm512_sub_ps(ones512, tsq512);
253 __m512 gprime512 = _mm512_fmadd_ps(xsq512, c2_x3_512, c1_512);
255 __m512 term1 = _mm512_mul_ps(half512, _mm512_add_ps(ones512, t512));
256 __m512 term2 = _mm512_mul_ps(half512, _mm512_mul_ps(x512, _mm512_mul_ps(gprime512, one_minus_tsq512)));
257 __m512 res = _mm512_add_ps(term1, term2);
258 _mm512_storeu_ps(dst + i, res);
260#elif defined(__AVX__)
261 const __m256 ones256 = _mm256_set1_ps(1.0f);
262 const __m256 half256 = _mm256_set1_ps(0.5f);
267 simd_end = (ptrdiff_t)n & ~(ptrdiff_t)7;
268 for (ptrdiff_t i = 0; i < simd_end; i += 8)
270 __m256 x256 = _mm256_loadu_ps(src + i);
271 __m256 xsq256 = _mm256_mul_ps(x256, x256);
272 __m256 xcube256 = _mm256_mul_ps(xsq256, x256);
273 __m256 c1x256 = _mm256_mul_ps(c1_256, x256);
276 __m256 inner256 = _mm256_fmadd_ps(xcube256, c2_256, c1x256);
277 __m256 gprime256 = _mm256_fmadd_ps(xsq256, c2_x3_256, c1_256);
279 __m256 inner256 = _mm256_add_ps(_mm256_mul_ps(xcube256, c2_256), c1x256);
280 __m256 gprime256 = _mm256_add_ps(_mm256_mul_ps(xsq256, c2_x3_256), c1_256);
283 __m256 t256 = Sleef_tanhf8_u10(inner256);
284 __m256 tsq256 = _mm256_mul_ps(t256, t256);
285 __m256 one_minus_tsq256 = _mm256_sub_ps(ones256, tsq256);
287 __m256 term1 = _mm256_mul_ps(half256, _mm256_add_ps(ones256, t256));
288 __m256 term2 = _mm256_mul_ps(half256, _mm256_mul_ps(x256, _mm256_mul_ps(gprime256, one_minus_tsq256)));
290 _mm256_storeu_ps(dst + i, _mm256_add_ps(term1, term2));
292#elif defined(__SSE__) || defined(_M_AMD64) || defined(_M_X64)
293 const __m128 ones128 = _mm_set1_ps(1.0f);
294 const __m128 half128 = _mm_set1_ps(0.5f);
299 simd_end = (ptrdiff_t)n & ~(ptrdiff_t)3;
300 for (ptrdiff_t i = 0; i < simd_end; i += 4)
302 __m128 x128 = _mm_loadu_ps(src + i);
303 __m128 xsq128 = _mm_mul_ps(x128, x128);
304 __m128 xcube128 = _mm_mul_ps(xsq128, x128);
305 __m128 c1x128 = _mm_mul_ps(c1_128, x128);
308 __m128 inner128 = _mm_fmadd_ps(xcube128, c2_128, c1x128);
309 __m128 gprime128 = _mm_fmadd_ps(xsq128, c2_x3_128, c1_128);
311 __m128 inner128 = _mm_add_ps(_mm_mul_ps(xcube128, c2_128), c1x128);
312 __m128 gprime128 = _mm_add_ps(_mm_mul_ps(xsq128, c2_x3_128), c1_128);
315 __m128 t128 = Sleef_tanhf4_u10(inner128);
316 __m128 tsq128 = _mm_mul_ps(t128, t128);
317 __m128 one_minus_tsq128 = _mm_sub_ps(ones128, tsq128);
319 __m128 term1 = _mm_mul_ps(half128, _mm_add_ps(ones128, t128));
320 __m128 term2 = _mm_mul_ps(half128, _mm_mul_ps(x128, _mm_mul_ps(gprime128, one_minus_tsq128)));
322 _mm_storeu_ps(dst + i, _mm_add_ps(term1, term2));
325 for (ptrdiff_t i = simd_end; i < n; ++i)
331 float t = Sleef_tanhf_u10(inner);
335 float term1 = 0.5f * (1.0f + t);
336 float term2 = 0.5f * xi * gprime * (1.0f - t * t);
338 dst[i] = term1 + term2;