Coverage Report

Created: 2019-07-03 22:50

/home/liu/buildslave/linux-x64-runtests/build/test/unit/nnc/symbolic.graph.tests.c
Line
Count
Source
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 "3rdparty/dsfmt/dSFMT.h"
8
9
TEST_SETUP()
10
{
11
  ccv_nnc_init();
12
}
13
14
TEST_CASE("compile symbolic graph of one node")
15
1
{
16
1
  ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
17
1
  ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "a");
18
1
  ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "b");
19
1
  ccv_nnc_tensor_symbol_t c = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "c");
20
1
  ccv_nnc_graph_exec_symbol_t prod = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(a, b), TENSOR_SYMBOL_LIST(c), "prod");
21
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
22
1
  ccv_nnc_graph_t* graph = 0;
23
1
  ccv_nnc_tensor_arena_t* tensor_arena = 0;
24
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
25
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, 0, 0, 0, 0, GRAPH_EXEC_SYMBOL_LIST(prod), GRAPH_EXEC_SYMBOL_LIST(prod), &graph, &tensor_arena, &graph_exec_arena);
26
1
  SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_SHORT_DOT_GRAPH);
27
1
  GRAPH_GEN(graph, CCV_NNC_SHORT_DOT_GRAPH);
28
1
  ccv_nnc_tensor_t* a_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, a);
29
1
  ccv_nnc_tensor_t* b_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b);
30
1
  ccv_nnc_tensor_t* c_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, c);
31
1
  a_tensor->data.f32[0] = 1.2;
32
1
  b_tensor->data.f32[0] = 2.3;
33
1
  ccv_nnc_graph_exec_t prod_exec = ccv_nnc_graph_exec_from_symbol(graph_exec_arena, prod);
34
1
  ccv_nnc_graph_run(graph, 0, 0, 0, GRAPH_EXEC_LIST(prod_exec), GRAPH_EXEC_LIST(prod_exec));
35
1
  REQUIRE(a_tensor->data.f32 == c_tensor->data.f32, "trivially in-place operation, should point to the same memory region");
36
1
  REQUIRE_EQ_WITH_TOLERANCE(c_tensor->data.f32[0], 1.2 * 2.3, 1e-6, "should be equal to 1.2 * 2.3");
37
1
  ccv_nnc_graph_free(graph);
38
1
  ccv_nnc_tensor_arena_free(tensor_arena);
39
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
40
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
41
1
}
42
43
TEST_CASE("compile a simple symbolic graph with autogen")
44
1
{
45
1
  ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
46
1
  ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 31, 21, 2), "a");
47
1
  ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 31, 21, 4), "b");
48
1
  ccv_nnc_cmd_t forw_cmd = CMD_CONVOLUTION_FORWARD(1, 4, 5, 3, 2);
49
1
  ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 4, 5, 3, 2), "w");
50
1
  ccv_nnc_tensor_symbol_t bias = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 4), "bias");
51
1
  // See what we compile to when have unused tensors.
52
1
  ccv_nnc_tensor_symbol_t unused0 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "unused0");
53
1
  ccv_nnc_tensor_symbol_t unused1 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "unused1");
54
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, forw_cmd, TENSOR_SYMBOL_LIST(a, w, bias), TENSOR_SYMBOL_LIST(b), "forw");
55
1
  ccv_nnc_tensor_symbol_t m = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 31, 21, 4), "m");
56
1
  ccv_nnc_cmd_t softmax_cmd = CMD_SOFTMAX_FORWARD();
57
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, softmax_cmd, TENSOR_SYMBOL_LIST(b), TENSOR_SYMBOL_LIST(m), "softmax");
58
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
59
1
  ccv_nnc_graph_t* graph = 0;
60
1
  ccv_nnc_tensor_arena_t* tensor_arena = 0;
61
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
62
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, 0, 0, 0, 0, SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph), &graph, &tensor_arena, &graph_exec_arena);
63
1
  SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
64
1
  GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
65
1
  ccv_nnc_tensor_t* a_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, a);
66
1
  ccv_nnc_tensor_t* b_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b);
67
1
  ccv_nnc_tensor_t* m_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, m);
68
1
  REQUIRE(a_tensor->data.u8 != b_tensor->data.u8, "tensor a and b shouldn't share the memory.");
69
1
  REQUIRE(b_tensor->data.u8 == m_tensor->data.u8, "tensor b and m should share the memory because softmax is an inplace op.");
