Coverage Report

Created: 2024-12-10 23:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/cmd/reduce/ccv_nnc_reduce_mean_cpu_ref.c
Line
Count
Source
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
// Shared methods.
14
#include "../_ccv_nnc_cpu_ref.h"
15
16
void _ccv_nnc_reduce_mean_forw_cpu_ref(ccv_nnc_tensor_view_t* const a, ccv_nnc_tensor_view_t* const b)
17
5
{
18
5
  assert(ccv_nnc_tensor_nd(a->info.dim) <= CCV_NNC_MAX_DIM + 2);
19
5
  assert(ccv_nnc_tensor_nd(b->info.dim) <= CCV_NNC_MAX_DIM + 2);
20
  // Assuming this is float 32.
21
5
  int adim[CCV_NNC_MAX_DIM_ALLOC];
22
5
  int bdim[CCV_NNC_MAX_DIM_ALLOC];
23
5
  ccv_nnc_tensor_view_get_dim(a, adim);
24
5
  ccv_nnc_tensor_view_get_dim(b, bdim);
25
5
  assert(ccv_nnc_tensor_view_check_broadcast_dim(b, adim));
26
5
  int astride[CCV_NNC_MAX_DIM_ALLOC];
27
5
  int bstride[CCV_NNC_MAX_DIM_ALLOC];
28
5
  assert(CCV_NNC_MAX_DIM == 2); // Need to change this logic for CCV_NNC_MAX_DIM == other number.
29
5
  ccv_nnc_tensor_view_get_stride(a, astride);
30
5
  ccv_nnc_tensor_view_get_stride(b, bstride);
31
5
  int i[CCV_NNC_MAX_DIM + 2];
32
5
  int x;
33
5
  ccv_nnc_tensor_zero(b);
34
5
  float* const ap = a->data.f32;
35
5
  float* const bp = b->data.f32;
36
5
  const float scale = (float)ccv_nnc_tensor_count(b->info) / (float)ccv_nnc_tensor_count(a->info);
37
  // Non-optimal case, need to do skip if needed.
38
10
  for (i[0] = 0; i[0] < adim[0]; 
i[0]++5
)
39
5
  {
40
5
    float* const ap0 = ap + i[0] * astride[0];
41
5
    float* const bp0 = bdim[0] == 1 ? bp : 
bp + i[0] * bstride[0]0
;
42
10
    for (i[1] = 0; i[1] < adim[1]; 
i[1]++5
)
43
5
    {
44
5
      float* ap1 = ap0 + i[1] * astride[1];
45
5
      float* const bp1 = bdim[1] == 1 ? bp0 : 
bp0 + i[1] * bstride[1]0
;
46
19
      for (i[2] = 0; i[2] < adim[2]; 
i[2]++14
)
47
14
      {
48
14
        float* const bp2 = bdim[2] == 1 ? 
bp14
:
bp1 + i[2] * bstride[2]10
;
49
14
        if (bdim[3] == 1)
50
28
          
for (x = 0; 10
x < adim[3];
x++18
)
51
18
            bp2[0] += ap1[x] * scale;
52
4
        else
53
16
          
for (x = 0; 4
x < adim[3];
x++12
)
54
12
            bp2[x] += ap1[x] * scale;
55
14
        ap1 += astride[2];
56
14
      }
57
5
    }
58
5
  }
59
5
}
60
61
static int _ccv_nnc_reduce_mean_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)
62
5
{
63
5
  assert(input_size == 1);
64
5
  ccv_nnc_tensor_view_t* const a = (ccv_nnc_tensor_view_t*)inputs[0];
65
5
  ccv_nnc_tensor_view_t* const b = (ccv_nnc_tensor_view_t*)outputs[0];
66
5
  _ccv_nnc_reduce_mean_forw_cpu_ref(a, b);
67
5
  return CCV_NNC_EXEC_SUCCESS;
68
5
}
69
70
static int _ccv_nnc_reduce_mean_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)
71
1
{
72
1
  if (inputs[0] == 0)
73
0
  {
74
0
    int i;
75
0
    ssize_t dims = 1;
76
0
    for (i = 0; i < cmd.info.reduce.count; i++)
77
0
      dims *= outputs[0]->info.dim[cmd.info.reduce.axis[i]];
78
0
    const float scale = 1.0 / (float)dims;
79
0
    _ccv_nnc_tensor_set_cpu_ref_f32((ccv_nnc_tensor_view_t*)outputs[0], scale);
80
0
    return CCV_NNC_EXEC_SUCCESS;
81
0
  }
82
1
  ccv_nnc_tensor_view_t* const a = (ccv_nnc_tensor_view_t*)outputs[0];
83
1
  ccv_nnc_tensor_view_t* const b = (ccv_nnc_tensor_view_t*)inputs[0];
84
1
  assert(ccv_nnc_tensor_nd(a->info.dim) <= CCV_NNC_MAX_DIM + 2);
85
1
  assert(ccv_nnc_tensor_nd(b->info.dim) <= CCV_NNC_MAX_DIM + 2);
86
  // Assuming this is float 32.
87
1
  int adim[CCV_NNC_MAX_DIM_ALLOC];
88
1
  int bdim[CCV_NNC_MAX_DIM_ALLOC];
89
1
  ccv_nnc_tensor_view_get_dim(a, adim);
90
1
  ccv_nnc_tensor_view_get_dim(b, bdim);
91
1
  int astride[CCV_NNC_MAX_DIM_ALLOC];
92
1
  int bstride[CCV_NNC_MAX_DIM_ALLOC];
93
1
  assert(CCV_NNC_MAX_DIM == 2); // Need to change this logic for CCV_NNC_MAX_DIM == other number.
94
1
  ccv_nnc_tensor_view_get_stride(a, astride);
95
1
  ccv_nnc_tensor_view_get_stride(b, bstride);
96
1
  int i[CCV_NNC_MAX_DIM + 2];
97
1
  int x;
98
1
  float* const ap = a->data.f32;
99
1
  float* const bp = b->data.f32;
100
1
  const float scale = (float)ccv_nnc_tensor_count(b->info) / (float)ccv_nnc_tensor_count(a->info);
101
  // Non-optimal case, need to do skip if needed.
102
2
  for (i[0] = 0; i[0] < adim[0]; 
i[0]++1
)
103
1
  {
104
1
    float* const ap0 = ap + i[0] * astride[0];
105
1
    float* const bp0 = bdim[0] == 1 ? bp : 
bp + i[0] * bstride[0]0
;
106
2
    for (i[1] = 0; i[1] < adim[1]; 
i[1]++1
)
107
1
    {
108
1
      float* ap1 = ap0 + i[1] * astride[1];
109
1
      float* const bp1 = bdim[1] == 1 ? bp0 : 
bp0 + i[1] * bstride[1]0
;
110
3
      for (i[2] = 0; i[2] < adim[2]; 
i[2]++2
)
111
2
      {
112
2
        float* const bp2 = bdim[2] == 1 ? bp1 : 
bp1 + i[2] * bstride[2]0
;
113
2
        if (bdim[3] == 1)
114
0
          for (x = 0; x < adim[3]; x++)
115
0
            ap1[x] = bp2[0] * scale;
116
2
        else
117
8
          
for (x = 0; 2
x < adim[3];
x++6
)
118
6
            ap1[x] = bp2[x] * scale;
119
2
        ap1 += astride[2];
120
2
      }
121
1
    }
122
1
  }
123
1
  return CCV_NNC_EXEC_SUCCESS;
124
1
}
125
126
REGISTER_COMMAND_BACKEND(CCV_NNC_REDUCE_MEAN_FORWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry)
127
1
{
128
1
  registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN;
129
1
  registry->tensor_datatypes = CCV_32F;
130
1
  registry->tensor_memory = CCV_TENSOR_CPU_MEMORY;
131
1
  registry->algorithms = 1;
132
1
  registry->exec = _ccv_nnc_reduce_mean_forw;
133
1
}
134
135
REGISTER_COMMAND_BACKEND(CCV_NNC_REDUCE_MEAN_BACKWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry)
136
1
{
137
1
  registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN;
138
1
  registry->tensor_datatypes = CCV_32F;
139
1
  registry->tensor_memory = CCV_TENSOR_CPU_MEMORY;
140
1
  registry->algorithms = 1;
141
1
  registry->exec = _ccv_nnc_reduce_mean_back;
142
1
}