/home/liu/actions-runner/_work/ccv/ccv/test/unit/nnc/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 | | static int _ccv_nnc_custom_24_loss_exec(const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, ccv_nnc_tensor_t* const* const inputs, const int input_size, ccv_nnc_tensor_t* const* const outputs, const int output_size, ccv_nnc_stream_context_t* const stream_context) |
15 | 1 | { |
16 | 1 | int i; |
17 | 1 | assert(input_size == 1); |
18 | 1 | const ccv_nnc_tensor_t* m = inputs[0]; |
19 | 1 | assert(output_size == 1); |
20 | 1 | ccv_nnc_tensor_t* g = outputs[0]; |
21 | 2.60k | for (i = 0; i < 21 * 31 * 4; i++2.60k ) |
22 | 2.60k | g->data.f32[i] = m->data.f32[i] - (i == 24); |
23 | 1 | return CCV_NNC_EXEC_SUCCESS; |
24 | 1 | } |
25 | | |
26 | | static ccv_nnc_cmd_vtab_t _custom_24_loss_isa = { |
27 | | .exec = _ccv_nnc_custom_24_loss_exec, |
28 | | }; |
29 | | |
30 | | TEST_CASE("run simple graph network") |
31 | 1 | { |
32 | 1 | ccv_nnc_graph_t* graph = ccv_nnc_graph_new(); |
33 | 1 | ccv_nnc_tensor_t* a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 31, 21, 2), 0); |
34 | 1 | ccv_nnc_tensor_t* b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 31, 21, 4), 0); |
35 | 1 | ccv_nnc_cmd_t forw_cmd = CMD_CONVOLUTION_FORWARD(1, 4, 5, 3, 2); |
36 | 1 | ccv_nnc_hint_t hint = ccv_nnc_hint_auto(forw_cmd.info, a->info, b->info); |
37 | 1 | ccv_nnc_tensor_t* w = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 5, 3, 2), 0); |
38 | 1 | ccv_nnc_tensor_t* bias = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4), 0); |
39 | 1 | dsfmt_t dsfmt; |
40 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
41 | 1 | int i; |
42 | 121 | for (i = 0; i < 2 * 3 * 5 * 4; i++120 ) |
43 | 120 | w->data.f32[i] = (dsfmt_genrand_open_close(&dsfmt) * 2 - 1) * 1.41421356237 / sqrtf(21 * 31 * 2 + 21 * 31 * 4); |
44 | 1 | float denom = (21 * 31 * 2 - 1) * 21 * 31 * 2; |
45 | 1.30k | for (i = 0; i < 21 * 31 * 2; i++1.30k ) |
46 | 1.30k | a->data.f32[i] = (float)(i - 21 * 31) / denom; |
47 | 5 | for (i = 0; i < 4; i++4 ) |
48 | 4 | bias->data.f32[i] = 0; |
49 | 1 | ccv_nnc_graph_exec_t forw_node = ccv_nnc_graph_exec_new(graph, forw_cmd, hint, TENSOR_LIST(a, w, bias), TENSOR_LIST(b)); |
50 | 1 | ccv_nnc_cmd_t softmax_cmd = CMD_SOFTMAX_FORWARD(); |
51 | 1 | ccv_nnc_tensor_t* m = ccv_nnc_tensor_new(0, b->info, 0); |
52 | 1 | ccv_nnc_graph_exec_t softmax_node = ccv_nnc_graph_exec_new(graph, softmax_cmd, hint, TENSOR_LIST(b), TENSOR_LIST(m)); |
53 | 1 | ccv_nnc_tensor_t* g = ccv_nnc_tensor_new(0, b->info, 0); |
54 | 1 | ccv_nnc_cmd_t loss_cmd = CMD_CUSTOM_FORWARD(&_custom_24_loss_isa); |
55 | 1 | ccv_nnc_graph_exec_t loss_node = ccv_nnc_graph_exec_new(graph, loss_cmd, hint, TENSOR_LIST(m), TENSOR_LIST(g)); |
56 | 1 | ccv_nnc_cmd_t back_cmd = CMD_CONVOLUTION_BACKWARD(1, 4, 2, 3, 5); |
57 | 1 | ccv_nnc_tensor_t* gw = ccv_nnc_tensor_new(0, w->info, 0); |
58 | 1 | ccv_nnc_tensor_t* gbias = ccv_nnc_tensor_new(0, bias->info, 0); |
59 | 1 | ccv_nnc_tensor_t* h = ccv_nnc_tensor_new(0, a->info, 0); |
60 | 1 | ccv_nnc_graph_exec_t back_node = ccv_nnc_graph_exec_new(graph, back_cmd, hint, TENSOR_LIST(g, a, w), TENSOR_LIST(h, gw, gbias)); |
61 | | // All nodes are created, now to concat the graph. |
62 | 1 | ccv_nnc_graph_exec_concat(graph, forw_node, softmax_node); |
63 | 1 | ccv_nnc_graph_exec_concat(graph, softmax_node, loss_node); |
64 | 1 | ccv_nnc_graph_exec_concat(graph, loss_node, back_node); |
65 | 1 | ccv_nnc_graph_exec_t source_nodes[] = { |
66 | 1 | forw_node, |
67 | 1 | }; |
68 | 1 | ccv_nnc_graph_exec_t destination_nodes[] = { |
69 | 1 | back_node, |
70 | 1 | }; |
71 | 1 | ccv_nnc_graph_run(graph, 0, source_nodes, 1, destination_nodes, 1, 0, 0); |
72 | 1 | ccv_nnc_graph_free(graph); |
73 | | /* At this point, do the computation with a different set of tensors and then compare */ |
74 | 1 | ccv_nnc_tensor_t* vb = ccv_nnc_tensor_new(0, b->info, 0); |
75 | 1 | ccv_nnc_cmd_exec(forw_cmd, hint, 0, TENSOR_LIST(a, w, bias), TENSOR_LIST(vb), 0); |
76 | 1 | REQUIRE_TENSOR_EQ(b, vb, "Graph computed forward pass result should be the same."); |
77 | 1 | ccv_nnc_tensor_t* vm = ccv_nnc_tensor_new(0, b->info, 0); |
78 | 1 | ccv_nnc_cmd_exec(softmax_cmd, hint, 0, TENSOR_LIST(vb), TENSOR_LIST(vm), 0); |
79 | 1 | REQUIRE_TENSOR_EQ(m, vm, "Graph computed softmax pass result should be the same."); |
80 | 1 | ccv_nnc_tensor_t* vg = ccv_nnc_tensor_new(0, g->info, 0); |
81 | 2.60k | for (i = 0; i < 21 * 31 * 4; i++2.60k ) |
82 | 2.60k | vg->data.f32[i] = vm->data.f32[i] - (i == 24); |
83 | 1 | REQUIRE_TENSOR_EQ(g, vg, "Graph computed custom loss result should be the same."); |
84 | 1 | ccv_nnc_tensor_t* vgw = ccv_nnc_tensor_new(0, w->info, 0); |
85 | 1 | ccv_nnc_tensor_t* vgbias = ccv_nnc_tensor_new(0, bias->info, 0); |
86 | 1 | ccv_nnc_tensor_t* vh = ccv_nnc_tensor_new(0, h->info, 0); |
87 | 1 | ccv_nnc_cmd_exec(back_cmd, hint, 0, TENSOR_LIST(vg, a, w), TENSOR_LIST(vh, vgw, vgbias), 0); |
88 | 1 | REQUIRE_TENSOR_EQ(gbias, vgbias, "Graph computed backward pass weight delta should be the same."); |
89 | 1 | REQUIRE_TENSOR_EQ(gw, vgw, "Graph computed backward pass bias delta should be the same."); |
90 | 1 | REQUIRE_TENSOR_EQ(h, vh, "Graph computed backward pass result should be the same."); |
91 | | // free all the tensor data. |
92 | 1 | ccv_nnc_tensor_free(a); |
93 | 1 | ccv_nnc_tensor_free(b); |
94 | 1 | ccv_nnc_tensor_free(m); |
95 | 1 | ccv_nnc_tensor_free(g); |
96 | 1 | ccv_nnc_tensor_free(h); |
97 | 1 | ccv_nnc_tensor_free(w); |
98 | 1 | ccv_nnc_tensor_free(bias); |
99 | 1 | ccv_nnc_tensor_free(gw); |
100 | 1 | ccv_nnc_tensor_free(gbias); |
101 | 1 | ccv_nnc_tensor_free(vb); |
102 | 1 | ccv_nnc_tensor_free(vm); |
103 | 1 | ccv_nnc_tensor_free(vg); |
104 | 1 | ccv_nnc_tensor_free(vh); |
105 | 1 | ccv_nnc_tensor_free(vgw); |
106 | 1 | ccv_nnc_tensor_free(vgbias); |
107 | 1 | } |
108 | | |
109 | | #include "case_main.h" |