Coverage Report

Created: 2019-07-03 22:50

/home/liu/buildslave/linux-x64-runtests/build/test/unit/nnc/dynamic.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("dynamic graph to compute log(19)")
15
1
{
16
1
  ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
17
1
  ccv_nnc_tensor_variable_t a = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
18
1
  ccv_nnc_tensor_from_variable(graph, a)->data.f32[0] = 19;
19
1
  ccv_nnc_tensor_variable_t b = ccv_nnc_tensor_variable_new(graph);
20
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(a), TENSOR_VARIABLE_LIST(b));
21
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, b)->data.f32[0], logf(19), 1e-5, "log(19) result should be equal.");
22
1
  DYNAMIC_GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
23
1
  ccv_nnc_dynamic_graph_free(graph);
24
1
}
25
26
TEST_CASE("dynamic graph to compute f(x) = x * log(x) + 1.2 * x, f'(x) where x = 19")
27
1
{
28
1
  ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
29
1
  ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
30
1
  ccv_nnc_tensor_from_variable(graph, x)->data.f32[0] = 19;
31
1
  ccv_nnc_tensor_variable_t f = ccv_nnc_tensor_variable_new(graph);
32
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x), TENSOR_VARIABLE_LIST(f));
33
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x, f), TENSOR_VARIABLE_LIST(f));
34
1
  ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
35
1
  ccv_nnc_tensor_from_variable(graph, y)->data.f32[0] = 1.2;
36
1
  ccv_nnc_tensor_variable_t z = ccv_nnc_tensor_variable_new(graph);
37
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x, y), TENSOR_VARIABLE_LIST(z));
38
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_EWSUM_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(f, z), TENSOR_VARIABLE_LIST(f));
39
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, f)->data.f32[0], 19 * logf(19) + 1.2 * 19, 1e-5, "f(x) = 1.2 * 19 + 19 * log(19)");
40
1
  // Do gradient computation multiple times.
41
1
  ccv_nnc_tensor_variable_t dx = ccv_nnc_tensor_variable_new(graph);
42
1
  ccv_nnc_dynamic_graph_backward(graph, f, 0, TENSOR_VARIABLE_LIST(x), TENSOR_VARIABLE_LIST(dx));
43
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, dx)->data.f32[0], logf(19) + 1 + 1.2, 1e-5, "f'(x) = 1.2 + log(19) + 19 * 1 / 19");
44
1
  ccv_nnc_tensor_variable_t dy = ccv_nnc_tensor_variable_new(graph);
45
1
  ccv_nnc_dynamic_graph_backward(graph, f, 0, TENSOR_VARIABLE_LIST(y), TENSOR_VARIABLE_LIST(dy));
46
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, dy)->data.f32[0], 19, 1e-5, "f'(y) = 19");
47
1
  ccv_nnc_tensor_variable_t dz = ccv_nnc_tensor_variable_new(graph);
48
1
  ccv_nnc_dynamic_graph_backward(graph, f, 0, TENSOR_VARIABLE_LIST(z), TENSOR_VARIABLE_LIST(dz));
49
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, dz)->data.f32[0], 1, 1e-5, "f'(z) = 1");
50
1
  ccv_nnc_dynamic_graph_backward(graph, f, 0, TENSOR_VARIABLE_LIST(y, x), TENSOR_VARIABLE_LIST(dy, dx));
51
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, dx)->data.f32[0], logf(19) + 1 + 1.2, 1e-5, "f'(x) = 1.2 + log(19) + 19 * 1 / 19");
52
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, dy)->data.f32[0], 19, 1e-5, "f'(y) = 19");
53
1
  DYNAMIC_GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
54
1
  ccv_nnc_dynamic_graph_free(graph);
55
1
}
56
57
TEST_CASE("dynamic graph with dense net (extensive use of alias)")
58
1
{
59
1
  ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
60
1
  ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1, 4));
61
1
  ccv_nnc_tensor_from_variable(graph, x)->data.f32[0] = 0.472;
62
1
  ccv_nnc_tensor_variable_t x1 = ccv_nnc_tensor_variable_alias_new(graph, x, ccv_nnc_no_ofs, DIM_ALLOC(1, 4), CPU_TENSOR_NHWC(32F, 1, 1));
63
1
  ccv_nnc_tensor_variable_t w1 = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1, 1));
64
1
  ccv_nnc_tensor_from_variable(graph, w1)->data.f32[0] = 0.234;
