/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" |