Coverage Report

Created: 2024-08-19 11:27

/home/liu/actions-runner/_work/ccv/ccv/test/unit/nnc/tensor.bind.tests.c
Line
Count
Source
1
2
#include "case.h"
3
#include "ccv_case.h"
4
#include "ccv_nnc_case.h"
5
#include <ccv.h>
6
#include <nnc/ccv_nnc.h>
7
#include <nnc/ccv_nnc_easy.h>
8
#include "3rdparty/dsfmt/dSFMT.h"
9
10
TEST_SETUP()
11
{
12
  ccv_nnc_init();
13
}
14
15
static int while_4(ccv_nnc_tensor_t* const* const inputs, const int input_size, const void* const data)
16
5
{
17
5
  return inputs[0]->data.i64[0] < 4;
18
5
}
19
20
TEST_CASE("while z = a * x + b (x <- z) compiled a and b binded to a tensor")
21
1
{
22
1
  ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
23
1
  ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x");
24
1
  ccv_nnc_symbolic_graph_t* while_graph = ccv_nnc_symbolic_graph_new();
25
1
  ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph, "while");
26
1
  ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 1), "a");
27
1
  ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 1), "b");
28
1
  ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 1), "y");
29
1
  ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 1), "z");
30
1
  ccv_nnc_graph_exec_symbol_new(while_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(a, x), TENSOR_SYMBOL_LIST(y), "prod");
31
1
  ccv_nnc_graph_exec_symbol_t sum = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(y, b), TENSOR_SYMBOL_LIST(z), "sum");
32
1
  ccv_nnc_graph_exec_symbol_t noop = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
33
1
  ccv_nnc_graph_exec_symbol_concat(while_graph, sum, noop);
34
1
  ccv_nnc_graph_exec_symbol_autogen(while_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
35
1
  ccv_nnc_symbolic_graph_set_while_expr(while_graph, while_4, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(while_graph)), GRAPH_EXEC_SYMBOL_LIST(noop));
36
1
  ccv_nnc_symbolic_graph_set_carry_overs(while_graph, TENSOR_SYMBOL_MAP(KV(z, x)));
37
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
38
1
  SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
39
1
  ccv_nnc_graph_t* graph = 0;
40
1
  ccv_nnc_tensor_arena_t* tensor_arena = 0;
41
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
42
1
  ccv_nnc_tensor_t* a_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
43
1
  a_tensor->data.f32[0] = 0.3;
44
1
  ccv_nnc_tensor_t* b_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
45
1
  b_tensor->data.f32[0] = 1.1;
46
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params,
47
1
    TENSOR_BIND_MAP(KV(a, a_tensor), KV(b, b_tensor)), // Binding the tensors.
48
1
    0, 0,
49
1
    SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph),
50
1
    &graph, &tensor_arena, &graph_exec_arena);
51
1
  GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
52
1
  ccv_nnc_tensor_t* x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
53
1
  x_tensor->data.f32[0] = 0.88;
54
1
  ccv_nnc_tensor_t* z_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z);
55
1
  ccv_nnc_graph_exec_t source = ccv_nnc_graph_exec_source(graph_exec_arena);
56
1
  ccv_nnc_graph_exec_t destination = ccv_nnc_graph_exec_destination(graph_exec_arena);
57
1
  ccv_nnc_graph_run(graph, 0, &source, 1, &destination, 1, 0, 0);
58
1
  int i;
59
1
  float z_val = 0.88;
60
6
  for (i = 0; i < 5; 
i++5
)
61
5
    z_val = 0.3 * z_val + 1.1;
62
1
  REQUIRE_EQ_WITH_TOLERANCE(z_tensor->data.f32[0], z_val, 1e-6, "z should be equal to a * x + b (5)");
63
1
  ccv_nnc_tensor_free(a_tensor);
64
1
  ccv_nnc_tensor_free(b_tensor);
65
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
66
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
67
1
  ccv_nnc_tensor_arena_free(tensor_arena);
68
1
  ccv_nnc_graph_free(graph);
69
1
}
70
71
TEST_CASE("compile graph (a[1] + a[0]) * a where a is a binded tensor")
72
1
{
73
1
  ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
74
1
  const ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 2), "a");
