← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
audio_conv1d_checked.c
Go to the documentation of this file.
4
5#include <limits.h>
6#include <math.h>
7#include <stdint.h>
8#include <string.h>
9
10#if (defined(__x86_64__) || defined(__i386__)) && \
11 (defined(__GNUC__) || defined(__clang__))
12#include <immintrin.h>
13#endif
14
15#if (defined(__x86_64__) || defined(__i386__)) && \
16 (defined(__GNUC__) || defined(__clang__))
17#define CK_AUDIO_CONV_X86_TARGET_FMA 1
18#else
19#define CK_AUDIO_CONV_X86_TARGET_FMA 0
20#endif
21
22/* Both implementations execute the same channel/frame/input/tap reduction.
23 * Only the function target changes how the explicit fmaf is implemented. */
24#define CK_AUDIO_CONV1D_COMPUTE_BODY \
25 for (size_t oc = job->channel_begin; oc < job->channel_end; ++oc) { \
26 for (size_t frame = 0; frame < job->output_frames; ++frame) { \
27 float sum = job->bias[oc]; \
28 for (size_t ic = 0; ic < job->input_channels; ++ic) { \
29 const float *row = job->weight + \
30 (oc * job->input_channels + ic) * job->kernel_size; \
31 for (size_t tap = 0; tap < job->kernel_size; ++tap) { \
32 int64_t source = (int64_t)frame * job->stride + \
33 (int64_t)tap * job->dilation - job->padding; \
34 if (source >= 0 && (size_t)source < job->input_frames) \
35 sum = fmaf(job->input[ic * job->input_stride + \
36 (size_t)source], row[tap], sum); \
37 } \
38 } \
39 job->staged[oc * job->output_frames + frame] = sum; \
40 } \
41 }
42
43static void audio_conv1d_compute_scalar(const ck_audio_conv1d_job *job, void *unused) {
44 (void)unused;
46}
47
48#if CK_AUDIO_CONV_X86_TARGET_FMA
49__attribute__((target("fma"), noinline))
50static void audio_conv1d_compute_hwfma(const ck_audio_conv1d_job *job, void *unused) {
51 (void)unused;
53}
54
55/* Output frames are independent. SIMD lanes retain the input-channel/tap
56 * reduction order of the scalar FMA provider; padding frames use its exact
57 * scalar path, so no zero-padded arithmetic is introduced. */
58__attribute__((target("avx2,fma"), noinline))
59void audio_conv1d_compute_avx2(const ck_audio_conv1d_job *job, void *unused) {
60 (void)unused;
61 if (job->stride != 1 || job->output_frames < 8) {
62 audio_conv1d_compute_hwfma(job, NULL);
63 return;
64 }
65 const size_t final_tap = (job->kernel_size - 1) * job->dilation;
66 for (size_t oc = job->channel_begin; oc < job->channel_end; ++oc) {
67 size_t frame = 0;
68 for (; frame < job->output_frames;) {
69 const int64_t first = (int64_t)frame - (int64_t)job->padding;
70 const int64_t last = first + 7 + (int64_t)final_tap;
71 if (frame + 8 <= job->output_frames && first >= 0 &&
72 last < (int64_t)job->input_frames) {
73 __m256 sums = _mm256_set1_ps(job->bias[oc]);
74 for (size_t ic = 0; ic < job->input_channels; ++ic) {
75 const float *row = job->weight +
76 (oc * job->input_channels + ic) * job->kernel_size;
77 const float *input = job->input + ic * job->input_stride +
78 (size_t)first;
79 for (size_t tap = 0; tap < job->kernel_size; ++tap) {
80 const __m256 values = _mm256_loadu_ps(input + tap * job->dilation);
81 sums = _mm256_fmadd_ps(values, _mm256_set1_ps(row[tap]), sums);
82 }
83 }
84 _mm256_storeu_ps(job->staged + oc * job->output_frames + frame, sums);
85 frame += 8;
86 } else {
87 float sum = job->bias[oc];
88 for (size_t ic = 0; ic < job->input_channels; ++ic) {
89 const float *row = job->weight +
90 (oc * job->input_channels + ic) * job->kernel_size;
91 for (size_t tap = 0; tap < job->kernel_size; ++tap) {
92 const int64_t source = (int64_t)frame +
93 (int64_t)tap * (int64_t)job->dilation -
94 (int64_t)job->padding;
95 if (source >= 0 && source < (int64_t)job->input_frames)
96 sum = fmaf(job->input[ic * job->input_stride +
97 (size_t)source], row[tap], sum);
98 }
99 }
100 job->staged[oc * job->output_frames + frame] = sum;
101 ++frame;
102 }
103 }
104 }
105}
106#endif
107#undef CK_AUDIO_CONV1D_COMPUTE_BODY
108
110#if CK_AUDIO_CONV_X86_TARGET_FMA
111 __builtin_cpu_init();
112 return __builtin_cpu_supports("fma") != 0;
113#else
114 return 0;
115#endif
116}
117
119#if CK_AUDIO_CONV_X86_TARGET_FMA
120 __builtin_cpu_init();
121 return __builtin_cpu_supports("avx2") && __builtin_cpu_supports("fma");
122#else
123 return 0;
124#endif
125}
126
127int audio_conv1d_checked_workspace(size_t input_channels, size_t output_channels,
128 size_t input_frames, size_t output_frames, size_t *scratch_elements) {
129 size_t staged;
130 if (!scratch_elements || !input_channels || !output_channels ||
131 !input_frames || !output_frames ||
132 input_channels > SIZE_MAX / input_frames ||
133 output_channels > SIZE_MAX / output_frames)
135 staged = output_channels * output_frames;
136 if (staged > SIZE_MAX / sizeof(float))
138 *scratch_elements = staged;
140}
141
143 const float *input, size_t input_elements, size_t input_stride,
144 const float *weight, size_t weight_elements,
145 const float *bias, size_t bias_elements,
146 float *output, size_t output_elements, size_t output_stride,
147 float *scratch, size_t scratch_elements,
148 size_t input_channels, size_t output_channels, size_t input_frames,
149 size_t kernel_size, size_t stride, size_t padding, size_t dilation,
150 size_t output_frames,
151 ck_audio_conv1d_compute_fn compute, void *compute_context) {
152 size_t input_span, output_span, weight_count, scratch_need;
153 if (!input_channels || !output_channels || !input_frames ||
154 !kernel_size || !stride || !dilation || !output_frames ||
155 input_channels > INT_MAX || output_channels > INT_MAX ||
156 input_frames > INT_MAX || kernel_size > INT_MAX ||
157 stride > INT_MAX || padding > INT_MAX || dilation > INT_MAX ||
158 output_frames > INT_MAX)
160 const int64_t effective_kernel = 1 +
161 ((int64_t)kernel_size - 1) * (int64_t)dilation;
162 const int64_t padded = (int64_t)input_frames +
163 2 * (int64_t)padding - effective_kernel;
164 if (padded < 0 || padded / stride + 1 != output_frames)
166 if (!ck_checked_span((size_t)input_channels, (size_t)input_frames,
167 input_stride, &input_span) ||
168 !ck_checked_span((size_t)output_channels, (size_t)output_frames,
169 output_stride, &output_span) ||
170 audio_conv1d_checked_workspace((size_t)input_channels,
171 (size_t)output_channels, (size_t)input_frames,
172 (size_t)output_frames, &scratch_need))
174 if ((size_t)output_channels > SIZE_MAX / (size_t)input_channels ||
175 (size_t)output_channels * (size_t)input_channels > SIZE_MAX / (size_t)kernel_size)
177 weight_count = (size_t)output_channels * (size_t)input_channels * (size_t)kernel_size;
178 if (weight_count > SIZE_MAX / sizeof(float)) return CK_AUDIO_CONV_CHECKED_OVERFLOW;
179 if (input_elements < input_span || weight_elements < weight_count ||
180 bias_elements < (size_t)output_channels || output_elements < output_span ||
181 scratch_elements < scratch_need)
183 if (!ck_checked_region(input, input_span) ||
184 !ck_checked_region(weight, weight_count) ||
185 !ck_checked_region(bias, (size_t)output_channels) ||
186 !ck_checked_region(output, output_span) ||
187 !ck_checked_region(scratch, scratch_need))
189 if (ck_checked_overlap(output, output_span, input, input_span) ||
190 ck_checked_overlap(output, output_span, weight, weight_count) ||
191 ck_checked_overlap(output, output_span, bias, (size_t)output_channels) ||
192 ck_checked_overlap(output, output_span, scratch, scratch_need) ||
193 ck_checked_overlap(scratch, scratch_need, input, input_span) ||
194 ck_checked_overlap(scratch, scratch_need, weight, weight_count) ||
195 ck_checked_overlap(scratch, scratch_need, bias, (size_t)output_channels))
197 if (!ck_checked_finite(weight, weight_count) ||
198 !ck_checked_finite(bias, (size_t)output_channels))
200 for (size_t channel = 0; channel < input_channels; ++channel)
201 if (!ck_checked_finite(input + (size_t)channel * input_stride,
202 (size_t)input_frames))
204 /* Validation and staged commit remain shared by both providers. */
205 const ck_audio_conv1d_job job = {input, weight, bias, scratch,
206 input_stride, input_channels, output_channels, input_frames,
207 kernel_size, stride, padding, dilation, output_frames, 0,
208 output_channels};
209 compute(&job, compute_context);
210 if (!ck_checked_finite(scratch, (size_t)output_channels * (size_t)output_frames))
212 for (size_t channel = 0; channel < output_channels; ++channel)
213 memcpy(output + (size_t)channel * output_stride,
214 scratch + (size_t)channel * (size_t)output_frames,
215 (size_t)output_frames * sizeof(float));
217}
218
220 const float *input, size_t input_elements, size_t input_stride,
221 const float *weight, size_t weight_elements,
222 const float *bias, size_t bias_elements,
223 float *output, size_t output_elements, size_t output_stride,
224 float *scratch, size_t scratch_elements,
225 size_t input_channels, size_t output_channels, size_t input_frames,
226 size_t kernel_size, size_t stride, size_t padding, size_t output_frames) {
227 return ck_audio_conv1d_checked_execute(input, input_elements, input_stride,
228 weight, weight_elements, bias, bias_elements, output, output_elements,
229 output_stride, scratch, scratch_elements, input_channels,
230 output_channels, input_frames, kernel_size, stride, padding, 1,
231 output_frames, audio_conv1d_compute_scalar, NULL);
232}
233
235 const float *input, size_t input_elements, size_t input_stride,
236 const float *weight, size_t weight_elements,
237 const float *bias, size_t bias_elements,
238 float *output, size_t output_elements, size_t output_stride,
239 float *scratch, size_t scratch_elements,
240 size_t input_channels, size_t output_channels, size_t input_frames,
241 size_t kernel_size, size_t stride, size_t padding, size_t dilation,
242 size_t output_frames) {
243 return ck_audio_conv1d_checked_execute(input, input_elements, input_stride,
244 weight, weight_elements, bias, bias_elements, output, output_elements,
245 output_stride, scratch, scratch_elements, input_channels,
246 output_channels, input_frames, kernel_size, stride, padding, dilation,
247 output_frames, audio_conv1d_compute_scalar, NULL);
248}
249
251 const float *input, size_t input_elements, size_t input_stride,
252 const float *weight, size_t weight_elements,
253 const float *bias, size_t bias_elements,
254 float *output, size_t output_elements, size_t output_stride,
255 float *scratch, size_t scratch_elements,
256 size_t input_channels, size_t output_channels, size_t input_frames,
257 size_t kernel_size, size_t stride, size_t padding, size_t output_frames) {
258#if CK_AUDIO_CONV_X86_TARGET_FMA
261 return ck_audio_conv1d_checked_execute(input, input_elements, input_stride,
262 weight, weight_elements, bias, bias_elements, output, output_elements,
263 output_stride, scratch, scratch_elements, input_channels,
264 output_channels, input_frames, kernel_size, stride, padding, 1,
265 output_frames, audio_conv1d_compute_hwfma, NULL);
266#else
267 (void)input; (void)input_elements; (void)input_stride;
268 (void)weight; (void)weight_elements; (void)bias; (void)bias_elements;
269 (void)output; (void)output_elements; (void)output_stride;
270 (void)scratch; (void)scratch_elements; (void)input_channels;
271 (void)output_channels; (void)input_frames; (void)kernel_size;
272 (void)stride; (void)padding; (void)output_frames;
274#endif
275}
276
278 const float *input, size_t input_elements, size_t input_stride,
279 const float *weight, size_t weight_elements,
280 const float *bias, size_t bias_elements,
281 float *output, size_t output_elements, size_t output_stride,
282 float *scratch, size_t scratch_elements,
283 size_t input_channels, size_t output_channels, size_t input_frames,
284 size_t kernel_size, size_t stride, size_t padding, size_t dilation,
285 size_t output_frames) {
286#if CK_AUDIO_CONV_X86_TARGET_FMA
289 return ck_audio_conv1d_checked_execute(input, input_elements, input_stride,
290 weight, weight_elements, bias, bias_elements, output, output_elements,
291 output_stride, scratch, scratch_elements, input_channels,
292 output_channels, input_frames, kernel_size, stride, padding, dilation,
293 output_frames, audio_conv1d_compute_hwfma, NULL);
294#else
295 (void)input; (void)input_elements; (void)input_stride;
296 (void)weight; (void)weight_elements; (void)bias; (void)bias_elements;
297 (void)output; (void)output_elements; (void)output_stride;
298 (void)scratch; (void)scratch_elements; (void)input_channels;
299 (void)output_channels; (void)input_frames; (void)kernel_size;
300 (void)stride; (void)padding; (void)dilation; (void)output_frames;
302#endif
303}
304
306 const float *input, size_t input_elements, size_t input_stride,
307 const float *weight, size_t weight_elements,
308 const float *bias, size_t bias_elements,
309 float *output, size_t output_elements, size_t output_stride,
310 float *scratch, size_t scratch_elements,
311 size_t input_channels, size_t output_channels, size_t input_frames,
312 size_t kernel_size, size_t stride, size_t padding, size_t output_frames) {
313#if CK_AUDIO_CONV_X86_TARGET_FMA
316 return ck_audio_conv1d_checked_execute(input, input_elements, input_stride,
317 weight, weight_elements, bias, bias_elements, output, output_elements,
318 output_stride, scratch, scratch_elements, input_channels,
319 output_channels, input_frames, kernel_size, stride, padding, 1,
320 output_frames, audio_conv1d_compute_avx2, NULL);
321#else
322 (void)input; (void)input_elements; (void)input_stride;
323 (void)weight; (void)weight_elements; (void)bias; (void)bias_elements;
324 (void)output; (void)output_elements; (void)output_stride;
325 (void)scratch; (void)scratch_elements; (void)input_channels;
326 (void)output_channels; (void)input_frames; (void)kernel_size;
327 (void)stride; (void)padding; (void)output_frames;
329#endif
330}
331
333 const float *input, size_t input_elements, size_t input_stride,
334 const float *weight, size_t weight_elements,
335 const float *bias, size_t bias_elements,
336 float *output, size_t output_elements, size_t output_stride,
337 float *scratch, size_t scratch_elements,
338 size_t input_channels, size_t output_channels, size_t input_frames,
339 size_t kernel_size, size_t stride, size_t padding, size_t dilation,
340 size_t output_frames) {
341#if CK_AUDIO_CONV_X86_TARGET_FMA
344 return ck_audio_conv1d_checked_execute(input, input_elements, input_stride,
345 weight, weight_elements, bias, bias_elements, output, output_elements,
346 output_stride, scratch, scratch_elements, input_channels,
347 output_channels, input_frames, kernel_size, stride, padding, dilation,
348 output_frames, audio_conv1d_compute_avx2, NULL);
349#else
350 (void)input; (void)input_elements; (void)input_stride;
351 (void)weight; (void)weight_elements; (void)bias; (void)bias_elements;
352 (void)output; (void)output_elements; (void)output_stride;
353 (void)scratch; (void)scratch_elements; (void)input_channels;
354 (void)output_channels; (void)input_frames; (void)kernel_size;
355 (void)stride; (void)padding; (void)dilation; (void)output_frames;
357#endif
358}
int audio_conv1d_checked_channel_major_f32_hwfma(const float *input, size_t input_elements, size_t input_stride, const float *weight, size_t weight_elements, const float *bias, size_t bias_elements, float *output, size_t output_elements, size_t output_stride, float *scratch, size_t scratch_elements, size_t input_channels, size_t output_channels, size_t input_frames, size_t kernel_size, size_t stride, size_t padding, size_t output_frames)
int audio_conv1d_checked_avx2_fma_available(void)
int audio_conv1d_dilated_checked_channel_major_f32_hwfma(const float *input, size_t input_elements, size_t input_stride, const float *weight, size_t weight_elements, const float *bias, size_t bias_elements, float *output, size_t output_elements, size_t output_stride, float *scratch, size_t scratch_elements, size_t input_channels, size_t output_channels, size_t input_frames, size_t kernel_size, size_t stride, size_t padding, size_t dilation, size_t output_frames)
#define CK_AUDIO_CONV1D_COMPUTE_BODY
int audio_conv1d_dilated_checked_channel_major_f32(const float *input, size_t input_elements, size_t input_stride, const float *weight, size_t weight_elements, const float *bias, size_t bias_elements, float *output, size_t output_elements, size_t output_stride, float *scratch, size_t scratch_elements, size_t input_channels, size_t output_channels, size_t input_frames, size_t kernel_size, size_t stride, size_t padding, size_t dilation, size_t output_frames)
int audio_conv1d_dilated_checked_channel_major_f32_avx2_fma(const float *input, size_t input_elements, size_t input_stride, const float *weight, size_t weight_elements, const float *bias, size_t bias_elements, float *output, size_t output_elements, size_t output_stride, float *scratch, size_t scratch_elements, size_t input_channels, size_t output_channels, size_t input_frames, size_t kernel_size, size_t stride, size_t padding, size_t dilation, size_t output_frames)
int ck_audio_conv1d_checked_execute(const float *input, size_t input_elements, size_t input_stride, const float *weight, size_t weight_elements, const float *bias, size_t bias_elements, float *output, size_t output_elements, size_t output_stride, float *scratch, size_t scratch_elements, size_t input_channels, size_t output_channels, size_t input_frames, size_t kernel_size, size_t stride, size_t padding, size_t dilation, size_t output_frames, ck_audio_conv1d_compute_fn compute, void *compute_context)
int audio_conv1d_checked_hardware_fma_available(void)
static void audio_conv1d_compute_scalar(const ck_audio_conv1d_job *job, void *unused)
int audio_conv1d_checked_channel_major_f32_avx2_fma(const float *input, size_t input_elements, size_t input_stride, const float *weight, size_t weight_elements, const float *bias, size_t bias_elements, float *output, size_t output_elements, size_t output_stride, float *scratch, size_t scratch_elements, size_t input_channels, size_t output_channels, size_t input_frames, size_t kernel_size, size_t stride, size_t padding, size_t output_frames)
int audio_conv1d_checked_workspace(size_t input_channels, size_t output_channels, size_t input_frames, size_t output_frames, size_t *scratch_elements)
int audio_conv1d_checked_channel_major_f32(const float *input, size_t input_elements, size_t input_stride, const float *weight, size_t weight_elements, const float *bias, size_t bias_elements, float *output, size_t output_elements, size_t output_stride, float *scratch, size_t scratch_elements, size_t input_channels, size_t output_channels, size_t input_frames, size_t kernel_size, size_t stride, size_t padding, size_t output_frames)
void audio_conv1d_compute_avx2(const ck_audio_conv1d_job *job, void *unused)
void(* ck_audio_conv1d_compute_fn)(const ck_audio_conv1d_job *, void *)
static int ck_checked_finite(const float *ptr, size_t n)
static int ck_checked_span(size_t rows, size_t width, size_t stride, size_t *span)
static int ck_checked_region(const float *ptr, size_t n)
static int ck_checked_overlap(const float *a, size_t na, const float *b, size_t nb)
@ CK_AUDIO_CONV_CHECKED_OVERFLOW
@ CK_AUDIO_CONV_CHECKED_OK
@ CK_AUDIO_CONV_CHECKED_UNSUPPORTED
@ CK_AUDIO_CONV_CHECKED_CAPACITY
@ CK_AUDIO_CONV_CHECKED_NONFINITE
@ CK_AUDIO_CONV_CHECKED_INVALID
__attribute__((visibility("default"))) CKTokenizer *ck_tokenizer_create(CKTokenizerType type)