Coverage Report

Created: 2017-11-12 13:27

/home/liu/buildslave/linux-x64-runtests/build/test/int/nnc/symbolic.graph.vgg.d.tests.c
Line
Count
Source (jump to first uncovered line)
1
#include "case.h"
2
#include "ccv_case.h"
3
#include <ccv.h>
4
#include <nnc/ccv_nnc.h>
5
#include <nnc/ccv_nnc_easy.h>
6
#include <inc/ccv_convnet_internal.h>
7
8
TEST_SETUP()
9
{
10
  ccv_nnc_init();
11
}
12
13
static ccv_nnc_symbolic_graph_t* ccv_nnc_simple_symbolic_graph(ccv_convnet_t* convnet, ccv_nnc_tensor_t* input, ccv_nnc_tensor_t* output, ccv_nnc_graph_exec_symbol_t* source_symbol, ccv_nnc_graph_exec_symbol_t* dest_symbol, ccv_nnc_tensor_symbol_t* input_symbol_ref, ccv_nnc_tensor_symbol_t* output_symbol_ref, ccv_nnc_tensor_symbol_t* w_symbols, ccv_nnc_tensor_symbol_t* bias_symbols)
14
1
{
15
1
  int i;
16
1
  // We only create the graph compute to the last fc layer.
17
1
  ccv_nnc_symbolic_graph_t* symbolic_vgg = ccv_nnc_symbolic_graph_new();
18
1
  ccv_nnc_tensor_symbol_t input_symbol = ccv_nnc_tensor_symbol_new(symbolic_vgg, input->info, 0);
19
1
  *input_symbol_ref = input_symbol;
20
1
  ccv_nnc_tensor_symbol_t output_symbol = ccv_nnc_tensor_symbol_new(symbolic_vgg, output->info, 0);
21
1
  *output_symbol_ref = output_symbol;
22
1
  ccv_nnc_graph_exec_symbol_t previous_exec_symbol;
23
22
  for (i = 0; 
i < convnet->count22
;
i++21
)
24
21
  {
25
21
    ccv_convnet_layer_t* layer = convnet->layers + i;
26
21
    int rows, cols, partition;
27
21
    ccv_convnet_make_output(layer, layer->input.matrix.rows, layer->input.matrix.cols, &rows, &cols, &partition);
28
21
    ccv_nnc_tensor_symbol_t tensor_symbol = output_symbol;
29
21
    if (i < convnet->count - 1)
30
20
    {
31
20
      if (layer->type == CCV_CONVNET_FULL_CONNECT)
32
2
        
tensor_symbol = ccv_nnc_tensor_symbol_new(symbolic_vgg, 2
ONE_CPU_TENSOR2
(rows * cols * partition), 0);
33
20
      else
34
18
        
tensor_symbol = ccv_nnc_tensor_symbol_new(symbolic_vgg, 18
ONE_CPU_TENSOR18
(rows, cols, (layer->type == CCV_CONVNET_CONVOLUTIONAL ? layer->net.convolutional.count : layer->input.matrix.channels)), 0);
35
20
    }
36
21
    ccv_nnc_graph_exec_symbol_t exec_symbol = {0};
37
21
    if (layer->type == CCV_CONVNET_CONVOLUTIONAL)
38
13
    {
39
13
      ccv_nnc_tensor_symbol_t w_symbol = ccv_nnc_tensor_symbol_new(symbolic_vgg, ONE_CPU_TENSOR(layer->net.convolutional.count, layer->net.convolutional.rows, layer->net.convolutional.cols, layer->net.convolutional.channels), 0);
40
13
      w_symbols[i] = w_symbol;
41
13
      ccv_nnc_tensor_symbol_t bias_symbol = ccv_nnc_tensor_symbol_new(symbolic_vgg, ONE_CPU_TENSOR(layer->net.convolutional.count), 0);
42
13
      bias_symbols[i] = bias_symbol;
43
13
      ccv_nnc_cmd_t cmd = CMD_CONVOLUTION_FORWARD(layer->net.convolutional.count, layer->net.convolutional.rows, layer->net.convolutional.cols, layer->net.convolutional.channels);
44
13
      exec_symbol = ccv_nnc_graph_exec_symbol_new(symbolic_vgg, cmd, 
TENSOR_SYMBOL_LIST13
(input_symbol, w_symbol, bias_symbol),
TENSOR_SYMBOL_LIST13
(tensor_symbol), 0);
45
8
    } else 
if (8
layer->type == CCV_CONVNET_MAX_POOL8
)
{5
46
5
      ccv_nnc_cmd_t cmd = ccv_nnc_cmd(CCV_NNC_MAX_POOL_FORWARD, 0, CMD_GENERIC(layer->net.pool.size, layer->net.pool.size, layer->input.matrix.channels), 0);
47
5
      exec_symbol = ccv_nnc_graph_exec_symbol_new(symbolic_vgg, cmd, 
TENSOR_SYMBOL_LIST5
(input_symbol),
TENSOR_SYMBOL_LIST5
(tensor_symbol), 0);
48
3
    } else 
if (3
layer->type == CCV_CONVNET_FULL_CONNECT3
)
{3
49
3
      ccv_nnc_tensor_symbol_t w_symbol = ccv_nnc_tensor_symbol_new(symbolic_vgg, ONE_CPU_TENSOR(layer->net.full_connect.count, layer->input.node.count), 0);
50
3
      w_symbols[i] = w_symbol;
51
3
      ccv_nnc_tensor_symbol_t bias_symbol = ccv_nnc_tensor_symbol_new(symbolic_vgg, ONE_CPU_TENSOR(layer->net.full_connect.count), 0);
52
3
      bias_symbols[i] = bias_symbol;
53
3
      ccv_nnc_cmd_t cmd = ccv_nnc_cmd(CCV_NNC_GEMM_FORWARD, 0, CMD_GEMM(layer->net.full_connect.count), 0);
54
3
      // If the input is not what I expected (array), reshape it.
55
3
      if (input_symbol.info.dim[0] != ccv_nnc_tensor_count(input_symbol.info))
56
1
        
input_symbol = ccv_nnc_tensor_symbol_alias_new(symbolic_vgg, input_symbol, ccv_nnc_no_ofs, 1
ONE_CPU_TENSOR1
(ccv_nnc_tensor_count(input_symbol.info)).dim,
ONE_CPU_TENSOR1
(ccv_nnc_tensor_count(input_symbol.info)), 0);
57
3
      exec_symbol = ccv_nnc_graph_exec_symbol_new(symbolic_vgg, cmd, 
TENSOR_SYMBOL_LIST3
(input_symbol, w_symbol, bias_symbol),
TENSOR_SYMBOL_LIST3
(tensor_symbol), 0);
58
0
    } else {
59
0
      assert("unreachable");
60
0
    }
61
21
    if (i != 0)
62
20
      ccv_nnc_graph_exec_symbol_concat(symbolic_vgg, previous_exec_symbol, exec_symbol);
63
21
    previous_exec_symbol = exec_symbol;
64
21
    if (i == 0)
65
1
      *source_symbol = exec_symbol;
66
21
    if (i < convnet->count - 1 &&
67
20
      
(layer->type == CCV_CONVNET_CONVOLUTIONAL || 20
layer->type == CCV_CONVNET_FULL_CONNECT7
))
68
15
    {
69
15
      // Create the ReLU layer.
70
15
      ccv_nnc_cmd_t cmd = ccv_nnc_cmd(CCV_NNC_RELU_FORWARD, 0, CMD_GENERIC(), 0);
71
15
      ccv_nnc_tensor_symbol_t next_symbol = ccv_nnc_tensor_symbol_new(symbolic_vgg, tensor_symbol.info, 0);
72
15
      exec_symbol = ccv_nnc_graph_exec_symbol_new(symbolic_vgg, cmd, 
TENSOR_SYMBOL_LIST15
(tensor_symbol),
TENSOR_SYMBOL_LIST15
(next_symbol), 0);
73
15
      ccv_nnc_graph_exec_symbol_concat(symbolic_vgg, previous_exec_symbol, exec_symbol);
74
15
      tensor_symbol = next_symbol;
75
15
      previous_exec_symbol = exec_symbol;
76
15
    }
77
21
    if (i == convnet->count - 1)
78
1
      *dest_symbol = exec_symbol;
79
21
    // This is the input of next layer.
80
21
    input_symbol = tensor_symbol;
81
21
  }
82
1
  return symbolic_vgg;
83
1
}
84
85
TEST_CASE("run vgg-d graph from its symbolic representation")
86
1
{
87
1
  ccv_convnet_t* convnet = ccv_convnet_read(0, "../../../samples/image-net-2012-vgg-d.sqlite3");
88
1
  ccv_dense_matrix_t* image = 0;
89
1
  ccv_read("../../../samples/dex.png", &image, CCV_IO_ANY_FILE | CCV_IO_RGB_COLOR);
90
1
  ccv_dense_matrix_t* input = 0;
91
1
  ccv_convnet_input_formation(convnet->input, image, &input);
92
1
  ccv_matrix_free(image);
93
1
  ccv_dense_matrix_t* sliced = 0;
94
1
  ccv_slice(input, (ccv_matrix_t**)&sliced, 0, (input->rows - 225) / 2, (input->cols - 225) / 2, 225, 225);
95
1
  ccv_matrix_free(input);
96
1
  ccv_dense_matrix_t* b = 0;
97
1
  ccv_convnet_encode(convnet, &sliced, &b, 1);
98
1
  ccv_nnc_tensor_t* c = ccv_nnc_tensor_new(0, ONE_CPU_TENSOR(1000), 0);
99
1
  ccv_nnc_tensor_symbol_t* w_symbols = ccmalloc(sizeof(ccv_nnc_tensor_symbol_t) * convnet->count);
100
1
  ccv_nnc_tensor_symbol_t* bias_symbols = ccmalloc(sizeof(ccv_nnc_tensor_symbol_t) * convnet->count);
101
1
  ccv_nnc_graph_exec_symbol_t source_symbol, dest_symbol;
102
1
  ccv_nnc_tensor_symbol_t input_symbol, output_symbol;
103
1
  ccv_nnc_symbolic_graph_t* graph = ccv_nnc_simple_symbolic_graph(convnet, (ccv_nnc_tensor_t*)sliced, c, &source_symbol, &dest_symbol, &input_symbol, &output_symbol, w_symbols, bias_symbols);
104
1
  ccv_nnc_graph_t* run_graph = 0;
105
1
  ccv_nnc_tensor_arena_t* tensor_arena = 0;
106
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
107
1
  SYMBOLIC_GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
108
1
  ccv_nnc_symbolic_graph_compile(graph, 
TENSOR_BIND_MAP1
(KV(input_symbol, (ccv_nnc_tensor_t*)sliced), KV(output_symbol, c)),
GRAPH_EXEC_SYMBOL_LIST1
(source_symbol),
GRAPH_EXEC_SYMBOL_LIST1
(dest_symbol), &run_graph, &tensor_arena, &graph_exec_arena);
109
1
  GRAPH_GEN(run_graph, CCV_NNC_LONG_DOT_GRAPH);
110
1
  int i;
111
22
  for (i = 0; 
i < convnet->count22
;
i++21
)
112
21
  {
113
21
    ccv_convnet_layer_t* layer = convnet->layers + i;
114
21
    if (layer->type == CCV_CONVNET_CONVOLUTIONAL)
115
13
    {
116
13
      ccv_nnc_tensor_t* w = ccv_nnc_tensor_from_symbol(tensor_arena, w_symbols[i]);
117
13
      memcpy(w->data.f32, layer->w, layer->wnum * sizeof(float));
118
13
      ccv_nnc_tensor_t* bias = ccv_nnc_tensor_from_symbol(tensor_arena, bias_symbols[i]);
119
13
      memcpy(bias->data.f32, layer->bias, layer->net.convolutional.count * sizeof(float));
120
8
    } else 
if (8
layer->type == CCV_CONVNET_FULL_CONNECT8
)
{3
121
3
      ccv_nnc_tensor_t* w = ccv_nnc_tensor_from_symbol(tensor_arena, w_symbols[i]);
122
3
      memcpy(w->data.f32, layer->w, layer->wnum * sizeof(float));
123
3
      ccv_nnc_tensor_t* bias = ccv_nnc_tensor_from_symbol(tensor_arena, bias_symbols[i]);
124
3
      memcpy(bias->data.f32, layer->bias, layer->net.full_connect.count * sizeof(float));
125
3
    }
126
21
  }
127
1
  ccv_nnc_graph_autotune(run_graph, 0, 0, 
GRAPH_EXEC_LIST1
(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, source_symbol)),
GRAPH_EXEC_LIST1
(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, dest_symbol)));
128
1
  // Repopulate the weight. Since the weight tensor may be reused, need to repopulate every time run.
