1routine_ew_rust!(x86_64;
10 f32,
11 x86_64_avx512_hardswish_f32_64n,
12 64,
13 16,
14 #[inline(never)]
15 fn run(buf: &mut [f32], _: ()) {
16 debug_assert!(buf.len() % Self::nr() == 0);
17 debug_assert!(buf.as_ptr() as usize % Self::alignment_bytes() == 0);
18 if buf.is_empty() {
19 return;
20 }
21 unsafe { x86_64_avx512_hardswish_f32_64n_run(buf) }
22 },
23 func(Hardswish),
24 isa(X86_64Avx512f)
25);
26
27#[cfg(target_arch = "x86_64")]
28#[target_feature(enable = "avx512f")]
29unsafe fn x86_64_avx512_hardswish_f32_64n_run(buf: &mut [f32]) {
30 unsafe {
31 let len = buf.len();
32 let ptr = buf.as_ptr();
33 std::arch::asm!("
34 vbroadcastss zmm0, xmm0 // 3.0
35 vbroadcastss zmm1, xmm1 // 6.0
36 vbroadcastss zmm2, xmm2 // 1/6
37 vpxord zmm3, zmm3, zmm3 // 0.0
38 2:
39 vmovaps zmm4, [{ptr}]
40 vmovaps zmm5, [{ptr} + 64]
41 vmovaps zmm6, [{ptr} + 128]
42 vmovaps zmm7, [{ptr} + 192]
43
44 vaddps zmm8, zmm4, zmm0
45 vaddps zmm9, zmm5, zmm0
46 vaddps zmm10, zmm6, zmm0
47 vaddps zmm11, zmm7, zmm0
48
49 vminps zmm8, zmm8, zmm1
50 vminps zmm9, zmm9, zmm1
51 vminps zmm10, zmm10, zmm1
52 vminps zmm11, zmm11, zmm1
53
54 vmaxps zmm8, zmm8, zmm3
55 vmaxps zmm9, zmm9, zmm3
56 vmaxps zmm10, zmm10, zmm3
57 vmaxps zmm11, zmm11, zmm3
58
59 vmulps zmm8, zmm8, zmm4
60 vmulps zmm9, zmm9, zmm5
61 vmulps zmm10, zmm10, zmm6
62 vmulps zmm11, zmm11, zmm7
63
64 vmulps zmm8, zmm8, zmm2
65 vmulps zmm9, zmm9, zmm2
66 vmulps zmm10, zmm10, zmm2
67 vmulps zmm11, zmm11, zmm2
68
69 vmovaps [{ptr}], zmm8
70 vmovaps [{ptr} + 64], zmm9
71 vmovaps [{ptr} + 128], zmm10
72 vmovaps [{ptr} + 192], zmm11
73
74 add {ptr}, 256
75 sub {len}, 64
76 jnz 2b
77 ",
78 len = inout(reg) len => _,
79 ptr = inout(reg) ptr => _,
80 inout("xmm0") 3.0f32 => _,
81 inout("xmm1") 6.0f32 => _,
82 inout("xmm2") 1.0f32 / 6.0f32 => _,
83 out("zmm3") _,
84 out("zmm4") _, out("zmm5") _, out("zmm6") _, out("zmm7") _,
85 out("zmm8") _, out("zmm9") _, out("zmm10") _, out("zmm11") _,
86 );
87 }
88}
89
90routine_ew_rust!(x86_64;
92 f32,
93 x86_64_avx512_leaky_relu_f32_64n,
94 64,
95 16,
96 #[inline(never)]
97 fn run(buf: &mut [f32], alpha: f32) {
98 debug_assert!(buf.len() % Self::nr() == 0);
99 debug_assert!(buf.as_ptr() as usize % Self::alignment_bytes() == 0);
100 if buf.is_empty() {
101 return;
102 }
103 unsafe { x86_64_avx512_leaky_relu_f32_64n_run(buf, alpha) }
104 },
105 func(LeakyRelu),
106 param,
107 isa(X86_64Avx512f)
108);
109
110#[cfg(target_arch = "x86_64")]
111#[target_feature(enable = "avx512f")]
112unsafe fn x86_64_avx512_leaky_relu_f32_64n_run(buf: &mut [f32], alpha: f32) {
113 unsafe {
114 let len = buf.len();
115 let ptr = buf.as_ptr();
116 std::arch::asm!("
117 vbroadcastss zmm0, xmm0 // alpha
118 vpxord zmm1, zmm1, zmm1 // 0.0
119 2:
120 vmovaps zmm4, [{ptr}]
121 vmovaps zmm5, [{ptr} + 64]
122 vmovaps zmm6, [{ptr} + 128]
123 vmovaps zmm7, [{ptr} + 192]
124
125 // alpha * x in zmm8..11
126 vmulps zmm8, zmm4, zmm0
127 vmulps zmm9, zmm5, zmm0
128 vmulps zmm10, zmm6, zmm0
129 vmulps zmm11, zmm7, zmm0
130
131 // mask = x > 0
132 vcmpps k1, zmm4, zmm1, 14
133 vcmpps k2, zmm5, zmm1, 14
134 vcmpps k3, zmm6, zmm1, 14
135 vcmpps k4, zmm7, zmm1, 14
136
137 // where x > 0, overwrite alpha*x with x
138 vmovaps zmm8{{k1}}, zmm4
139 vmovaps zmm9{{k2}}, zmm5
140 vmovaps zmm10{{k3}}, zmm6
141 vmovaps zmm11{{k4}}, zmm7
142
143 vmovaps [{ptr}], zmm8
144 vmovaps [{ptr} + 64], zmm9
145 vmovaps [{ptr} + 128], zmm10
146 vmovaps [{ptr} + 192], zmm11
147
148 add {ptr}, 256
149 sub {len}, 64
150 jnz 2b
151 ",
152 len = inout(reg) len => _,
153 ptr = inout(reg) ptr => _,
154 inout("xmm0") alpha => _,
155 out("zmm1") _,
156 out("zmm4") _, out("zmm5") _, out("zmm6") _, out("zmm7") _,
157 out("zmm8") _, out("zmm9") _, out("zmm10") _, out("zmm11") _,
158 out("k1") _, out("k2") _, out("k3") _, out("k4") _,
159 );
160 }
161}
162
163routine_ew_rust!(x86_64;
169 f32,
170 x86_64_avx512_gelu_f32_16n,
171 16,
172 16,
173 #[inline(never)]
174 fn run(buf: &mut [f32], _: ()) {
175 debug_assert!(buf.len() % Self::nr() == 0);
176 debug_assert!(buf.as_ptr() as usize % Self::alignment_bytes() == 0);
177 const SQRT_2_OVER_PI: f32 = 0.7978845608028654;
178 const COEF: f32 = 0.044715;
179 const CHUNK: usize = 256;
180 let mut scratch = [0f32; CHUNK];
181 let mut start = 0;
182 while start < buf.len() {
183 let end = (start + CHUNK).min(buf.len());
184 let chunk = &mut buf[start..end];
185 let n = chunk.len();
186 for i in 0..n {
187 let x = chunk[i];
188 scratch[i] = x;
189 chunk[i] = SQRT_2_OVER_PI * (x + COEF * x * x * x);
190 }
191 super::avx512_tanh_f32::run(chunk, ());
192 for i in 0..n {
193 chunk[i] = 0.5 * scratch[i] * (1.0 + chunk[i]);
194 }
195 start = end;
196 }
197 },
198 func(Gelu),
199 isa(X86_64Avx512f)
200);