65
1
  ccv_nnc_tensor_variable_t b1 = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
66
1
  ccv_nnc_tensor_from_variable(graph, b1)->data.f32[0] = 0.1;
67
1
  ccv_nnc_tensor_variable_t x11 = ccv_nnc_tensor_variable_alias_new(graph, x, DIM_ALLOC(0, 1), DIM_ALLOC(1, 4), CPU_TENSOR_NHWC(32F, 1, 1));
68
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_GEMM_FORWARD(1), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x1, w1, b1), TENSOR_VARIABLE_LIST(x11));
69
1
  ccv_nnc_tensor_variable_t x2 = ccv_nnc_tensor_variable_alias_new(graph, x, ccv_nnc_no_ofs, DIM_ALLOC(1, 4), CPU_TENSOR_NHWC(32F, 1, 2));
70
1
  ccv_nnc_tensor_variable_t w2 = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1, 2));
71
1
  ccv_nnc_tensor_from_variable(graph, w2)->data.f32[0] = 0.374;
72
1
  ccv_nnc_tensor_from_variable(graph, w2)->data.f32[1] = 0.886;
73
1
  ccv_nnc_tensor_variable_t b2 = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
74
1
  ccv_nnc_tensor_from_variable(graph, b2)->data.f32[0] = 0.2;
75
1
  ccv_nnc_tensor_variable_t x21 = ccv_nnc_tensor_variable_alias_new(graph, x, DIM_ALLOC(0, 2), DIM_ALLOC(1, 4), CPU_TENSOR_NHWC(32F, 1, 1));
76
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_GEMM_FORWARD(1), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x2, w2, b2), TENSOR_VARIABLE_LIST(x21));
77
1
  ccv_nnc_tensor_variable_t x3 = ccv_nnc_tensor_variable_alias_new(graph, x, ccv_nnc_no_ofs, DIM_ALLOC(1, 4), CPU_TENSOR_NHWC(32F, 1, 3));
78
1
  ccv_nnc_tensor_variable_t w3 = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1, 3));
79
1
  ccv_nnc_tensor_from_variable(graph, w3)->data.f32[0] = 0.484;
80
1
  ccv_nnc_tensor_from_variable(graph, w3)->data.f32[1] = 0.912;
81
1
  ccv_nnc_tensor_from_variable(graph, w3)->data.f32[2] = 0.235;
82
1
  ccv_nnc_tensor_variable_t b3 = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
83
1
  ccv_nnc_tensor_from_variable(graph, b3)->data.f32[0] = 0.3;
84
1
  ccv_nnc_tensor_variable_t x31 = ccv_nnc_tensor_variable_alias_new(graph, x, DIM_ALLOC(0, 3), DIM_ALLOC(1, 4), CPU_TENSOR_NHWC(32F, 1, 1));
85
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_GEMM_FORWARD(1), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x3, w3, b3), TENSOR_VARIABLE_LIST(x31));
86
1
  DYNAMIC_GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
87
1
  ccv_nnc_tensor_t* xt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1, 4), 0);
88
1
  xt->data.f32[0] = 0.472;
89
1
  xt->data.f32[1] = xt->data.f32[0] * 0.234 + 0.1;
90
1
  xt->data.f32[2] = xt->data.f32[0] * 0.374 + xt->data.f32[1] * 0.886 + 0.2;
91
1
  xt->data.f32[3] = xt->data.f32[0] * 0.484 + xt->data.f32[1] * 0.912 + xt->data.f32[2] * 0.235 + 0.3;
92
1
  REQUIRE_MATRIX_EQ(ccv_nnc_tensor_from_variable(graph, x), xt, "1x4 matrix should be exactly the same");
93
1
  ccv_nnc_tensor_free(xt);
94
1
  ccv_nnc_tensor_variable_t dw1 = ccv_nnc_tensor_variable_new(graph);
95
1
  ccv_nnc_dynamic_graph_backward(graph, x, 0, TENSOR_VARIABLE_LIST(w1), TENSOR_VARIABLE_LIST(dw1));
96
1
  REQUIRE_EQ_WITH_TOLERANCE((0.235 * 0.886 + 0.912) * 0.472, ccv_nnc_tensor_from_variable(graph, dw1)->data.f32[0], 1e-5, "the gradient should be equal to a complicated result");
97
1
  ccv_nnc_dynamic_graph_free(graph);
