| File: | nnc/cmd/causal_convolution/ccv_nnc_causal_convolution_cpu_ref.c |
| Warning: | line 28, column 46 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | #include "ccv.h" | |||
| 2 | #include "ccv_internal.h" | |||
| 3 | #include "nnc/ccv_nnc.h" | |||
| 4 | #include "nnc/ccv_nnc_easy.h" | |||
| 5 | #include "nnc/ccv_nnc_internal.h" | |||
| 6 | #include <math.h> | |||
| 7 | ||||
| 8 | static int _ccv_nnc_causal_convolution_forw(const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, ccv_nnc_tensor_t* const* const inputs, const int input_size, ccv_nnc_tensor_t* const* const outputs, const int output_size, ccv_nnc_stream_context_t* const stream_context) | |||
| 9 | { | |||
| 10 | assert(input_size == 3)((void) sizeof ((input_size == 3) ? 1 : 0), __extension__ ({ if (input_size == 3) ; else __assert_fail ("input_size == 3", "causal_convolution/ccv_nnc_causal_convolution_cpu_ref.c" , 10, __extension__ __PRETTY_FUNCTION__); })); | |||
| ||||
| 11 | assert(output_size == 2)((void) sizeof ((output_size == 2) ? 1 : 0), __extension__ ({ if (output_size == 2) ; else __assert_fail ("output_size == 2" , "causal_convolution/ccv_nnc_causal_convolution_cpu_ref.c", 11 , __extension__ __PRETTY_FUNCTION__); })); | |||
| 12 | const ccv_nnc_tensor_t* const x = inputs[0]; | |||
| 13 | const ccv_nnc_tensor_t* const previous = inputs[1]; | |||
| 14 | const ccv_nnc_tensor_t* const weight = inputs[2]; | |||
| 15 | ccv_nnc_tensor_t* const y = outputs[0]; | |||
| 16 | ccv_nnc_tensor_t* const next = outputs[1]; | |||
| 17 | int i; | |||
| 18 | for (i = 0; i < 3; i++) | |||
| 19 | assert(inputs[i]->info.datatype == CCV_32F && CCV_IS_TENSOR_CONTIGUOUS(inputs[i]))((void) sizeof ((inputs[i]->info.datatype == CCV_32F && (!((*(int*)(inputs[i])) & CCV_TENSOR_VIEW) || (((ccv_nnc_tensor_view_t *)inputs[i])->contiguous == 1))) ? 1 : 0), __extension__ ( { if (inputs[i]->info.datatype == CCV_32F && (!((* (int*)(inputs[i])) & CCV_TENSOR_VIEW) || (((ccv_nnc_tensor_view_t *)inputs[i])->contiguous == 1))) ; else __assert_fail ("inputs[i]->info.datatype == CCV_32F && CCV_IS_TENSOR_CONTIGUOUS(inputs[i])" , "causal_convolution/ccv_nnc_causal_convolution_cpu_ref.c", 19 , __extension__ __PRETTY_FUNCTION__); })); | |||
| 20 | for (i = 0; i < 2; i++) | |||
| 21 | assert(outputs[i]->info.datatype == CCV_32F && CCV_IS_TENSOR_CONTIGUOUS(outputs[i]))((void) sizeof ((outputs[i]->info.datatype == CCV_32F && (!((*(int*)(outputs[i])) & CCV_TENSOR_VIEW) || (((ccv_nnc_tensor_view_t *)outputs[i])->contiguous == 1))) ? 1 : 0), __extension__ ( { if (outputs[i]->info.datatype == CCV_32F && (!(( *(int*)(outputs[i])) & CCV_TENSOR_VIEW) || (((ccv_nnc_tensor_view_t *)outputs[i])->contiguous == 1))) ; else __assert_fail ("outputs[i]->info.datatype == CCV_32F && CCV_IS_TENSOR_CONTIGUOUS(outputs[i])" , "causal_convolution/ccv_nnc_causal_convolution_cpu_ref.c", 21 , __extension__ __PRETTY_FUNCTION__); })); | |||
| 22 | // Shapes only matter through their counts: C is x's last axis and the previous rows hold B batches. | |||
| 23 | const int channels = x->info.dim[ccv_nnc_tensor_nd(x->info.dim) - 1]; | |||
| 24 | const int kernel_size = ccv_nnc_tensor_count(weight->info) / channels; | |||
| 25 | // One tap has no previous rows to carry. | |||
| 26 | assert(kernel_size >= 2 && ccv_nnc_tensor_count(weight->info) == (size_t)kernel_size * channels)((void) sizeof ((kernel_size >= 2 && ccv_nnc_tensor_count (weight->info) == (size_t)kernel_size * channels) ? 1 : 0) , __extension__ ({ if (kernel_size >= 2 && ccv_nnc_tensor_count (weight->info) == (size_t)kernel_size * channels) ; else __assert_fail ("kernel_size >= 2 && ccv_nnc_tensor_count(weight->info) == (size_t)kernel_size * channels" , "causal_convolution/ccv_nnc_causal_convolution_cpu_ref.c", 26 , __extension__ __PRETTY_FUNCTION__); })); | |||
| 27 | const int B = ccv_nnc_tensor_count(previous->info) / ((size_t)(kernel_size - 1) * channels); | |||
| 28 | const int T = ccv_nnc_tensor_count(x->info) / ((size_t)B * channels); | |||
| ||||
| 29 | const int rows = ccv_nnc_tensor_count(next->info) / ((size_t)B * channels); | |||
| 30 | assert(ccv_nnc_tensor_count(y->info) == (size_t)B * T * channels)((void) sizeof ((ccv_nnc_tensor_count(y->info) == (size_t) B * T * channels) ? 1 : 0), __extension__ ({ if (ccv_nnc_tensor_count (y->info) == (size_t)B * T * channels) ; else __assert_fail ("ccv_nnc_tensor_count(y->info) == (size_t)B * T * channels" , "causal_convolution/ccv_nnc_causal_convolution_cpu_ref.c", 30 , __extension__ __PRETTY_FUNCTION__); })); | |||
| 31 | assert(rows <= kernel_size - 1 + T)((void) sizeof ((rows <= kernel_size - 1 + T) ? 1 : 0), __extension__ ({ if (rows <= kernel_size - 1 + T) ; else __assert_fail ( "rows <= kernel_size - 1 + T", "causal_convolution/ccv_nnc_causal_convolution_cpu_ref.c" , 31, __extension__ __PRETTY_FUNCTION__); })); | |||
| 32 | const int history = kernel_size - 1; | |||
| 33 | // Context row r of batch b is previous row r, then x row r - history. | |||
| 34 | #define CONTEXT(b, r, c) ((r) < history ? previous->data.f32[((size_t)(b) * history + (r)) * channels + (c)] : x->data.f32[((size_t)(b) * T + (r) - history) * channels + (c)]) | |||
| 35 | const int silu = cmd.info.causal_convolution.silu; | |||
| 36 | int b, t, c, j; | |||
| 37 | for (b = 0; b < B; b++) | |||
| 38 | for (c = 0; c < channels; c++) | |||
| 39 | { | |||
| 40 | const float* const w = weight->data.f32 + (size_t)c * kernel_size; | |||
| 41 | for (t = 0; t < T; t++) | |||
| 42 | { | |||
| 43 | float sum = 0; | |||
| 44 | for (j = 0; j < kernel_size; j++) | |||
| 45 | sum += w[j] * CONTEXT(b, t + j, c); | |||
| 46 | y->data.f32[((size_t)b * T + t) * channels + c] = silu ? sum / (1 + expf(-sum)) : sum; | |||
| 47 | } | |||
| 48 | // The next rows are the context's last rows. | |||
| 49 | const int first = history + T - rows; | |||
| 50 | for (j = 0; j < rows; j++) | |||
| 51 | next->data.f32[((size_t)b * rows + j) * channels + c] = CONTEXT(b, first + j, c); | |||
| 52 | } | |||
| 53 | #undef CONTEXT | |||
| 54 | return CCV_NNC_EXEC_SUCCESS; | |||
| 55 | } | |||
| 56 | ||||
| 57 | static int _ccv_nnc_causal_convolution_back(const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, ccv_nnc_tensor_t* const* const inputs, const int input_size, ccv_nnc_tensor_t* const* const outputs, const int output_size, ccv_nnc_stream_context_t* const stream_context) | |||
| 58 | { | |||
| 59 | return CCV_NNC_EXEC_INVALID; | |||
| 60 | } | |||
| 61 | ||||
| 62 | REGISTER_COMMAND_BACKEND(CCV_NNC_CAUSAL_CONVOLUTION_FORWARD, CCV_NNC_BACKEND_CPU_REF)void _register_command_CCV_NNC_CAUSAL_CONVOLUTION_FORWARD_backend_CCV_NNC_BACKEND_CPU_REF(ccv_nnc_cmd_backend_registry_t* const registry) | |||
| 63 | { | |||
| 64 | registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN; | |||
| 65 | registry->tensor_datatypes = CCV_32F; | |||
| 66 | registry->tensor_memory = CCV_TENSOR_CPU_MEMORY; | |||
| 67 | registry->algorithms = 1; | |||
| 68 | registry->exec = _ccv_nnc_causal_convolution_forw; | |||
| 69 | } | |||
| 70 | ||||
| 71 | REGISTER_COMMAND_BACKEND(CCV_NNC_CAUSAL_CONVOLUTION_BACKWARD, CCV_NNC_BACKEND_CPU_REF)void _register_command_CCV_NNC_CAUSAL_CONVOLUTION_BACKWARD_backend_CCV_NNC_BACKEND_CPU_REF(ccv_nnc_cmd_backend_registry_t* const registry) | |||
| 72 | { | |||
| 73 | registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN; | |||
| 74 | registry->tensor_datatypes = CCV_32F; | |||
| 75 | registry->tensor_memory = CCV_TENSOR_CPU_MEMORY; | |||
| 76 | registry->algorithms = 1; | |||
| 77 | registry->exec = _ccv_nnc_causal_convolution_back; | |||
| 78 | } |