Coverage Report

Created: 2019-07-03 22:50

/home/liu/buildslave/linux-x64-runtests/build/lib/nnc/cmd/blas/ccv_nnc_gemm_cpu_opt.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
7
#include "_ccv_nnc_gemm_cpu_opt.h"
8
9
FIND_FILE(cpu_opt/_ccv_nnc_gemm_cpu_opt.c, cpu_sys/_ccv_nnc_gemm_cpu_sys.c)
10
11
enum {
12
  CCV_NNC_CMD_OPT_GEMM_ALGO_DIRECT, // Direct multiplication
13
  CCV_NNC_CMD_OPT_GEMM_ALGO_SYSTEM, // Use system GEMM
14
  CCV_NNC_CMD_OPT_GEMM_ALGO_COUNT
15
};
16
17
static int _ccv_nnc_gemm_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)
18
5.28k
{
19
5.28k
  assert(input_size >= 2);
20
5.28k
  const ccv_nnc_tensor_view_t* w = (const ccv_nnc_tensor_view_t*)inputs[1];
21
5.28k
  const ccv_nnc_tensor_view_t* bias = input_size > 2 ? (const ccv_nnc_tensor_view_t*)inputs[2] : 
00
;
22
5.28k
  // Copy the most of parameters, but reshape the dimension of a to a vector.
23
5.28k
  const ccv_nnc_tensor_view_t* a = (const ccv_nnc_tensor_view_t*)inputs[0];
24
5.28k
  assert(a->info.dim[2] == 0); // It is a 2-d array.
25
5.28k
  assert(output_size == 1);
26
5.28k
  ccv_nnc_tensor_view_t* b = (ccv_nnc_tensor_view_t*)outputs[0];
27
5.28k
  assert(b->info.dim[2] == 0); // It is a 2-d array.
28
5.28k
  assert(w->info.dim[2] == 0); // It is a 2-d array
29
5.28k
  assert(!bias || bias->info.dim[1] == 0); // It is a 1-d array
30
5.28k
  const int a_nd = ccv_nnc_tensor_nd(a->info.dim);
31
5.28k
  assert(a_nd == 1 || a_nd == 2);
32
5.28k
  const int* adim = (a_nd == 1) ? 
a->info.dim97
:
a->info.dim + 15.18k
;
33
5.28k
  const int b_nd = ccv_nnc_tensor_nd(b->info.dim);
34
5.28k
  assert(b_nd == 1 || b_nd == 2);
35
5.28k
  const int* bdim = (b_nd == 1) ? 
b->info.dim97
:
b->info.dim + 15.18k
;
36
5.28k
  const int batch_size = a_nd == 1 ? 
197
:
ccv_max5.18k
(1, a->info.dim[0]);
37
5.28k
  assert(batch_size == (b_nd == 1) ? 1 : ccv_max(1, b->info.dim[0]));
38
5.28k
  assert(!bias || bdim[0] == bias->info.dim[0]);
39
5.28k
  assert(bdim[0] == w->info.dim[0]);
40
5.28k
  assert(adim[0] == w->info.dim[1]);
41
5.28k
  switch (cmd.algorithm)
42
5.28k
  {
43
5.28k
    case CCV_NNC_CMD_OPT_GEMM_ALGO_DIRECT:
44
105
      return _ccv_nnc_gemm_forw_cpu_opt(a, w, bias, b);
45
5.28k
    case CCV_NNC_CMD_OPT_GEMM_ALGO_SYSTEM:
46
5.17k
      if (!CCV_IS_TENSOR_VIEW(a) && !CCV_IS_TENSOR_VIEW(w) && (!bias || !CCV_IS_TENSOR_VIEW(bias)) && !CCV_IS_TENSOR_VIEW(b))
47
5.17k
        return _ccv_nnc_gemm_forw_cpu_sys(a, w, bias, b);
48
0
      return CCV_NNC_EXEC_INVALID;
49
0
    case -1:
50
0
      // Pass-through
51
0
      break;
52
0
  }
53
0
#if (defined HAVE_CBLAS || defined HAVE_ACCELERATE_FRAMEWORK)
54
0
  if (!CCV_IS_TENSOR_VIEW(a) && !CCV_IS_TENSOR_VIEW(w) && (!bias || !CCV_IS_TENSOR_VIEW(bias)) && !CCV_IS_TENSOR_VIEW(b))
55
0
    return _ccv_nnc_gemm_forw_cpu_sys(a, w, bias, b);
56
0
#endif
57
0
  return _ccv_nnc_gemm_forw_cpu_opt(a, w, bias, b);
58
0
}
59
60
static int _ccv_nnc_gemm_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)
61
5.24k
{
62
5.24k
  // inputs: gradient, forw prop input, [w]
63
5.24k
  // outputs: [output gradient], weight updates, bias updates
64
5.24k
  assert(input_size >= 2 && output_size >= 2);
65
5.24k
  const ccv_nnc_tensor_view_t* g = (const ccv_nnc_tensor_view_t*)inputs[0];
66
5.24k
  assert(g->info.dim[2] == 0); // It is a 2-d array.
67
5.24k
  const ccv_nnc_tensor_view_t* a = (const ccv_nnc_tensor_view_t*)inputs[1];
68
5.24k
  assert(a->info.dim[2] == 0); // It is a 2-d array.
69
5.24k
  ccv_nnc_tensor_view_t* dw = (ccv_nnc_tensor_view_t*)outputs[1];
70
5.24k
  assert(dw->info.dim[2] == 0); // It is a 2-d array.
71
5.24k
  ccv_nnc_tensor_view_t* bias = output_size > 2 ? (ccv_nnc_tensor_view_t*)outputs[2] : 
00
;
72
5.24k
  assert(!bias || bias->info.dim[1] == 0); // It is a 1-d array.
73
5.24k
  const int a_nd = ccv_nnc_tensor_nd(a->info.dim);
74
5.24k
  assert(a_nd == 1 || a_nd == 2);
75
5.24k
  const int* adim = (a_nd == 1) ? 
a->info.dim0
: a->info.dim + 1;
76
5.24k
  const int g_nd = ccv_nnc_tensor_nd(g->info.dim);
77
5.24k
  assert(g_nd == 1 || g_nd == 2);
78
5.24k
  const int* gdim = (g_nd == 1) ? 
g->info.dim0
: g->info.dim + 1;
79
5.24k
  const int batch_size = a_nd == 1 ? 
10
: ccv_max(1, a->info.dim[0]);
80
5.24k
  assert(batch_size == (g_nd == 1) ? 1 : ccv_max(1, g->info.dim[0]));
81
5.24k
  assert(!bias || bias->info.dim[0] == gdim[0]);
82
5.24k
  assert(gdim[0] == dw->info.dim[0]);
83
5.24k
  assert(adim[0] == dw->info.dim[1]);
84
5.24k
  const ccv_nnc_tensor_view_t* w = (input_size > 2) ? (const ccv_nnc_tensor_view_t*)inputs[2] : 
00
;
85
5.24k
  ccv_nnc_tensor_view_t* h = (ccv_nnc_tensor_view_t*)outputs[0];
86
5.24k
  if (h)
87
5.24k
  {
88
5.24k
    assert(h->info.dim[2] == 0); // It is a 2-d array.
89
5.24k
    const int h_nd = ccv_nnc_tensor_nd(h->info.dim);
90
5.24k
    assert(h_nd == 1 || h_nd == 2);
91
5.24k
    const int* hdim = (h_nd == 1) ? 
h->info.dim0
: h->info.dim + 1;
92
5.24k
    assert(hdim[0] == adim[0]);
93
5.24k
  }
94
5.24k
  if (w)
95
5.24k
  {
96
5.24k
    assert(w->info.dim[2] == 0); // It is a 2-d array.
97
5.24k
    assert(w->info.dim[0] == dw->info.dim[0]);
98
5.24k
    assert(w->info.dim[1] == dw->info.dim[1]);
99
5.24k
  }
100
5.24k
  switch (cmd.algorithm)
101
5.24k
  {
102
5.24k
    case CCV_NNC_CMD_OPT_GEMM_ALGO_DIRECT:
103
36
      return _ccv_nnc_gemm_back_cpu_opt(g, a, w, dw, bias, h, flags);
104
5.24k
    case CCV_NNC_CMD_OPT_GEMM_ALGO_SYSTEM:
105
5.21k
      if (!CCV_IS_TENSOR_VIEW(g) && !CCV_IS_TENSOR_VIEW(a) && !CCV_IS_TENSOR_VIEW(dw) && (!bias || !CCV_IS_TENSOR_VIEW(bias)) &&
106
5.21k
        (!w || !CCV_IS_TENSOR_VIEW(w)) && (!h || !CCV_IS_TENSOR_VIEW(h)))
107
5.21k
        return _ccv_nnc_gemm_back_cpu_sys(g, a, w, dw, bias, h, flags);
108
0
      return CCV_NNC_EXEC_INVALID;
109
0
    case -1:
110
0
      // Pass-through
111
0
      break;
112
0
  }
113
0
#if (defined HAVE_CBLAS || defined HAVE_ACCELERATE_FRAMEWORK)
114
0
  if (!CCV_IS_TENSOR_VIEW(g) && !CCV_IS_TENSOR_VIEW(a) && !CCV_IS_TENSOR_VIEW(dw) && (!bias || !CCV_IS_TENSOR_VIEW(bias)) &&
115
0
    (!w || !CCV_IS_TENSOR_VIEW(w)) && (!h || !CCV_IS_TENSOR_VIEW(h)))
116
0
    return _ccv_nnc_gemm_back_cpu_sys(g, a, w, dw, bias, h, flags);
117
0
#endif
118
0
  return _ccv_nnc_gemm_back_cpu_opt(g, a, w, dw, bias, h, flags);
119
0
}
120
121
REGISTER_COMMAND_BACKEND(CCV_NNC_GEMM_FORWARD, CCV_NNC_BACKEND_CPU_OPT)(ccv_nnc_cmd_backend_registry_t* const registry)
122
1
{
123
1
  registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW;
124
1
  registry->tensor_datatypes = CCV_32F;
125
1
  registry->tensor_memory = CCV_TENSOR_CPU_MEMORY;
126
1
  registry->algorithms = CCV_NNC_CMD_OPT_GEMM_ALGO_COUNT;
127
1
  registry->exec = _ccv_nnc_gemm_forw;
128
1
}
129
130
REGISTER_COMMAND_BACKEND(CCV_NNC_GEMM_BACKWARD, CCV_NNC_BACKEND_CPU_OPT)(ccv_nnc_cmd_backend_registry_t* const registry)
131
1
{
132
1
  registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW;
133
1
  registry->tensor_datatypes = CCV_32F;
134
1
  registry->tensor_memory = CCV_TENSOR_CPU_MEMORY;
135
1
  registry->algorithms = CCV_NNC_CMD_OPT_GEMM_ALGO_COUNT;
136
1
  registry->exec = _ccv_nnc_gemm_back;
137
1
}