75
1
  const ccv_nnc_tensor_symbol_t a0 = ccv_nnc_tensor_symbol_alias_new(symbolic_graph, a, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 1), "a[0]");
76
1
  const ccv_nnc_tensor_symbol_t a1 = ccv_nnc_tensor_symbol_alias_new(symbolic_graph, a, DIM_ALLOC(1), DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 1), "a[1]");
77
1
  const ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "b");
78
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(a0, a1), TENSOR_SYMBOL_LIST(b), "sum");
79
1
  const ccv_nnc_tensor_symbol_t c = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 2), "c");
80
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_MUL_FORWARD(1), TENSOR_SYMBOL_LIST(b, a), TENSOR_SYMBOL_LIST(c), "mul");
81
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
82
1
  SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
83
1
  ccv_nnc_graph_t* graph = 0;
84
1
  ccv_nnc_tensor_arena_t* tensor_arena = 0;
85
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
86
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params,
87
1
    0, 0,
88
1
    0, 0,
89
1
    SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph),
90
1
    &graph, &tensor_arena, &graph_exec_arena);
91
1
  GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
92
1
  ccv_nnc_tensor_t* const a_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2), 0);
93
1
  a_tensor->data.f32[0] = 1.1;
94
1
  a_tensor->data.f32[1] = 0.4;
95
1
  ccv_nnc_tensor_bind_symbol(tensor_arena, a, a_tensor);
96
1
  ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
97
1
  ccv_nnc_tensor_t* const c_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, c);
98
1
  float ct[] = {
99
1
    (1.1 + 0.4) * 1.1,
100
1
    (1.1 + 0.4) * 0.4,
101
1
  };
102
1
  ccv_nnc_tensor_t ct_tensor = ccv_nnc_tensor(ct, CPU_TENSOR_NHWC(32F, 2), 0);
103
1
  REQUIRE_TENSOR_EQ(c_tensor, &ct_tensor, "c should be equal to [(1.1 + 0.4) * 11, (1.1 + 0.4) * 0.4]");
104
1
  ccv_nnc_tensor_free(a_tensor);
105
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
106
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
107
1
  ccv_nnc_tensor_arena_free(tensor_arena);
108
1
  ccv_nnc_graph_free(graph);
109
1
}
110
111
TEST_CASE("compile a graph with tensor bindings, verify tensor arena doesn't allocate these tensors")
112
1
{
113
1
  ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
114
1
  const ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1, 2), "a");
115
1
  const ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 2, 1), "b");
116
1
  const ccv_nnc_tensor_symbol_t c = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "c");
117
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_GEMM_FORWARD(), TENSOR_SYMBOL_LIST(a, b), TENSOR_SYMBOL_LIST(c), "gemm");
118
1
  const ccv_nnc_tensor_symbol_t d = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "d");
119
1
  const ccv_nnc_tensor_symbol_t e = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "e");
120
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_GEMM_FORWARD(), TENSOR_SYMBOL_LIST(c, d), TENSOR_SYMBOL_LIST(e), "mul");
121
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
122
1
  SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
123
1
  ccv_nnc_tensor_t* const a_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1, 2), 0);
124
1
  ccv_nnc_tensor_t* const d_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
125
1
  ccv_nnc_tensor_t* const e_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
126
1
  ccv_nnc_graph_t* graph = 0;
127
1
  ccv_nnc_tensor_arena_t* tensor_arena = 0;
128
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
129
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params,
130
1
    TENSOR_BIND_MAP(KV(a, a_tensor), KV(d, d_tensor), KV(e, e_tensor)),
131
1
    0, 0,
132
1
    SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph),
133
1
    &graph, &tensor_arena, &graph_exec_arena);
134
1
  GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
135
1
  const uint64_t size = ccv_nnc_tensor_arena_size(tensor_arena);
136
1
  const uint64_t tensor_size = ccv_nnc_tensor_data_size(CPU_TENSOR_NHWC(32F, 1, 2)) + ccv_nnc_tensor_data_size(CPU_TENSOR_NHWC(32F, 1));
137
1
  REQUIRE_EQ(size, tensor_size, "tensor arena should only allocate for two symbols");
138
1
  a_tensor->data.f32[0] = 1.1;
139
1
  a_tensor->data.f32[1] = 11003;
