Coverage Report

Created: 2024-08-18 16:21

/home/liu/actions-runner/_work/ccv/ccv/test/int/nnc/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_nnc_case.h"
4
#include <ccv.h>
5
#include <nnc/ccv_nnc.h>
6
#include <nnc/ccv_nnc_easy.h>
7
#include <inc/ccv_convnet_internal.h>
8
9
TEST_SETUP()
10
{
11
  ccv_nnc_init();
12
}
13
14
static ccv_nnc_graph_t* ccv_nnc_simple_graph(ccv_convnet_t* convnet, ccv_nnc_tensor_t* input, ccv_nnc_tensor_t* output, ccv_nnc_graph_exec_t* source, ccv_nnc_graph_exec_t* dest, ccv_array_t* tensors)
15
1
{
16
1
  int i;
17
  // We only create the graph compute to the last fc layer.
18
1
  ccv_nnc_graph_t* vgg = ccv_nnc_graph_new();
19
1
  ccv_nnc_graph_exec_t previous_exec;
20
22
  for (i = 0; i < convnet->count; 
i++21
)
21
21
  {
22
21
    ccv_convnet_layer_t* layer = convnet->layers + i;
23
21
    int rows, cols, partition;
24
21
    ccv_convnet_make_output(layer, layer->input.matrix.rows, layer->input.matrix.cols, &rows, &cols, &partition);
25
21
    ccv_nnc_tensor_t* tensor = output;
26
21
    if (i < convnet->count - 1)
27
20
    {
28
20
      if (layer->type == CCV_CONVNET_FULL_CONNECT)
29
2
        tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, rows * cols * partition), 0);
30
18
      else
31
18
        tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, rows, cols, (layer->type == CCV_CONVNET_CONVOLUTIONAL ? layer->net.convolutional.count : layer->input.matrix.channels)), 0);
32
20
      ccv_array_push(tensors, &tensor);
33
20
    }
34
21
    ccv_nnc_graph_exec_t exec = {0};
35
21
    if (layer->type == CCV_CONVNET_CONVOLUTIONAL)
36
13
    {
37
13
      ccv_nnc_tensor_t* w = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, layer->net.convolutional.count, layer->net.convolutional.rows, layer->net.convolutional.cols, layer->net.convolutional.channels), 0);
38
13
      memcpy(w->data.f32, layer->w, layer->wnum * sizeof(float));
39
13
      ccv_nnc_tensor_t* bias = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, layer->net.convolutional.count), 0);
40
13
      memcpy(bias->data.f32, layer->bias, layer->net.convolutional.count * sizeof(float));
41
13
      ccv_array_push(tensors, &w);
42
13
      ccv_array_push(tensors, &bias);
43
13
      ccv_nnc_cmd_t cmd = CMD_CONVOLUTION_FORWARD(1, layer->net.convolutional.count, layer->net.convolutional.rows, layer->net.convolutional.cols, layer->net.convolutional.channels);
44
13
      ccv_nnc_hint_t hint = ccv_nnc_hint_auto(cmd.info, input->info, tensor->info);
45
13
      cmd = ccv_nnc_cmd_autotune(cmd, 0, hint, 0, TENSOR_LIST(input, w, bias), TENSOR_LIST(tensor), 0);
46
13
      exec = ccv_nnc_graph_exec_new(vgg, cmd, hint, TENSOR_LIST(input, w, bias), TENSOR_LIST(tensor));
47
13
    } else 
if (8
layer->type == CCV_CONVNET_MAX_POOL8
) {
48
5
      ccv_nnc_cmd_t cmd = CMD_MAX_POOL_FORWARD(layer->net.pool.size, layer->net.pool.size);
49
5
      ccv_nnc_hint_t hint = ccv_nnc_hint_auto(cmd.info, input->info, tensor->info);
50
5
      exec = ccv_nnc_graph_exec_new(vgg, cmd, hint, TENSOR_LIST(input), TENSOR_LIST(tensor));
51
5
    } else 
if (3
layer->type == CCV_CONVNET_FULL_CONNECT3
) {
52
3
      ccv_nnc_tensor_t* w = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, layer->net.full_connect.count, layer->input.node.count), 0);
53
3
      memcpy(w->data.f32, layer->w, layer->wnum * sizeof(float));
54
3
      ccv_nnc_tensor_t* bias = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, layer->net.full_connect.count), 0);
55
3
      memcpy(bias->data.f32, layer->bias, layer->net.full_connect.count * sizeof(float));
56
3
      ccv_array_push(tensors, &w);
