/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/cmd/leaky_relu/ccv_nnc_leaky_relu_cpu_ref.c
Line | Count | Source (jump to first uncovered line) |
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 | | #ifdef USE_OPENMP |
7 | | #include <omp.h> |
8 | | #endif |
9 | | #ifdef USE_DISPATCH |
10 | | #include <dispatch/dispatch.h> |
11 | | #endif |
12 | | |
13 | | static int _ccv_nnc_leaky_relu_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) |
14 | 4 | { |
15 | 4 | assert(input_size == 1); |
16 | 4 | const ccv_nnc_tensor_t* a = inputs[0]; |
17 | 4 | assert(CCV_IS_TENSOR_CONTIGUOUS(a)); |
18 | 4 | assert(output_size == 1); |
19 | 4 | ccv_nnc_tensor_t* b = outputs[0]; |
20 | 4 | assert(CCV_IS_TENSOR_CONTIGUOUS(b)); |
21 | 4 | int i, count = ccv_nnc_tensor_count(a->info); |
22 | 12 | for (i = 0; i < CCV_NNC_MAX_DIM_ALLOC && a->info.dim[i] > 0; i++8 ) |
23 | 8 | { |
24 | 8 | assert(a->info.dim[i] == b->info.dim[i]); |
25 | 8 | } |
26 | 4 | const float negative_slope = cmd.info.leaky_relu.negative_slope; |
27 | 4 | float* ap = a->data.f32; |
28 | 4 | float* bp = b->data.f32; |
29 | 2.40k | for (i = 0; i < count; i++2.40k ) |
30 | 2.40k | if (ap[i] >= 0) |
31 | 2.40k | bp[i] = ap[i]; |
32 | 0 | else |
33 | 0 | bp[i] = ap[i] * negative_slope; |
34 | 4 | return CCV_NNC_EXEC_SUCCESS; |
35 | 4 | } |
36 | | |
37 | | static int _ccv_nnc_leaky_relu_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) |
38 | 2 | { |
39 | 2 | assert(input_size == 3); |
40 | 2 | const ccv_nnc_tensor_t* g = inputs[0]; // gradient |
41 | 2 | assert(CCV_IS_TENSOR_CONTIGUOUS(g)); |
42 | 2 | const ccv_nnc_tensor_t* b = inputs[2]; |
43 | 2 | assert(CCV_IS_TENSOR_CONTIGUOUS(b)); |
44 | 2 | assert(output_size == 1); |
45 | 2 | ccv_nnc_tensor_t* h = outputs[0]; |
46 | 2 | assert(CCV_IS_TENSOR_CONTIGUOUS(h)); |
47 | 2 | int i, count = ccv_nnc_tensor_count(g->info); |
48 | 6 | for (i = 0; i < CCV_NNC_MAX_DIM_ALLOC && g->info.dim[i] > 0; i++4 ) |
49 | 4 | { |
50 | 4 | assert(b->info.dim[i] == g->info.dim[i]); |
51 | 4 | assert(g->info.dim[i] == h->info.dim[i]); |
52 | 4 | } |
53 | 2 | float* bp = b->data.f32; |
54 | 2 | float* gp = g->data.f32; |
55 | 2 | float* hp = h->data.f32; |
56 | 2 | const float negative_slope = cmd.info.leaky_relu.negative_slope; |
57 | 2.00k | for (i = 0; i < count; i++2.00k ) |
58 | 2.00k | hp[i] = (bp[i] >= 0) ? gp[i] : negative_slope * gp[i]0 ; |
59 | 2 | return CCV_NNC_EXEC_SUCCESS; |
60 | 2 | } |
61 | | |
62 | | REGISTER_COMMAND_BACKEND(CCV_NNC_LEAKY_RELU_FORWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry) |
63 | 1 | { |
64 | 1 | registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN; |
65 | 1 | registry->tensor_datatypes = CCV_32F; |
66 | 1 | registry->tensor_memory = CCV_TENSOR_CPU_MEMORY; |
67 | 1 | registry->algorithms = 1; |
68 | 1 | registry->exec = _ccv_nnc_leaky_relu_forw; |
69 | 1 | } |
70 | | |
71 | | REGISTER_COMMAND_BACKEND(CCV_NNC_LEAKY_RELU_BACKWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry) |
72 | 1 | { |
73 | 1 | registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN; |
74 | 1 | registry->tensor_datatypes = CCV_32F; |
75 | 1 | registry->tensor_memory = CCV_TENSOR_CPU_MEMORY; |
76 | 1 | registry->algorithms = 1; |
77 | 1 | registry->exec = _ccv_nnc_leaky_relu_back; |
78 | 1 | } |