/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/ccv_nnc_symbolic_graph_minimize.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "ccv_nnc.h" |
2 | | #include "ccv_nnc_easy.h" |
3 | | #include "ccv_nnc_internal.h" |
4 | | #include "ccv_internal.h" |
5 | | #include "_ccv_nnc_symbolic_graph.h" |
6 | | |
7 | | // MARK - Level-3.5 API |
8 | | |
9 | | int ccv_nnc_minimizer_saved_aux_size(const ccv_nnc_cmd_t minimizer) |
10 | 12.3k | { |
11 | 12.3k | int i, aux_size = -1; |
12 | 12.3k | uint64_t input_bitmask = 0x1; |
13 | 12.3k | uint64_t output_bitmask = 0x0; |
14 | 36.9k | for (i = 0; i < 62 && aux_size < 0; i++24.6k ) |
15 | 24.6k | { |
16 | 24.6k | input_bitmask |= ((uint64_t)1 << (i + 1)); |
17 | 24.6k | output_bitmask |= ((uint64_t)1 << i); |
18 | 24.6k | if (ccv_nnc_cmd_bitmask(minimizer, i + 2, i + 1, &input_bitmask, 1, &output_bitmask, 1)) |
19 | 12.3k | aux_size = i; |
20 | 24.6k | } |
21 | 12.3k | return aux_size; |
22 | 12.3k | } |
23 | | |
24 | | void ccv_nnc_symbolic_graph_minimize(ccv_nnc_symbolic_graph_t* const graph, const ccv_nnc_cmd_t minimizer, const ccv_nnc_tensor_symbol_t* const losses, const int loss_size, const ccv_nnc_tensor_symbol_t* const parameters, const int parameter_size, const ccv_nnc_tensor_symbol_t* const inputs, const int input_size, const ccv_nnc_graph_exec_symbol_t* const sources, const int source_size, const ccv_nnc_graph_exec_symbol_t* const destinations, const int destination_size, ccv_nnc_tensor_symbol_t* const gradients, ccv_nnc_tensor_symbol_t* const updated_parameters, ccv_nnc_tensor_symbol_map_t* const saved_aux, ccv_nnc_graph_exec_symbol_t* const graph_exec_symbols) |
25 | 3.25k | { |
26 | 3.25k | assert(parameter_size >= 0); |
27 | 3.25k | assert(loss_size > 0); |
28 | 3.25k | assert((inputs && input_size > 0) || (inputs == 0 && input_size <= 0)); |
29 | 3.25k | int i, j; |
30 | | // First, compute gradient. |
31 | 3.25k | if (inputs) |
32 | 2.23k | { |
33 | 2.23k | ccv_nnc_tensor_symbol_t* const ingrads = gradients ? gradients : ccmalloc0 (sizeof(ccv_nnc_tensor_symbol_t) * (parameter_size + input_size))0 ; |
34 | 2.23k | if (parameter_size > 0) |
35 | 2.22k | memcpy(ingrads, parameters, sizeof(ccv_nnc_tensor_symbol_t) * parameter_size); |
36 | 2.23k | memcpy(ingrads + parameter_size, inputs, sizeof(ccv_nnc_tensor_symbol_t) * input_size); |
37 | | // Parameters wont, but inputs might be zero length. |
38 | 4.47k | for (i = parameter_size; i < parameter_size + input_size; i++2.24k ) |
39 | 2.24k | if (ingrads[i].d >= 0) |
40 | 2.24k | { |
41 | 2.24k | const ccv_nnc_tensor_param_t params = ccv_nnc_tensor_symbol_params(graph, ingrads[i]); |
42 | 2.24k | if (params.dim[0] == 0) |
43 | 0 | ingrads[i] = NO_TENSOR_SYMBOL; |
44 | 2.24k | } |
45 | 2.23k | ccv_nnc_symbolic_graph_backward(graph, losses, loss_size, ingrads, parameter_size + input_size, sources, source_size, destinations, destination_size); |
46 | 2.23k | if (ingrads != gradients) |
47 | 0 | ccfree(ingrads); |
48 | 2.23k | } else if (1.02k parameter_size > 01.02k ) |
49 | 1.02k | ccv_nnc_symbolic_graph_backward(graph, losses, loss_size, parameters, parameter_size, sources, source_size, destinations, destination_size); |
50 | | // At most the minimizer accepts 62 additional parameters. |
51 | 3.25k | const int aux_size = ccv_nnc_minimizer_saved_aux_size(minimizer); |
52 | 3.25k | assert(aux_size >= 0); |
53 | 3.25k | ccv_nnc_tensor_symbol_t update_inputs[aux_size + 2]; |
54 | 3.25k | ccv_nnc_tensor_symbol_t update_outputs[aux_size + 1]; |
55 | 6.93k | for (i = 0; i < parameter_size; i++3.68k ) |
56 | 3.68k | if (parameters[i].d >= 0) |
57 | 3.68k | { |
58 | 3.68k | const ccv_nnc_tensor_symbol_t gradient = ccv_nnc_tensor_symbol_for_backward(graph, parameters[i]); |
59 | 3.68k | if (gradients) |
60 | 2.67k | gradients[i] = gradient; |
61 | 3.68k | const ccv_nnc_graph_exec_symbol_t graph_exec = ccv_nnc_graph_exec_symbol_for_backward(graph, gradient); |
62 | 3.68k | update_inputs[0] = gradient; |
63 | 3.68k | update_inputs[1] = parameters[i]; |
64 | 3.68k | const ccv_nnc_tensor_param_t info = ccv_nnc_tensor_symbol_params(graph, update_inputs[1]); |
65 | 3.68k | update_outputs[0] = updated_parameters[i] = ccv_nnc_tensor_symbol_new(graph, info, 0); |
66 | 7.28k | for (j = 0; j < aux_size; j++3.60k ) |
67 | 3.60k | { |
68 | 3.60k | update_inputs[2 + j] = saved_aux[i * aux_size + j].source = ccv_nnc_tensor_symbol_new(graph, info, 0); |
69 | 3.60k | update_outputs[1 + j] = saved_aux[i * aux_size + j].destination = ccv_nnc_tensor_symbol_new(graph, info, 0); |
70 | 3.60k | } |
71 | 3.68k | const ccv_nnc_graph_exec_symbol_t minimize = ccv_nnc_graph_exec_symbol_new(graph, minimizer, update_inputs, aux_size + 2, update_outputs, aux_size + 1, 0); |
72 | 3.68k | ccv_nnc_graph_exec_symbol_concat(graph, graph_exec, minimize); |
73 | 3.68k | graph_exec_symbols[i] = minimize; |
74 | 3.68k | } else { |
75 | 7 | if (gradients) |
76 | 7 | gradients[i] = NO_TENSOR_SYMBOL; |
77 | 7 | updated_parameters[i] = NO_TENSOR_SYMBOL; |
78 | 12 | for (j = 0; j < aux_size; j++5 ) |
79 | 5 | { |
80 | 5 | saved_aux[i * aux_size + j].source = NO_TENSOR_SYMBOL; |
81 | 5 | saved_aux[i * aux_size + j].destination = NO_TENSOR_SYMBOL; |
82 | 5 | } |
83 | 7 | graph_exec_symbols[i] = (ccv_nnc_graph_exec_symbol_t){ |
84 | 7 | .d = -1, |
85 | 7 | .graph = 0, |
86 | 7 | }; |
87 | 7 | } |
88 | 3.25k | if (gradients) |
89 | 4.49k | for (i = 0; 2.24k i < input_size; i++2.24k ) |
90 | 2.24k | { |
91 | 2.24k | const ccv_nnc_tensor_param_t params = ccv_nnc_tensor_symbol_params(graph, inputs[i]); |
92 | 2.24k | if (params.dim[0] == 0) |
93 | 0 | gradients[i + parameter_size] = NO_TENSOR_SYMBOL; |
94 | 2.24k | else |
95 | 2.24k | gradients[i + parameter_size] = ccv_nnc_tensor_symbol_for_backward(graph, inputs[i]); |
96 | 2.24k | } |
97 | 3.25k | } |