129
1
  // To avoid this, bind the weights directly or declare as const.
130
22
  for (i = 0; 
i < convnet->count22
;
i++21
)
131
21
  {
132
21
    ccv_convnet_layer_t* layer = convnet->layers + i;
133
21
    if (layer->type == CCV_CONVNET_CONVOLUTIONAL)
134
13
    {
135
13
      ccv_nnc_tensor_t* w = ccv_nnc_tensor_from_symbol(tensor_arena, w_symbols[i]);
136
13
      memcpy(w->data.f32, layer->w, layer->wnum * sizeof(float));
137
13
      ccv_nnc_tensor_t* bias = ccv_nnc_tensor_from_symbol(tensor_arena, bias_symbols[i]);
138
13
      memcpy(bias->data.f32, layer->bias, layer->net.convolutional.count * sizeof(float));
139
8
    } else 
if (8
layer->type == CCV_CONVNET_FULL_CONNECT8
)
{3
140
3
      ccv_nnc_tensor_t* w = ccv_nnc_tensor_from_symbol(tensor_arena, w_symbols[i]);
141
3
      memcpy(w->data.f32, layer->w, layer->wnum * sizeof(float));
142
3
      ccv_nnc_tensor_t* bias = ccv_nnc_tensor_from_symbol(tensor_arena, bias_symbols[i]);
143
3
      memcpy(bias->data.f32, layer->bias, layer->net.full_connect.count * sizeof(float));
144
3
    }
145
21
  }
146
1
  ccv_nnc_graph_run(run_graph, 0, 
GRAPH_EXEC_LIST1
(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, source_symbol)),
GRAPH_EXEC_LIST1
(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, dest_symbol)));
147
1
  
REQUIRE_ARRAY_EQ_WITH_TOLERANCE1
(float, b->data.f32, c->data.f32, 1000, 1e-4, "output should be the same from convnet and from the symbolic graph")
;1
148
1
  ccv_nnc_tensor_free(c);
149
1
  ccv_matrix_free(sliced);
150
1
  ccv_matrix_free(b);
151
1
  ccv_nnc_symbolic_graph_free(graph);
152
1
  ccv_nnc_graph_free(run_graph);
153
1
  ccv_nnc_tensor_arena_free(tensor_arena);
154
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
155
1
  ccfree(w_symbols);
156
1
  ccfree(bias_symbols);
157
1
  ccv_convnet_free(convnet);
158
1
}
159
160
#include "case_main.h"