char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Ankit Khandelwalvulkan : fuse UNARY(GELU|SIGMOID|SILU|SOFTPLUS) + MUL (#27220)64e9bceb2

char/aliceai-t5-moe
5.0 KiB205 linesraw
1#version 450
2
3#include "types.glsl"
4#if defined(UNARY_MUL_FUSION)
5#include "generic_binary_head.glsl"
6#else
7#include "generic_unary_head.glsl"
8#endif
9
10#if defined(UNARY_MUL_FUSION)
11// OP on src1
12layout(constant_id = 1) const bool op_on_b = false;
13#endif
14
15#if defined(UNARY_MUL_FUSION)
16layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
17const uint num_threads = 256;
18#else
19layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
20#endif
21
22float op_abs(float x) {
23    return abs(x);
24}
25
26float op_sgn(float x) {
27    return sign(x);
28}
29
30float op_neg(float x) {
31    return -x;
32}
33
34float op_sqr(float x) {
35    return x * x;
36}
37
38float op_sqrt(float x) {
39    return sqrt(x);
40}
41
42float op_sin(float x) {
43    return sin(x);
44}
45
46float op_cos(float x) {
47    return cos(x);
48}
49
50float op_clamp(float x) {
51    return clamp(x, p.param1, p.param2);
52}
53
54float op_leaky_relu(float x) {
55    return max(x, 0.0f) + min(x, 0.0f) * p.param1;
56}
57
58float op_step(float x) {
59    return x > 0.0f ? 1.0f : 0.0f;
60}
61
62float op_tanh(float x) {
63    return 1.0f - 2.0f / (exp(2.0f*x) + 1.0f);
64}
65
66float op_elu(float x) {
67    return x < 0.0f ? exp(x) - 1.0f : x;
68}
69
70float op_relu(float x) {
71    return max(x, 0.0f);
72}
73
74float op_sigmoid(float x) {
75    return 1.0f / (1.0f + exp(-x));
76}
77
78float op_gelu(float x) {
79    const float GELU_COEF_A    = 0.044715f;
80    const float SQRT_2_OVER_PI = 0.79788456080286535587989211986876f;
81    const float val = SQRT_2_OVER_PI*x*(1.0f + GELU_COEF_A*x*x);
82    return 0.5f*x*(2.0f - 2.0f / (exp(2.0f * val) + 1.0f));
83}
84
85float op_gelu_quick(float x) {
86    const float GELU_QUICK_COEF = -1.702f;
87    return x * (1.0f / (1.0f + exp(GELU_QUICK_COEF * x)));
88}
89
90float op_silu(float x) {
91    return x / (1.0f + exp(-x));
92}
93
94float op_hardswish(float x) {
95    return x * min(1.0f, max(0.0f, (x + 3.0f) / 6.0f));
96}
97
98float op_hardsigmoid(float x) {
99    return min(1.0f, max(0.0f, (x + 3.0f) / 6.0f));
100}
101
102float op_exp(float x) {
103    return exp(x);
104}
105
106float op_expm1(float x) {
107    // exp(x) - 1 loses many ulps to cancellation near zero.  Use a degree-6
108    // Taylor expansion for |x| <= 1/4: the omitted x^7/5040 term is < 1.3e-8,
109    // about 0.5 ulp at expm1(0.25), and a host-side f32 model stays within
110    // 2 ulps over the interval.  The first native exp(x)-1 values outside the
111    // cutoff are about 1 ulp for +0.25 and 2 ulps for -0.25.
112    if (abs(x) <= 0.25f) {
113        return x * (1.0f + x * (0.5f + x * ((1.0f/6.0f) + x * ((1.0f/24.0f) + x * ((1.0f/120.0f) + x * (1.0f/720.0f))))));
114    }
115    return exp(x) - 1.0f;
116}
117
118float op_softplus(float x) {
119    return (x > 20.0f) ? x : log(1.0f + exp(x));
120}
121
122float op_gelu_erf(float a) {
123    // based on Abramowitz and Stegun formula 7.1.26 or similar Hastings' approximation
124    const float p_erf  = 0.3275911f;
125    const float a1_erf = 0.254829592f;
126    const float a2_erf = -0.284496736f;
127    const float a3_erf = 1.421413741f;
128    const float a4_erf = -1.453152027f;
129    const float a5_erf = 1.061405429f;
130
131    const float SQRT_2_INV = 0.70710678118654752440084436210484f;
132    const float a_div_sqr2 = a * SQRT_2_INV;
133    const float sign_x = sign(a_div_sqr2);
134    const float x = abs(a_div_sqr2);
135    const float t = 1.0f / (1.0f + p_erf * x);
136    const float y = 1.0f - (((((a5_erf * t + a4_erf) * t) + a3_erf) * t + a2_erf) * t + a1_erf) * t * exp(-x * x);
137    return 0.5f * a * (1.0f + sign_x * y);
138}
139
140#if !defined(UNARY_MUL_FUSION)
141float op_xielu(float x) {
142    const float alpha_n = p.param1;
143    const float alpha_p = p.param2;
144    const float beta = p.param3;
145    const float eps = p.param4;
146
147    if (x > 0.0f) {
148        return alpha_p * x * x + beta * x;
149    }
150
151    const float min_x_eps = min(x, eps);
152    return (op_expm1(min_x_eps) - x) * alpha_n + beta * x;
153}
154#endif
155
156float op_floor(float x) {
157    return floor(x);
158}
159
160float op_ceil(float x) {
161    return ceil(x);
162}
163
164float op_round(float x) {
165    // Round halfway cases away from zero as roundf does.
166    return x >= 0.0f ? floor(x + 0.5f) : ceil(x - 0.5f);
167}
168
169float op_trunc(float x) {
170    return trunc(x);
171}
172
173void main() {
174    uint idx = get_idx();
175
176#if defined(UNARY_MUL_FUSION)
177    // keep total threads at 512
178    [[unroll]] for (uint iter = 0; iter < 2; ++iter) {
179        if (idx >= p.ne) {
180            continue;
181        }
182        uint i00, i01, i02, i03;
183        get_indices(idx, i00, i01, i02, i03);
184
185        if (op_on_b) {
186            data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] =
187                D_TYPE(FLOAT_TYPE(OP(float(data_b[get_boffset() + src1_idx(i00, i01, i02, i03)]))) * FLOAT_TYPE(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)]));
188        } else {
189            data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] =
190                D_TYPE(FLOAT_TYPE(OP(float(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)]))) * FLOAT_TYPE(data_b[get_boffset() + src1_idx(i00, i01, i02, i03)]));
191        }
192
193        idx += num_threads;
194    }
195#else
196    if (idx >= p.ne) {
197        return;
198    }
199
200    const uint a_idx = get_aoffset() + src0_idx(idx);
201    const uint d_idx = get_doffset() + dst_idx(idx);
202
203    data_d[d_idx] = D_TYPE(OP(float(data_a[a_idx])));
204#endif
205}