57
3
      ccv_array_push(tensors, &bias);
58
3
      ccv_nnc_cmd_t cmd = CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1));
59
      // If the input is not what I expected (array), reshape it.
60
3
      if (input->info.dim[0] != ccv_nnc_tensor_count(input->info))
61
1
      {
62
1
        input = ccv_nnc_tensor_new(input->data.u8, CPU_TENSOR_NHWC(32F, ccv_nnc_tensor_count(input->info)), 0);
63
1
        ccv_array_push(tensors, &input);
64
1
      }
65
3
      cmd = ccv_nnc_cmd_autotune(cmd, 0, ccv_nnc_no_hint, 0, TENSOR_LIST(input, w, bias), TENSOR_LIST(tensor), 0);
66
3
      exec = ccv_nnc_graph_exec_new(vgg, cmd, ccv_nnc_no_hint, TENSOR_LIST(input, w, bias), TENSOR_LIST(tensor));
67
3
    } else {
68
0
      assert("unreachable");
69
0
    }
70
21
    if (i != 0)
71
20
      ccv_nnc_graph_exec_concat(vgg, previous_exec, exec);
72
21
    previous_exec = exec;
73
21
    if (i == 0)
74
1
      *source = exec;
75
21
    if (i < convnet->count - 1 &&
76
21
      
(20
layer->type == CCV_CONVNET_CONVOLUTIONAL20
||
layer->type == CCV_CONVNET_FULL_CONNECT7
))
77
15
    {
78
      // Create the ReLU layer.
79
15
      ccv_nnc_cmd_t cmd = CMD_RELU_FORWARD();
80
15
      exec = ccv_nnc_graph_exec_new(vgg, cmd, ccv_nnc_no_hint, TENSOR_LIST(tensor), TENSOR_LIST(tensor));
81
15
      ccv_nnc_graph_exec_concat(vgg, previous_exec, exec);
82
15
      previous_exec = exec;
83
15
    }
84
21
    if (i == convnet->count - 1)
85
1
      *dest = exec;
86
    // This is the input of next layer.
87
21
    input = tensor;
88
21
  }
89
1
  return vgg;
90
1
}
91
92
#ifdef HAVE_LIBPNG
93
TEST_CASE("run vgg-d graph with nnc")
94
1
{
95
1
  ccv_convnet_t* convnet = ccv_convnet_read(0, "../../../samples/image-net-2012-vgg-d.sqlite3");
96
1
  ccv_dense_matrix_t* image = 0;
97
1
  ccv_read("../../../samples/dex.png", &image, CCV_IO_ANY_FILE | CCV_IO_RGB_COLOR);
98
1
  ccv_dense_matrix_t* input = 0;
99
1
  ccv_convnet_input_formation(convnet->input, image, &input);
100
1
  ccv_matrix_free(image);
101
1
  ccv_dense_matrix_t* sliced = 0;
102
1
  ccv_slice(input, (ccv_matrix_t**)&sliced, 0, (input->rows - 225) / 2, (input->cols - 225) / 2, 225, 225);
103
1
  ccv_matrix_free(input);
104
1
  ccv_dense_matrix_t* b = 0;
105
1
  ccv_convnet_encode(convnet, &sliced, &b, 1);
106
1
  ccv_nnc_tensor_t* c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1000), 0);
107
1
  ccv_nnc_graph_exec_t source, dest;
108
1
  ccv_array_t* tensors = ccv_array_new(sizeof(ccv_nnc_tensor_t*), 1, 0);
109
1
  ccv_nnc_graph_t* graph = ccv_nnc_simple_graph(convnet, (ccv_nnc_tensor_t*)sliced, c, &source, &dest, tensors);
110
1
  GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
111
1
  ccv_nnc_graph_run(graph, 0, &source, 1, &dest, 1, 0, 0);
112
1
  REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, b->data.f32, c->data.f32, 1000, 1e-4, "output should be the same from convnet and from the graph");
113
1
  ccv_nnc_tensor_free(c);
114
1
  ccv_matrix_free(sliced);
115
1
  ccv_matrix_free(b);
116
1
  ccv_nnc_graph_free(graph);
117
1
  int i;
118
54
  for (i = 0; i < tensors->rnum; 
i++53
)
119
53
    ccv_nnc_tensor_free(*(ccv_nnc_tensor_t**)ccv_array_get(tensors, i));
120
1
  ccv_array_free(tensors);
121
1
  ccv_convnet_free(convnet);
122
1
}
123
#endif
124
125
#include "case_main.h"