Coverage Report

Created: 2024-08-19 11:27

/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
}