Coverage Report

Created: 2017-11-12 13:27

/home/liu/buildslave/linux-x64-runtests/build/lib/nnc/cmd/blas/cpu_sys/_ccv_nnc_gemm_cpu_sys.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
#include "../_ccv_nnc_gemm_cpu_opt.h"
7
8
int _ccv_nnc_gemm_forw_cpu_sys(const ccv_nnc_tensor_view_t* const a, const ccv_nnc_tensor_view_t* const w, const ccv_nnc_tensor_view_t* const bias, ccv_nnc_tensor_view_t* const b)
9
24
{
10
24
#if (defined HAVE_CBLAS || defined HAVE_ACCELERATE_FRAMEWORK)
11
24
  assert(!CCV_IS_TENSOR_VIEW(a));
12
24
  assert(!CCV_IS_TENSOR_VIEW(b));
13
24
  assert(!CCV_IS_TENSOR_VIEW(w));
14
24
  assert(!CCV_IS_TENSOR_VIEW(bias));
15
24
  assert(a->info.dim[2] == 0); // It is a 2-d array.
16
24
  assert(b->info.dim[2] == 0); // It is a 2-d array.
17
24
  // Copy the most of parameters, but reshape the dimension of a to a vector.
18
24
  const int a_nd = ccv_nnc_tensor_nd(a->info.dim);
19
24
  const int* adim = (a_nd == 1) ? 
a->info.dim24
:
a->info.dim + 10
;
20
24
  const int b_nd = ccv_nnc_tensor_nd(b->info.dim);
21
24
  const int* bdim = (b_nd == 1) ? 
b->info.dim24
:
b->info.dim + 10
;
22
24
  const int batch_size = a_nd == 1 ? 
124
:
ccv_max0
(1, a->info.dim[0]);
23
24
  ccv_dense_matrix_t am = ccv_dense_matrix(batch_size, adim[0], CCV_32F | CCV_C1, a->data.u8, 0);
24
24
  int bias_count = ccv_nnc_tensor_count(bias->info);
25
24
  assert(bdim[0] == bias_count);
26
24
  assert(batch_size == (b_nd == 1) ? 1 : ccv_max(1, b->info.dim[0]));
27
24
  ccv_dense_matrix_t bm = ccv_dense_matrix(batch_size, bdim[0], CCV_32F | CCV_C1, b->data.u8, 0);
28
24
  ccv_dense_matrix_t* dbm = &bm;
29
24
  // copy bias into each row.
30
24
  int i;
31
48
  for (i = 0; 
i < batch_size48
;
i++24
)
32
24
    memcpy(bm.data.f32 + i * bdim[0], bias->data.f32, sizeof(float) * bdim[0]);
33
24
  assert(bdim[0] == w->info.dim[0]);
34
24
  assert(adim[0] == w->info.dim[1]);
35
24
  ccv_dense_matrix_t wm = ccv_dense_matrix(bdim[0], adim[0], CCV_32F | CCV_C1, w->data.u8, 0);
36
24
  ccv_gemm(&am, &wm, 1, dbm, 1, CCV_B_TRANSPOSE, (ccv_matrix_t**)&dbm, 0); // supply b as matrix C is allowed
37
24
  return CCV_NNC_EXEC_SUCCESS;
38
24
#else
39
  return CCV_NNC_EXEC_INVALID;
40
#endif
41
24
}
42
43
int _ccv_nnc_gemm_back_cpu_sys(const ccv_nnc_tensor_view_t* const g, const ccv_nnc_tensor_view_t* const a, const ccv_nnc_tensor_view_t* const w, ccv_nnc_tensor_view_t* const dw, ccv_nnc_tensor_view_t* const bias, ccv_nnc_tensor_view_t* const h, const int flags)
44
{
45
#if (defined HAVE_CBLAS || defined HAVE_ACCELERATE_FRAMEWORK)
46
  assert(!CCV_IS_TENSOR_VIEW(g));
47
  assert(!CCV_IS_TENSOR_VIEW(a));
48
  assert(!CCV_IS_TENSOR_VIEW(dw));
49
  assert(!CCV_IS_TENSOR_VIEW(bias));
50
  if (!(flags & CCV_NNC_ACCUMULATE_OUTPUT)) // reset the gradients to 0
51
  {
52
    memset(dw->data.u8, 0, sizeof(float) * ccv_nnc_tensor_count(w->info));
53
    memset(bias->data.u8, 0, sizeof(float) * ccv_nnc_tensor_count(bias->info));
54
  }
55
  assert(a->info.dim[2] == 0); // It is a 2-d array.
56
  assert(g->info.dim[2] == 0); // It is a 2-d array.
57
  const int a_nd = ccv_nnc_tensor_nd(a->info.dim);
58
  assert(a_nd == 1 || a_nd == 2);
59
  const int* adim = (a_nd == 1) ? a->info.dim : a->info.dim + 1;
60
  const int g_nd = ccv_nnc_tensor_nd(g->info.dim);
61
  assert(g_nd == 1 || g_nd == 2);
62
  const int* gdim = (g_nd == 1) ? g->info.dim : g->info.dim + 1;
63
  const int batch_size = a_nd == 1 ? 1 : ccv_max(1, a->info.dim[0]);
64
  assert(batch_size == (g_nd == 1) ? 1 : ccv_max(1, g->info.dim[0]));
65
  assert(bias->info.dim[0] == gdim[0]);
66
  ccv_dense_matrix_t gm = ccv_dense_matrix(batch_size, gdim[0], CCV_32F | CCV_C1, g->data.u8, 0);
67
  ccv_dense_matrix_t am = ccv_dense_matrix(batch_size, adim[0], CCV_32F | CCV_C1, a->data.u8, 0);
68
  int i, j;
69
  float* gp = g->data.f32;
70
  float* bp = bias->data.f32;
71
  for (i = 0; i < batch_size; i++)
72
  {
73
    for (j = 0; j < gdim[0]; j++)
74
      bp[j] += gp[j];
75
    gp += gdim[0];
76
  }
77
  assert(gdim[0] == w->info.dim[0]);
78
  assert(adim[0] == w->info.dim[1]);
79
  ccv_dense_matrix_t dwm = ccv_dense_matrix(gdim[0], adim[0], CCV_32F | CCV_C1, dw->data.u8, 0);
80
  ccv_dense_matrix_t* ddwm = &dwm;
81
  ccv_gemm(&gm, &am, 1, ddwm, 1, CCV_A_TRANSPOSE, (ccv_matrix_t**)&ddwm, 0);
82
  if (h && w)
83
  {
84
    assert(!CCV_IS_TENSOR_VIEW(h));
85
    assert(!CCV_IS_TENSOR_VIEW(w));
86
    assert(h->info.dim[2] == 0); // It is a 2-d array.
87
    assert(h->info.dim[0] == a->info.dim[0]);
88
    const int h_nd = ccv_nnc_tensor_nd(h->info.dim);
89
    assert(h_nd == 1 || h_nd == 2);
90
    const int* hdim = (h_nd == 1) ? h->info.dim : h->info.dim + 1;
91
    assert(hdim[0] == adim[0]);
92
    assert(batch_size == (h_nd == 1) ? 1 : ccv_max(1, h->info.dim[0]));
93
    ccv_dense_matrix_t wm = ccv_dense_matrix(gdim[0], hdim[0], CCV_32F | CCV_C1, w->data.u8, 0);
94
    ccv_dense_matrix_t hm = ccv_dense_matrix(batch_size, hdim[0], CCV_32F | CCV_C1, h->data.u8, 0);
95
    ccv_dense_matrix_t* dhm = &hm;
96
    ccv_gemm(&gm, &wm, 1, 0, 0, 0 /* No transpose */, (ccv_matrix_t**)&dhm, 0);
97
  }
98
  return CCV_NNC_EXEC_SUCCESS;
99
#else
100
  return CCV_NNC_EXEC_INVALID;
101
#endif
102
}