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 >
13+ gelu_tanh_approx_v16 (aie::vector<bfloat16, 16 > x)
1214{
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
2115 const bfloat16 k0_5 = 0 .5f ;
2216 const bfloat16 k1 = 1 .0f ;
23- const bfloat16 sqrt_2_over_pi = 0 .79788456f ; // ≈ sqrt(2/π )
17+ const bfloat16 sqrt_2_over_pi = 0 .79788456f ; // sqrt(2/pi )
2418 const bfloat16 kBeta = 0 .044715f ;
2519
2620 auto v05 = aie::broadcast<bfloat16, 16 >(k0_5);
2721 auto v1 = aie::broadcast<bfloat16, 16 >(k1);
2822 auto vs2opi = aie::broadcast<bfloat16, 16 >(sqrt_2_over_pi);
2923 auto vBeta = aie::broadcast<bfloat16, 16 >(kBeta );
3024
25+ aie::vector<bfloat16, 16 > x2 = aie::mul (x, x);
26+ aie::vector<bfloat16, 16 > x3 = aie::mul (x, x2);
27+ aie::vector<bfloat16, 16 > x3_beta = aie::mul (x3, vBeta);
28+ aie::vector<bfloat16, 16 > inner = aie::add (x, x3_beta);
29+ auto inner1 = aie::mul (inner, vs2opi);
30+ auto tanh_out = aie::tanh<bfloat16>(inner1.to_vector <float >());
31+ aie::vector<bfloat16, 16 > one_plus_tanh = aie::add (tanh_out, v1);
32+ aie::vector<bfloat16, 16 > mul_v05 = aie::mul (v05, one_plus_tanh);
33+ return aie::mul (x, mul_v05).to_vector <bfloat16>();
34+ }
35+
36+ // Out-of-place GELU: output_vector = gelu(input_vector). input and output must not alias.
37+ void gelu_tanh_approx_bf16 (bfloat16 *restrict input_vector, bfloat16 *restrict output_vector, const int32_t vector_size)
38+ {
39+ event0 ();
40+ auto it_in = aie::begin_restrict_vector<16 >((bfloat16 *)input_vector);
41+ auto it_out = aie::begin_restrict_vector<16 >((bfloat16 *)output_vector);
42+
3143 AIE_PREPARE_FOR_PIPELINING
3244 AIE_LOOP_MIN_ITERATION_COUNT (64 )
3345 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>();
46+ *it_out++ = gelu_tanh_approx_v16 (*it_in++);
5647 }
57-
5848 event1 ();
49+ }
5950
60- return ;
51+ // In-place GELU: v = gelu(v). Single pointer, so aliasing-correct (each 16-lane slot is read then written).
52+ static inline void gelu_tanh_approx_inplace_bf16 (bfloat16 *restrict v, const int32_t vector_size)
53+ {
54+ event0 ();
55+ auto it = aie::begin_restrict_vector<16 >(v);
56+ AIE_PREPARE_FOR_PIPELINING
57+ AIE_LOOP_MIN_ITERATION_COUNT (64 )
58+ for (int i = 0 ; i < vector_size; i += 16 ) {
59+ aie::vector<bfloat16, 16 > x = *it;
60+ *it++ = gelu_tanh_approx_v16 (x);
61+ }
62+ event1 ();
6163}
6264
6365extern " C" {
@@ -67,4 +69,11 @@ void gelu_bf16(bfloat16 *restrict input, bfloat16 *restrict output, int input_si
6769 gelu_tanh_approx_bf16 (input, output, input_size);
6870}
6971
72+ // In-place GELU over n bf16 elements (n a multiple of 16). Intended as a fused epilogue over a compute
73+ // tile (e.g. a GEMV output tile), applied once per tile in the producing core.
74+ void gelu_tile_bf16 (uint32_t n, bfloat16 *restrict c)
75+ {
76+ gelu_tanh_approx_inplace_bf16 (c, (int32_t )n);
77+ }
78+
7079} // extern "C"
0 commit comments