98
1
}
99
100
TEST_CASE("batch norm in dynamic graph (enforce inplace)")
101
1
{
102
1
  ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
103
1
  ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 2, 2, 2, 10));
104
1
  ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_variable_new(graph);
105
1
  ccv_nnc_tensor_variable_t scale = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 10));
106
1
  ccv_nnc_tensor_variable_t bias = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 10));
107
1
  ccv_nnc_tensor_variable_t mean = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 10));
108
1
  ccv_nnc_tensor_variable_t var = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 10));
109
1
  ccv_nnc_tensor_variable_t saved_mean = ccv_nnc_tensor_variable_new(graph);
110
1
  ccv_nnc_tensor_variable_t saved_inv_std = ccv_nnc_tensor_variable_new(graph);
111
1
  dsfmt_t dsfmt;
112
1
  int i;
113
1
  dsfmt_init_gen_rand(&dsfmt, 1);
114
81
  for (i = 0; i < 2 * 2 * 2 * 10; 
i++80
)
115
80
    ccv_nnc_tensor_from_variable(graph, x)->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
116
11
  for (i = 0; i < 10; 
i++10
)
117
10
    ccv_nnc_tensor_from_variable(graph, scale)->data.f32[i] = 1;
118
11
  for (i = 0; i < 10; 
i++10
)
119
10
    ccv_nnc_tensor_from_variable(graph, bias)->data.f32[i] = 0;
120
11
  for (i = 0; i < 10; 
i++10
)
121
10
    ccv_nnc_tensor_from_variable(graph, mean)->data.f32[i] = 0;
122
1
  ccv_nnc_tensor_t* mean_tensor_ptr = ccv_nnc_tensor_from_variable(graph, mean);
123
11
  for (i = 0; i < 10; 
i++10
)
124
10
    ccv_nnc_tensor_from_variable(graph, var)->data.f32[i] = 0;
125
1
  ccv_nnc_tensor_t* var_tensor_ptr = ccv_nnc_tensor_from_variable(graph, var);
126
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_BATCH_NORM_FORWARD(0, 0, 0.9, 0, 1, 2), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x, scale, bias, mean, var), TENSOR_VARIABLE_LIST(y, mean, var, saved_mean, saved_inv_std));
127
1
  DYNAMIC_GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
128
1
  REQUIRE(mean_tensor_ptr == ccv_nnc_tensor_from_variable(graph, mean), "enforced inplace, tensor view pointer unchanged");
129
1
  REQUIRE(var_tensor_ptr == ccv_nnc_tensor_from_variable(graph, var), "enforced inplace, tensor view pointer unchanged");
130
1
  ccv_nnc_tensor_t* x_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 2, 10), 0);
131
1
  ccv_nnc_tensor_t* y_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 2, 10), 0);
132
1
  ccv_nnc_tensor_t* scale_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0);
133
1
  ccv_nnc_tensor_t* bias_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0);
134
1
  ccv_nnc_tensor_t* mean_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0);
135
1
  ccv_nnc_tensor_t* var_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0);
136
1
  ccv_nnc_tensor_t* saved_mean_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1, 1, 1, 10), 0);
137
1
  ccv_nnc_tensor_t* saved_inv_std_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1, 1, 1, 10), 0);
138
1
  memcpy(x_tensor->data.f32, ccv_nnc_tensor_from_variable(graph, x)->data.f32, sizeof(float) * 2 * 2 * 2 * 10);
139
11
  for (i = 0; i < 10; 
i++10
)
140
10
    scale_tensor->data.f32[i] = 1;
141
1
  memset(bias_tensor->data.f32, 0, sizeof(float) * 10);
142
1
  memset(mean_tensor->data.f32, 0, sizeof(float) * 10);
143
1
  memset(var_tensor->data.f32, 0, sizeof(float) * 10);
144
1
  ccv_nnc_cmd_exec(CMD_BATCH_NORM_FORWARD(0, 0, 0.9, 0, 1, 2), ccv_nnc_no_hint, 0, TENSOR_LIST(x_tensor, scale_tensor, bias_tensor, mean_tensor, var_tensor), TENSOR_LIST(y_tensor, mean_tensor, var_tensor, saved_mean_tensor, saved_inv_std_tensor), 0);
145
1
  REQUIRE_TENSOR_EQ(y_tensor, ccv_nnc_tensor_from_variable(graph, y), "y should be equal");
