/home/liu/actions-runner/_work/ccv/ccv/test/unit/nnc/compare.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("min of two tensors") |
15 | 1 | { |
16 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
17 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
18 | 1 | ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
19 | 1 | int i; |
20 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
21 | 12 | a->data.f32[i] = i; |
22 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
23 | 12 | b->data.f32[i] = i - 1; |
24 | 1 | ccv_nnc_cmd_exec(CMD_MIN_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(a, b), TENSOR_LIST(c), 0); |
25 | 1 | REQUIRE_TENSOR_EQ(b, c, "c should be the minimal of the two"); |
26 | 1 | ccv_nnc_tensor_free(a); |
27 | 1 | ccv_nnc_tensor_free(b); |
28 | 1 | ccv_nnc_tensor_free(c); |
29 | 1 | } |
30 | | |
31 | | TEST_CASE("min of two tensor views") |
32 | 1 | { |
33 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
34 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
35 | 1 | ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
36 | 1 | int i; |
37 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
38 | 48 | a->data.f32[i] = i; |
39 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
40 | 48 | b->data.f32[i] = i - 1; |
41 | 1 | ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
42 | 1 | ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
43 | 1 | ccv_nnc_cmd_exec(CMD_MIN_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(c), 0); |
44 | 1 | ccv_nnc_tensor_t* const bvt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
45 | 1 | ccv_nnc_cmd_exec(CMD_DATATYPE_CONVERSION_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)bv), TENSOR_LIST(bvt), 0); |
46 | 1 | REQUIRE_TENSOR_EQ(bvt, c, "c should be the minimal of the two"); |
47 | 1 | ccv_nnc_tensor_free(a); |
48 | 1 | ccv_nnc_tensor_free(b); |
49 | 1 | ccv_nnc_tensor_free(c); |
50 | 1 | ccv_nnc_tensor_free(bvt); |
51 | 1 | ccv_nnc_tensor_view_free(av); |
52 | 1 | ccv_nnc_tensor_view_free(bv); |
53 | 1 | } |
54 | | |
55 | | TEST_CASE("min of two tensors backward") |
56 | 1 | { |
57 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
58 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
59 | 1 | ccv_nnc_tensor_t* const g = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
60 | 1 | ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
61 | 1 | ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
62 | 1 | ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
63 | 1 | ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
64 | 1 | int i; |
65 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
66 | 12 | a->data.f32[i] = i; |
67 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
68 | 12 | b->data.f32[i] = i < 3 ? i3 : i - 19 ; |
69 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
70 | 12 | g->data.f32[i] = -1; |
71 | 1 | ccv_nnc_cmd_exec(CMD_MIN_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(g, a, b), TENSOR_LIST(ha, hb), 0); |
72 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
73 | 12 | hat->data.f32[i] = i < 3 ? -13 : 09 ; |
74 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
75 | 12 | hbt->data.f32[i] = -1; |
76 | 1 | REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3"); |
77 | 1 | REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients"); |
78 | 1 | ccv_nnc_tensor_free(a); |
79 | 1 | ccv_nnc_tensor_free(b); |
80 | 1 | ccv_nnc_tensor_free(g); |
81 | 1 | ccv_nnc_tensor_free(ha); |
82 | 1 | ccv_nnc_tensor_free(hb); |
83 | 1 | ccv_nnc_tensor_free(hat); |
84 | 1 | ccv_nnc_tensor_free(hbt); |
85 | 1 | } |
86 | | |
87 | | TEST_CASE("min of two tensors backward with null") |
88 | 1 | { |
89 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
90 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
91 | 1 | ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
92 | 1 | ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
93 | 1 | ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
94 | 1 | ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
95 | 1 | int i; |
96 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
97 | 12 | a->data.f32[i] = i; |
98 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
99 | 12 | b->data.f32[i] = i < 3 ? i3 : i - 19 ; |
100 | 1 | ccv_nnc_cmd_exec(CMD_MIN_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(0, a, b), TENSOR_LIST(ha, hb), 0); |
101 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
102 | 12 | hat->data.f32[i] = i < 3 ? 13 : 09 ; |
103 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
104 | 12 | hbt->data.f32[i] = 1; |
105 | 1 | REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3"); |
106 | 1 | REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients"); |
107 | 1 | ccv_nnc_tensor_free(a); |
108 | 1 | ccv_nnc_tensor_free(b); |
109 | 1 | ccv_nnc_tensor_free(ha); |
110 | 1 | ccv_nnc_tensor_free(hb); |
111 | 1 | ccv_nnc_tensor_free(hat); |
112 | 1 | ccv_nnc_tensor_free(hbt); |
113 | 1 | } |
114 | | |
115 | | TEST_CASE("min of two tensor views backward") |
116 | 1 | { |
117 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
118 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
119 | 1 | ccv_nnc_tensor_t* const g = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
120 | 1 | ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
121 | 1 | ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
122 | 1 | ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
123 | 1 | ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
124 | 1 | int i; |
125 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
126 | 48 | a->data.f32[i] = i; |
127 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
128 | 48 | b->data.f32[i] = i < 3 ? i3 : i - 145 ; |
129 | 1 | ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
130 | 1 | ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
131 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
132 | 12 | g->data.f32[i] = -1; |
133 | 1 | ccv_nnc_cmd_exec(CMD_MIN_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(g, (ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(ha, hb), 0); |
134 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
135 | 12 | hat->data.f32[i] = i < 3 ? -13 : 09 ; |
136 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
137 | 12 | hbt->data.f32[i] = -1; |
138 | 1 | REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3"); |
139 | 1 | REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients"); |
140 | 1 | ccv_nnc_tensor_free(a); |
141 | 1 | ccv_nnc_tensor_free(b); |
142 | 1 | ccv_nnc_tensor_view_free(av); |
143 | 1 | ccv_nnc_tensor_view_free(bv); |
144 | 1 | ccv_nnc_tensor_free(g); |
145 | 1 | ccv_nnc_tensor_free(ha); |
146 | 1 | ccv_nnc_tensor_free(hb); |
147 | 1 | ccv_nnc_tensor_free(hat); |
148 | 1 | ccv_nnc_tensor_free(hbt); |
149 | 1 | } |
150 | | |
151 | | TEST_CASE("min of two tensor views backward with null") |
152 | 1 | { |
153 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
154 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
155 | 1 | ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
156 | 1 | ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
157 | 1 | ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
158 | 1 | ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
159 | 1 | int i; |
160 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
161 | 48 | a->data.f32[i] = i; |
162 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
163 | 48 | b->data.f32[i] = i < 3 ? i3 : i - 145 ; |
164 | 1 | ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
165 | 1 | ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
166 | 1 | ccv_nnc_cmd_exec(CMD_MIN_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(0, (ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(ha, hb), 0); |
167 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
168 | 12 | hat->data.f32[i] = i < 3 ? 13 : 09 ; |
169 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
170 | 12 | hbt->data.f32[i] = 1; |
171 | 1 | REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3"); |
172 | 1 | REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients"); |
173 | 1 | ccv_nnc_tensor_free(a); |
174 | 1 | ccv_nnc_tensor_free(b); |
175 | 1 | ccv_nnc_tensor_view_free(av); |
176 | 1 | ccv_nnc_tensor_view_free(bv); |
177 | 1 | ccv_nnc_tensor_free(ha); |
178 | 1 | ccv_nnc_tensor_free(hb); |
179 | 1 | ccv_nnc_tensor_free(hat); |
180 | 1 | ccv_nnc_tensor_free(hbt); |
181 | 1 | } |
182 | | |
183 | | TEST_CASE("min of two tensors with model") |
184 | 1 | { |
185 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
186 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
187 | 1 | ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
188 | 1 | int i; |
189 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
190 | 12 | a->data.f32[i] = i; |
191 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
192 | 12 | b->data.f32[i] = i - 1; |
193 | 1 | ccv_cnnp_model_t* const min = ccv_cnnp_min(0); |
194 | 1 | const ccv_nnc_tensor_param_t a_params = CPU_TENSOR_NHWC(32F, 2, 2, 3); |
195 | 1 | const ccv_nnc_tensor_param_t b_params = CPU_TENSOR_NHWC(32F, 2, 2, 3); |
196 | 1 | ccv_cnnp_model_compile(min, TENSOR_PARAM_LIST(a_params, b_params), CMD_NOOP(), CMD_NOOP()); |
197 | 1 | ccv_cnnp_model_evaluate(min, (ccv_cnnp_evaluate_param_t){ |
198 | 1 | .requires_grad = 0, |
199 | 1 | .is_test = 0, |
200 | 1 | .disable_outgrad = CCV_CNNP_DISABLE_OUTGRAD_ALL |
201 | 1 | }, TENSOR_LIST(a, b), TENSOR_LIST(c), 0, 0); |
202 | 1 | REQUIRE_TENSOR_EQ(b, c, "c should be the minimal of the two"); |
203 | 1 | ccv_cnnp_model_free(min); |
204 | 1 | ccv_nnc_tensor_free(a); |
205 | 1 | ccv_nnc_tensor_free(b); |
206 | 1 | ccv_nnc_tensor_free(c); |
207 | 1 | } |
208 | | |
209 | | TEST_CASE("max of two tensors") |
210 | 1 | { |
211 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
212 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
213 | 1 | ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
214 | 1 | int i; |
215 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
216 | 12 | a->data.f32[i] = i; |
217 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
218 | 12 | b->data.f32[i] = i + 1; |
219 | 1 | ccv_nnc_cmd_exec(CMD_MAX_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(a, b), TENSOR_LIST(c), 0); |
220 | 1 | REQUIRE_TENSOR_EQ(b, c, "c should be the maximal of the two"); |
221 | 1 | ccv_nnc_tensor_free(a); |
222 | 1 | ccv_nnc_tensor_free(b); |
223 | 1 | ccv_nnc_tensor_free(c); |
224 | 1 | } |
225 | | |
226 | | TEST_CASE("max of two tensor views") |
227 | 1 | { |
228 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
229 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
230 | 1 | ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
231 | 1 | int i; |
232 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
233 | 48 | a->data.f32[i] = i; |
234 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
235 | 48 | b->data.f32[i] = i + 1; |
236 | 1 | ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
237 | 1 | ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
238 | 1 | ccv_nnc_cmd_exec(CMD_MAX_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(c), 0); |
239 | 1 | ccv_nnc_tensor_t* const bvt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
240 | 1 | ccv_nnc_cmd_exec(CMD_DATATYPE_CONVERSION_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)bv), TENSOR_LIST(bvt), 0); |
241 | 1 | REQUIRE_TENSOR_EQ(bvt, c, "c should be the maximal of the two"); |
242 | 1 | ccv_nnc_tensor_free(a); |
243 | 1 | ccv_nnc_tensor_free(b); |
244 | 1 | ccv_nnc_tensor_free(c); |
245 | 1 | ccv_nnc_tensor_free(bvt); |
246 | 1 | ccv_nnc_tensor_view_free(av); |
247 | 1 | ccv_nnc_tensor_view_free(bv); |
248 | 1 | } |
249 | | |
250 | | TEST_CASE("max of two tensors backward") |
251 | 1 | { |
252 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
253 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
254 | 1 | ccv_nnc_tensor_t* const g = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
255 | 1 | ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
256 | 1 | ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
257 | 1 | ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
258 | 1 | ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
259 | 1 | int i; |
260 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
261 | 12 | a->data.f32[i] = i; |
262 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
263 | 12 | b->data.f32[i] = i < 3 ? i3 : i + 19 ; |
264 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
265 | 12 | g->data.f32[i] = -1; |
266 | 1 | ccv_nnc_cmd_exec(CMD_MAX_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(g, a, b), TENSOR_LIST(ha, hb), 0); |
267 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
268 | 12 | hat->data.f32[i] = i < 3 ? -13 : 09 ; |
269 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
270 | 12 | hbt->data.f32[i] = -1; |
271 | 1 | REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3"); |
272 | 1 | REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients"); |
273 | 1 | ccv_nnc_tensor_free(a); |
274 | 1 | ccv_nnc_tensor_free(b); |
275 | 1 | ccv_nnc_tensor_free(g); |
276 | 1 | ccv_nnc_tensor_free(ha); |
277 | 1 | ccv_nnc_tensor_free(hb); |
278 | 1 | ccv_nnc_tensor_free(hat); |
279 | 1 | ccv_nnc_tensor_free(hbt); |
280 | 1 | } |
281 | | |
282 | | TEST_CASE("max of two tensors backward with null") |
283 | 1 | { |
284 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
285 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
286 | 1 | ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
287 | 1 | ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
288 | 1 | ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
289 | 1 | ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
290 | 1 | int i; |
291 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
292 | 12 | a->data.f32[i] = i; |
293 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
294 | 12 | b->data.f32[i] = i < 3 ? i3 : i + 19 ; |
295 | 1 | ccv_nnc_cmd_exec(CMD_MAX_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(0, a, b), TENSOR_LIST(ha, hb), 0); |
296 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
297 | 12 | hat->data.f32[i] = i < 3 ? 13 : 09 ; |
298 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
299 | 12 | hbt->data.f32[i] = 1; |
300 | 1 | REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3"); |
301 | 1 | REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients"); |
302 | 1 | ccv_nnc_tensor_free(a); |
303 | 1 | ccv_nnc_tensor_free(b); |
304 | 1 | ccv_nnc_tensor_free(ha); |
305 | 1 | ccv_nnc_tensor_free(hb); |
306 | 1 | ccv_nnc_tensor_free(hat); |
307 | 1 | ccv_nnc_tensor_free(hbt); |
308 | 1 | } |
309 | | |
310 | | TEST_CASE("max of two tensor views backward") |
311 | 1 | { |
312 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
313 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
314 | 1 | ccv_nnc_tensor_t* const g = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
315 | 1 | ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
316 | 1 | ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
317 | 1 | ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
318 | 1 | ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
319 | 1 | int i; |
320 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
321 | 48 | a->data.f32[i] = i; |
322 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
323 | 48 | b->data.f32[i] = i < 3 ? i3 : i + 145 ; |
324 | 1 | ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
325 | 1 | ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
326 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
327 | 12 | g->data.f32[i] = -1; |
328 | 1 | ccv_nnc_cmd_exec(CMD_MAX_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(g, (ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(ha, hb), 0); |
329 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
330 | 12 | hat->data.f32[i] = i < 3 ? -13 : 09 ; |
331 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
332 | 12 | hbt->data.f32[i] = -1; |
333 | 1 | REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3"); |
334 | 1 | REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients"); |
335 | 1 | ccv_nnc_tensor_free(a); |
336 | 1 | ccv_nnc_tensor_free(b); |
337 | 1 | ccv_nnc_tensor_view_free(av); |
338 | 1 | ccv_nnc_tensor_view_free(bv); |
339 | 1 | ccv_nnc_tensor_free(g); |
340 | 1 | ccv_nnc_tensor_free(ha); |
341 | 1 | ccv_nnc_tensor_free(hb); |
342 | 1 | ccv_nnc_tensor_free(hat); |
343 | 1 | ccv_nnc_tensor_free(hbt); |
344 | 1 | } |
345 | | |
346 | | TEST_CASE("max of two tensor views backward with null") |
347 | 1 | { |
348 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
349 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0); |
350 | 1 | ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
351 | 1 | ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
352 | 1 | ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
353 | 1 | ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
354 | 1 | int i; |
355 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
356 | 48 | a->data.f32[i] = i; |
357 | 49 | for (i = 0; i < 4 * 4 * 3; i++48 ) |
358 | 48 | b->data.f32[i] = i < 3 ? i3 : i + 145 ; |
359 | 1 | ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
360 | 1 | ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4 * 3, 3, 1)); |
361 | 1 | ccv_nnc_cmd_exec(CMD_MAX_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(0, (ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(ha, hb), 0); |
362 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
363 | 12 | hat->data.f32[i] = i < 3 ? 13 : 09 ; |
364 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
365 | 12 | hbt->data.f32[i] = 1; |
366 | 1 | REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3"); |
367 | 1 | REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients"); |
368 | 1 | ccv_nnc_tensor_free(a); |
369 | 1 | ccv_nnc_tensor_free(b); |
370 | 1 | ccv_nnc_tensor_view_free(av); |
371 | 1 | ccv_nnc_tensor_view_free(bv); |
372 | 1 | ccv_nnc_tensor_free(ha); |
373 | 1 | ccv_nnc_tensor_free(hb); |
374 | 1 | ccv_nnc_tensor_free(hat); |
375 | 1 | ccv_nnc_tensor_free(hbt); |
376 | 1 | } |
377 | | |
378 | | TEST_CASE("max of two tensors with model") |
379 | 1 | { |
380 | 1 | ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
381 | 1 | ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
382 | 1 | ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0); |
383 | 1 | int i; |
384 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
385 | 12 | a->data.f32[i] = i; |
386 | 13 | for (i = 0; i < 2 * 2 * 3; i++12 ) |
387 | 12 | b->data.f32[i] = i + 1; |
388 | 1 | ccv_cnnp_model_t* const max = ccv_cnnp_max(0); |
389 | 1 | const ccv_nnc_tensor_param_t a_params = CPU_TENSOR_NHWC(32F, 2, 2, 3); |
390 | 1 | const ccv_nnc_tensor_param_t b_params = CPU_TENSOR_NHWC(32F, 2, 2, 3); |
391 | 1 | ccv_cnnp_model_compile(max, TENSOR_PARAM_LIST(a_params, b_params), CMD_NOOP(), CMD_NOOP()); |
392 | 1 | ccv_cnnp_model_evaluate(max, (ccv_cnnp_evaluate_param_t){ |
393 | 1 | .requires_grad = 0, |
394 | 1 | .is_test = 0, |
395 | 1 | .disable_outgrad = CCV_CNNP_DISABLE_OUTGRAD_ALL |
396 | 1 | }, TENSOR_LIST(a, b), TENSOR_LIST(c), 0, 0); |
397 | 1 | REQUIRE_TENSOR_EQ(b, c, "c should be the maximal of the two"); |
398 | 1 | ccv_cnnp_model_free(max); |
399 | 1 | ccv_nnc_tensor_free(a); |
400 | 1 | ccv_nnc_tensor_free(b); |
401 | 1 | ccv_nnc_tensor_free(c); |
402 | 1 | } |
403 | | |
404 | | #include "case_main.h" |