88
99using namespace aie ;
1010
11- void gelu_tanh_approx_bf16 (bfloat16 *restrict input_vector, bfloat16 *restrict output_vector, const int32_t vector_size)
11+ // One 16-lane GELU (tanh approximation): 0.5 * x * (1 + tanh(sqrt(2/pi) * (x + 0.044715 * x^3))).
12+ static inline aie::vector<bfloat16, 16 > gelu_tanh_approx_v16 (aie::vector<bfloat16, 16 > x)
1213{
13- event0 ();
14-
15- auto it_in = aie::begin_restrict_vector<16 >((bfloat16 *)input_vector);
16- auto it_out = aie::begin_restrict_vector<16 >((bfloat16 *)output_vector);
17-
18- aie::vector<bfloat16, 16 > input;
19-
20- // Constants
2114 const bfloat16 k0_5 = 0 .5f ;
2215 const bfloat16 k1 = 1 .0f ;
23- const bfloat16 sqrt_2_over_pi = 0 .79788456f ; // ≈ sqrt(2/π )
16+ const bfloat16 sqrt_2_over_pi = 0 .79788456f ; // sqrt(2/pi )
2417 const bfloat16 kBeta = 0 .044715f ;
2518
2619 auto v05 = aie::broadcast<bfloat16, 16 >(k0_5);
2720 auto v1 = aie::broadcast<bfloat16, 16 >(k1);
2821 auto vs2opi = aie::broadcast<bfloat16, 16 >(sqrt_2_over_pi);
2922 auto vBeta = aie::broadcast<bfloat16, 16 >(kBeta );
3023
24+ aie::vector<bfloat16, 16 > x2 = aie::mul (x, x);
25+ aie::vector<bfloat16, 16 > x3 = aie::mul (x, x2);
26+ aie::vector<bfloat16, 16 > x3_beta = aie::mul (x3, vBeta);
27+ aie::vector<bfloat16, 16 > inner = aie::add (x, x3_beta);
28+ auto inner1 = aie::mul (inner, vs2opi);
29+ auto tanh_out = aie::tanh<bfloat16>(inner1.to_vector <float >());
30+ aie::vector<bfloat16, 16 > one_plus_tanh = aie::add (tanh_out, v1);
31+ aie::vector<bfloat16, 16 > mul_v05 = aie::mul (v05, one_plus_tanh);
32+ return aie::mul (x, mul_v05).to_vector <bfloat16>();
33+ }
34+
35+ // Out-of-place GELU: output_vector = gelu(input_vector). input and output must not alias.
36+ void gelu_tanh_approx_bf16 (bfloat16 *restrict input_vector, bfloat16 *restrict output_vector, const int32_t vector_size)
37+ {
38+ event0 ();
39+ auto it_in = aie::begin_restrict_vector<16 >((bfloat16 *)input_vector);
40+ auto it_out = aie::begin_restrict_vector<16 >((bfloat16 *)output_vector);
41+
3142 AIE_PREPARE_FOR_PIPELINING
3243 AIE_LOOP_MIN_ITERATION_COUNT (64 )
3344 for (int i = 0 ; i < vector_size; i += 16 ) {
34- input = *it_in++;
35- auto x = input;
36-
37- // Compute x^3
38- aie::vector<bfloat16, 16 > x2 = aie::mul (x, x); // x^2
39- aie::vector<bfloat16, 16 > x3 = aie::mul (x, x2); // x^3
40-
41- // inner = sqrt(2/pi) * (x + 0.044715 * x^3)
42- aie::vector<bfloat16, 16 > x3_beta = aie::mul (x3, vBeta);
43- aie::vector<bfloat16, 16 > inner = aie::add (x, x3_beta);
44- auto inner1 = aie::mul (inner, vs2opi);
45-
46- // tanh_out = tanh(inner)
47- auto tanh_out = aie::tanh<bfloat16>(inner1.to_vector <float >());
48-
49- // result = 0.5 * x * (1 + tanh_out)
50- aie::vector<bfloat16, 16 > one_plus_tanh = aie::add (tanh_out, v1);
51- // Multiply by x and 0.5
52- aie::vector<bfloat16, 16 > mul_v05 = aie::mul (v05, one_plus_tanh);
53- auto result = aie::mul (x, mul_v05);
54-
55- *it_out++ = result.to_vector <bfloat16>();
45+ *it_out++ = gelu_tanh_approx_v16 (*it_in++);
5646 }
57-
5847 event1 ();
48+ }
5949
60- return ;
50+ // In-place GELU: v = gelu(v). Single pointer, so aliasing-correct (each 16-lane slot is read then written).
51+ static inline void gelu_tanh_approx_inplace_bf16 (bfloat16 *restrict v, const int32_t vector_size)
52+ {
53+ event0 ();
54+ auto it = aie::begin_restrict_vector<16 >(v);
55+ AIE_PREPARE_FOR_PIPELINING
56+ AIE_LOOP_MIN_ITERATION_COUNT (64 )
57+ for (int i = 0 ; i < vector_size; i += 16 ) {
58+ aie::vector<bfloat16, 16 > x = *it;
59+ *it++ = gelu_tanh_approx_v16 (x);
60+ }
61+ event1 ();
6162}
6263
6364extern " C" {
@@ -67,4 +68,11 @@ void gelu_bf16(bfloat16 *restrict input, bfloat16 *restrict output, int input_si
6768 gelu_tanh_approx_bf16 (input, output, input_size);
6869}
6970
71+ // In-place GELU over n bf16 elements (n a multiple of 16). Intended as a fused epilogue over a compute
72+ // tile (e.g. a GEMV output tile), applied once per tile in the producing core.
73+ void gelu_tile_bf16 (uint32_t n, bfloat16 *restrict c)
74+ {
75+ gelu_tanh_approx_inplace_bf16 (c, (int32_t )n);
76+ }
77+
7078} // extern "C"
0 commit comments