146
1
  REQUIRE_TENSOR_EQ(mean_tensor, ccv_nnc_tensor_from_variable(graph, mean), "mean should be equal");
147
1
  REQUIRE_TENSOR_EQ(var_tensor, ccv_nnc_tensor_from_variable(graph, var), "var should be equal");
148
1
  REQUIRE_TENSOR_EQ(saved_mean_tensor, ccv_nnc_tensor_from_variable(graph, saved_mean), "saved_mean should be equal");
149
1
  REQUIRE_TENSOR_EQ(saved_inv_std_tensor, ccv_nnc_tensor_from_variable(graph, saved_inv_std), "saved_inv_std should be equal");
150
1
  ccv_nnc_dynamic_graph_free(graph);
151
1
  ccv_nnc_tensor_free(x_tensor);
152
1
  ccv_nnc_tensor_free(y_tensor);
153
1
  ccv_nnc_tensor_free(scale_tensor);
154
1
  ccv_nnc_tensor_free(bias_tensor);
155
1
  ccv_nnc_tensor_free(mean_tensor);
156
1
  ccv_nnc_tensor_free(var_tensor);
157
1
  ccv_nnc_tensor_free(saved_mean_tensor);
158
1
  ccv_nnc_tensor_free(saved_inv_std_tensor);
159
1
}
160
161
TEST_CASE("empty inputs / outputs for dynamic graph")
162
1
{
163
1
  ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
164
1
  ccv_nnc_tensor_variable_t df = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
165
1
  ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
166
1
  ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_variable_new(graph);
167
1
  ccv_nnc_tensor_from_variable(graph, df)->data.f32[0] = 1;
168
1
  ccv_nnc_tensor_from_variable(graph, x)->data.f32[0] = 10;
169
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_EWDIV_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(df, 0, x), TENSOR_VARIABLE_LIST(y, 0));
170
1
  DYNAMIC_GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
171
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, y)->data.f32[0], 1. / 10, 1e-5, "div backward should equal to 1 / 10");
172
1
  ccv_nnc_dynamic_graph_free(graph);
173
1
}
174
175
TEST_CASE("long dynamic graph with unused variables freed")
176
1
{
177
1
  ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
178
1
  int i;
179
1
  ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
180
1
  ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
181
1
  ccv_nnc_tensor_from_variable(graph, x)->data.f32[0] = 32;
182
1
  ccv_nnc_tensor_from_variable(graph, y)->data.f32[0] = 0.5;
183
11
  for (i = 0; i < 10; 
i++10
)
184
10
  {
185
10
    ccv_nnc_tensor_variable_t z = ccv_nnc_tensor_variable_new(graph);
186
10
    if (i < 7)
187
7
      ccv_nnc_dynamic_graph_exec(graph, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x, y), TENSOR_VARIABLE_LIST(z));
188
3
    else {
189
3
      if (i == 7)
190
1
        ccv_nnc_tensor_variable_free(graph, y); // No longer need y.
191
3
      ccv_nnc_dynamic_graph_exec(graph, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x, x), TENSOR_VARIABLE_LIST(z));
192
3
    }
193
10
    if (i < 9)
194
9
      ccv_nnc_tensor_variable_free(graph, x);
195
10
    x = z;
196
10
  }
197
1
  DYNAMIC_GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
198
1
  float g = 32;
199
11
  for (i = 0; i < 10; 
i++10
)
200
10
  {
201
10
    if (i < 7)
202
7
      g = g * 0.5;
203
3
    else
204
3
      g = g * g;
205
10
  }
206
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, x)->data.f32[0], g, 1e-5, "x should equal to the computed result");
207
1
  ccv_nnc_dynamic_graph_free(graph);
208
1
}
209
210
TEST_CASE("repeat multiple x * y with y as a constant")
211
1
{
212
1
  ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
213
1
  int i;
214
1
  ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
215
1
  ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_constant_new(graph, CPU_TENSOR_NHWC(32F, 1));
216
1
  ccv_nnc_tensor_from_variable(graph, x)->data.f32[0] = 32;
217
1
  ccv_nnc_tensor_from_variable(graph, y)->data.f32[0] = 0.5;
218
11
  for (i = 0; i < 10; 
i++10
)
219
10
  {
220
10
    ccv_nnc_tensor_variable_t z = ccv_nnc_tensor_variable_new(graph);
221
10
    ccv_nnc_dynamic_graph_exec(graph, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x, y), TENSOR_VARIABLE_LIST(z));
222
10
    ccv_nnc_tensor_variable_free(graph, x);
223
10
    x = z;
224
10
  }