70
1
  REQUIRE(ccv_nnc_tensor_from_symbol(tensor_arena, unused0) == 0, "tensor unused 0 should have not pointed memory.");
71
1
  REQUIRE(ccv_nnc_tensor_from_symbol(tensor_arena, unused1) == 0, "tensor unused 0 should have not pointed memory.");
72
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
73
1
  ccv_nnc_graph_free(graph);
74
1
  ccv_nnc_tensor_arena_free(tensor_arena);
75
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
76
1
}
77
78
TEST_CASE("use symbolic graph disjoin and free")
79
1
{
80
1
  ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
81
1
  ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "a");
82
1
  ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "b");
83
1
  ccv_nnc_tensor_symbol_t c = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "c");
84
1
  ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x");
85
1
  ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y");
86
1
  ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "z");
87
1
  ccv_nnc_tensor_symbol_t p = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "p");
88
1
  ccv_nnc_tensor_symbol_t q = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "q");
89
1
  ccv_nnc_graph_exec_symbol_t prod = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(x, y), TENSOR_SYMBOL_LIST(z), "prod");
90
1
  ccv_nnc_graph_exec_symbol_t log0 = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWLOG_FORWARD(), TENSOR_SYMBOL_LIST(p), TENSOR_SYMBOL_LIST(q), "log0");
91
1
  ccv_nnc_graph_exec_symbol_t sum = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(a, b), TENSOR_SYMBOL_LIST(c), "sum");
92
1
  ccv_nnc_graph_exec_symbol_concat(symbolic_graph, sum, prod);
93
1
  ccv_nnc_graph_exec_symbol_concat(symbolic_graph, sum, log0);
94
1
  ccv_nnc_graph_exec_symbol_disjoin(symbolic_graph, sum, prod);
95
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
96
1
  REQUIRE(ccv_nnc_symbolic_graph_source_size(symbolic_graph) == 2, "sources now should contain both sum and prod");
97
1
  REQUIRE(ccv_nnc_symbolic_graph_destination_size(symbolic_graph) == 2, "destinations now should contain both log0 and prod");
98
1
  ccv_nnc_graph_exec_symbol_free(symbolic_graph, prod);
99
1
  REQUIRE(ccv_nnc_symbolic_graph_source_size(symbolic_graph) == 1, "sources now should contain sum");
100
1
  REQUIRE(ccv_nnc_symbolic_graph_destination_size(symbolic_graph) == 1, "destinations now should contain log0");
101
1
  REQUIRE(ccv_nnc_symbolic_graph_sources(symbolic_graph)->d == sum.d, "source should be sum");
102
1
  REQUIRE(ccv_nnc_symbolic_graph_destinations(symbolic_graph)->d == log0.d, "source should be log0");
103
1
  SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_SHORT_DOT_GRAPH);
104
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
105
1
}
106
107
TEST_CASE("set tensor symbol shape after computation specified")
108
1
{
109
1
  ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
110
1
  ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(symbolic_graph, ccv_nnc_tensor_auto, "a");
111
1
  ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(symbolic_graph, ccv_nnc_tensor_auto, "b");
112
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWLOG_FORWARD(), TENSOR_SYMBOL_LIST(a), TENSOR_SYMBOL_LIST(b), "log");
113
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
114
1
  ccv_nnc_tensor_symbol_set(symbolic_graph, a, CPU_TENSOR_NHWC(32F, 1));
115
1
  ccv_nnc_graph_t* graph = 0;
116
1
  ccv_nnc_tensor_arena_t* tensor_arena = 0;
117
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
118
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, 0, 0, 0, 0, SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph), &graph, &tensor_arena, &graph_exec_arena);
119
1
  SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
120
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
121
1
  GRAPH_GEN(graph, CCV_NNC_SHORT_DOT_GRAPH);
122
1
  ccv_nnc_tensor_t* const a_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, a);
123
1
  a_tensor->data.f32[0] = 1.25;
124
1
  ccv_nnc_graph_run(graph, 0, 0, 0, TRAVERSE_FULL);
125
1
  ccv_nnc_tensor_t* const b_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b);
126
1
  REQUIRE_EQ_WITH_TOLERANCE(b_tensor->data.f32[0], logf(1.25), 1e-5, "should be equal to logf(1.25)");
127
1
  ccv_nnc_graph_free(graph);
128
1
  ccv_nnc_tensor_arena_free(tensor_arena);
129
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
130
1
}
131
132
#include "case_main.h"