140
1
  ccv_nnc_tensor_t* const b_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b);
141
1
  b_tensor->data.f32[0] = -1;
142
1
  b_tensor->data.f32[1] = -0.12;
143
1
  d_tensor->data.f32[0] = 0.5;
144
1
  ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
145
1
  REQUIRE_EQ_WITH_TOLERANCE(e_tensor->data.f32[0], -(11003 * 0.12 + 1.1) * 0.5, 1e-2, "result should be equal");
146
1
  ccv_nnc_tensor_free(a_tensor);
147
1
  ccv_nnc_tensor_free(d_tensor);
148
1
  ccv_nnc_tensor_free(e_tensor);
149
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
150
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
151
1
  ccv_nnc_tensor_arena_free(tensor_arena);
152
1
  ccv_nnc_graph_free(graph);
153
1
}
154
155
TEST_CASE("compile a graph with tensor binded to alias")
156
1
{
157
1
  ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
158
1
  const ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "a");
159
1
  const ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "b");
160
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWLOG_FORWARD(), TENSOR_SYMBOL_LIST(a), TENSOR_SYMBOL_LIST(b), "log");
161
1
  const ccv_nnc_tensor_symbol_t b_alias = ccv_nnc_tensor_symbol_alias_new(symbolic_graph, b, DIM_ALLOC(), DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 1), "alias");
162
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
163
1
  SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
164
1
  ccv_nnc_tensor_t* const a_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
165
1
  ccv_nnc_tensor_t* const b_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
166
1
  ccv_nnc_graph_t* graph = 0;
167
1
  ccv_nnc_tensor_arena_t* tensor_arena = 0;
168
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
169
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params,
170
1
      TENSOR_BIND_MAP(KV(a, a_tensor), KV(b_alias, b_tensor)),
171
1
      0, 0,
172
1
      SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph),
173
1
      &graph, &tensor_arena, &graph_exec_arena);
174
1
  b_tensor->data.f32[0] = 0;
175
1
  a_tensor->data.f32[0] = 2.34;
176
1
  ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
177
1
  REQUIRE_EQ_WITH_TOLERANCE(b_tensor->data.f32[0], log(2.34), 1e-5, "result should be equal");
178
1
  ccv_nnc_tensor_free(a_tensor);
179
1
  ccv_nnc_tensor_free(b_tensor);
180
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
181
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
182
1
  ccv_nnc_tensor_arena_free(tensor_arena);
183
1
  ccv_nnc_graph_free(graph);
184
1
}
185
186
TEST_CASE("compile a graph with tensor alias and bind to the alias later")
187
1
{
188
1
  ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
189
1
  const ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "a");
190
1
  const ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "b");
191
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWLOG_FORWARD(), TENSOR_SYMBOL_LIST(a), TENSOR_SYMBOL_LIST(b), "log");
192
1
  const ccv_nnc_tensor_symbol_t b_alias = ccv_nnc_tensor_symbol_alias_new(symbolic_graph, b, DIM_ALLOC(), DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 1), "alias");
193
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
194
1
  SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
195
1
  ccv_nnc_tensor_t* const a_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
196
1
  ccv_nnc_tensor_t* const b_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
197
1
  ccv_nnc_graph_t* graph = 0;
198
1
  ccv_nnc_tensor_arena_t* tensor_arena = 0;
199
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
200
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params,
201
1
      TENSOR_BIND_MAP(KV(a, a_tensor)),
202
1
      0, 0,
203
1
      SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph),
204
1
      &graph, &tensor_arena, &graph_exec_arena);
205
1
  b_tensor->data.f32[0] = 0;
206
1
  a_tensor->data.f32[0] = 2.34;
207
1
  ccv_nnc_tensor_bind_symbol(tensor_arena, b_alias, b_tensor);
208
1
  ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
209
1
  REQUIRE_EQ_WITH_TOLERANCE(b_tensor->data.f32[0], log(2.34), 1e-5, "result should be equal");
210
1
  ccv_nnc_tensor_free(a_tensor);
211
1
  ccv_nnc_tensor_free(b_tensor);
212
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
213
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
214
1
  ccv_nnc_tensor_arena_free(tensor_arena);
215
1
  ccv_nnc_graph_free(graph);
216
1
}
217
218
#include "case_main.h"