225
1
  DYNAMIC_GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
226
1
  float g = 32;
227
11
  for (i = 0; i < 10; 
i++10
)
228
10
    g = g * 0.5;
229
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, x)->data.f32[0], g, 1e-5, "x should equal to the computed result");
230
1
  ccv_nnc_dynamic_graph_free(graph);
231
1
}
232
233
TEST_CASE("repeat multiple x * y with y as a constant, compute d(x)")
234
1
{
235
1
  ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
236
1
  int i;
237
1
  ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
238
1
  ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_constant_new(graph, CPU_TENSOR_NHWC(32F, 1));
239
1
  ccv_nnc_tensor_variable_t ox = x;
240
1
  ccv_nnc_tensor_from_variable(graph, x)->data.f32[0] = 32;
241
1
  ccv_nnc_tensor_from_variable(graph, y)->data.f32[0] = 0.9;
242
5
  for (i = 0; i < 4; 
i++4
)
243
4
  {
244
4
    ccv_nnc_tensor_variable_t z = ccv_nnc_tensor_variable_new(graph);
245
4
    ccv_nnc_dynamic_graph_exec(graph, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x, y), TENSOR_VARIABLE_LIST(z));
246
4
    if (i > 0)
247
3
      ccv_nnc_tensor_variable_free(graph, x);
248
4
    x = z;
249
4
  }
250
1
  ccv_nnc_tensor_variable_t dx = ccv_nnc_tensor_variable_new(graph);
251
1
  ccv_nnc_dynamic_graph_backward(graph, x, 0, TENSOR_VARIABLE_LIST(ox), TENSOR_VARIABLE_LIST(dx));
252
1
  ccv_nnc_tensor_variable_free(graph, ox);
253
1
  DYNAMIC_GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
254
1
  float g = 1;
255
5
  for (i = 0; i < 4; 
i++4
)
256
4
    g = g * 0.9;
257
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, dx)->data.f32[0], g, 1e-5, "x should equal to the computed result");
258
1
  ccv_nnc_dynamic_graph_free(graph);
259
1
}
260
261
TEST_CASE("compute f(x) = x * log(x) + x, f'(x) when x = 10 (and intermediate results all freed)")
262
1
{
263
1
  ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
264
1
  ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
265
1
  ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_variable_new(graph);
266
1
  ccv_nnc_tensor_variable_t f = ccv_nnc_tensor_variable_new(graph);
267
1
  ccv_nnc_tensor_from_variable(graph, x)->data.f32[0] = 10;
268
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x), TENSOR_VARIABLE_LIST(y));
269
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x, y), TENSOR_VARIABLE_LIST(y));
270
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_EWSUM_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(y, x), TENSOR_VARIABLE_LIST(f));
271
1
  ccv_nnc_tensor_variable_t df = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
272
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_SET_FORWARD(1), ccv_nnc_no_hint, 0, 0, 0, TENSOR_VARIABLE_LIST(df));
273
1
  ccv_nnc_dynamic_graph_backward(graph, f, df, TENSOR_VARIABLE_LIST(x), TENSOR_VARIABLE_LIST(x));
274
1
  DYNAMIC_GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
275
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, x)->data.f32[0], log(10) + 1 + 1, 1e-5, "dx should equal to the computed result");
276
1
  ccv_nnc_dynamic_graph_free(graph);
277
1
}
278
279
TEST_CASE("dynamic graph with binded value")
280
1
{
281
1
  ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
282
1
  ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph, CPU_TENSOR_NHWC(32F, 1));
283
1
  ccv_nnc_tensor_t* const x_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
284
1
  x_tensor->data.f32[0] = 10;
285
1
  ccv_nnc_tensor_variable_set(graph, x, x_tensor);
286
1
  ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_variable_new(graph);
287
1
  ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x), TENSOR_VARIABLE_LIST(y));
288
1
  DYNAMIC_GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
289
1
  REQUIRE_EQ_WITH_TOLERANCE(ccv_nnc_tensor_from_variable(graph, y)->data.f32[0], log(10), 1e-5, "dx should equal to the computed result");
290
1
  ccv_nnc_dynamic_graph_free(graph);
291
1
  ccv_nnc_tensor_free(x_tensor);
292
1
}
293
294
#include "case_main.h"