Coverage Report

Created: 2024-08-18 16:21

/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/cmd/reduce/ccv_nnc_argmax_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
// Shared methods.
14
#include "../_ccv_nnc_cpu_ref.h"
15
16
static int _ccv_nnc_argmax_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)
17
4
{
18
4
  assert(input_size == 1);
19
4
  ccv_nnc_tensor_t* const a = inputs[0];
20
4
  assert(CCV_IS_TENSOR_CONTIGUOUS(a));
21
4
  assert(output_size == 1);
22
4
  ccv_nnc_tensor_t* const b = outputs[0];
23
4
  assert(CCV_IS_TENSOR_CONTIGUOUS(b));
24
4
  const int axis = cmd.info.reduce.axis[0];
25
4
  assert(cmd.info.reduce.count == 1);
26
4
  assert(axis >= 0);
27
4
  const int a_nd = ccv_nnc_tensor_nd(a->info.dim);
28
4
  assert(axis < a_nd);
29
4
  const int b_nd = ccv_nnc_tensor_nd(b->info.dim);
30
4
  int i, j, k;
31
12
  for (i = axis; i < a_nd; 
i++8
)
32
8
    { assert(a->info.dim[i] == (b_nd - (a_nd - i) >= 0) ? b->info.dim[b_nd - (a_nd - i)] : 1); }
33
4
  assert(1 == (b_nd - (a_nd - axis) >= 0) ? b->info.dim[b_nd - (a_nd - axis)] : 1);
34
6
  
for (i = 0; 4
i < axis;
i++2
)
35
2
    { assert(a->info.dim[i] == (b_nd - (a_nd - i) >= 0) ? b->info.dim[b_nd - (a_nd - i)] : 1); }
36
4
  const int tensor_count = ccv_nnc_tensor_count(a->info);
37
4
  const int axis_dim = a->info.dim[axis];
38
4
  int dim_after_axis = 1;
39
8
  for (i = axis + 1; i < a_nd; 
i++4
)
40
4
    dim_after_axis *= a->info.dim[i];
41
4
  const int dim_before_axis = tensor_count / axis_dim / dim_after_axis;
42
4
  assert(ccv_nnc_tensor_count(b->info) == tensor_count / axis_dim);
43
4
  const float* const ap = a->data.f32;
44
4
  assert(b->info.datatype == CCV_32F || b->info.datatype == CCV_32S);
45
4
  if (b->info.datatype == CCV_32S)
46
4
  {
47
4
    int* const bp = b->data.i32;
48
18
    for (i = 0; i < dim_before_axis; 
i++14
)
49
14
    {
50
14
      const float* const ap0 = ap + i * dim_after_axis * axis_dim;
51
14
      int* const bp0 = bp + i * dim_after_axis;
52
172
      for (j = 0; j < dim_after_axis; 
j++158
)
53
158
      {
54
158
        float max = ap0[j];
55
158
        int idx = 0;
56
468
        for (k = 1; k < axis_dim; 
k++310
)
57
310
          if (ap0[j + k * dim_after_axis] > max)
58
128
            max = ap0[j + k * dim_after_axis], idx = k;
59
158
        bp0[j] = idx;
60
158
      }
61
14
    }
62
4
  } else {
63
0
    float* const bp = b->data.f32;
64
0
    for (i = 0; i < dim_before_axis; i++)
65
0
    {
66
0
      const float* const ap0 = ap + i * dim_after_axis * axis_dim;
67
0
      float* const bp0 = bp + i * dim_after_axis;
68
0
      for (j = 0; j < dim_after_axis; j++)
69
0
      {
70
0
        float max = ap0[j];
71
0
        int idx = 0;
72
0
        for (k = 1; k < axis_dim; k++)
73
0
          if (ap0[j + k * dim_after_axis] > max)
74
0
            max = ap0[j + k * dim_after_axis], idx = k;
75
0
        bp0[j] = idx;
76
0
      }
77
0
    }
78
0
  }
79
4
  return CCV_NNC_EXEC_SUCCESS;
80
4
}
81
82
static int _ccv_nnc_argmax_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)
83
0
{
84
0
  return CCV_NNC_EXEC_INVALID;
85
0
}
86
87
REGISTER_COMMAND_BACKEND(CCV_NNC_ARGMAX_FORWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry)
88
1
{
89
1
  registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN;
90
1
  registry->tensor_datatypes = CCV_32F | CCV_32S;
91
1
  registry->tensor_memory = CCV_TENSOR_CPU_MEMORY;
92
1
  registry->algorithms = 1;
93
1
  registry->exec = _ccv_nnc_argmax_forw;
94
1
}
95
96
REGISTER_COMMAND_BACKEND(CCV_NNC_ARGMAX_BACKWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry)
97
1
{
98
1
  registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN;
99
1
  registry->tensor_datatypes = CCV_32F | CCV_32S;
100
1
  registry->tensor_memory = CCV_TENSOR_CPU_MEMORY;
101
1
  registry->algorithms = 1;
102
1
  registry->exec = _ccv_nnc_argmax_back;
103
1
}