/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/_ccv_nnc_symbolic_graph.h
Line | Count | Source |
1 | | /********************************************************** |
2 | | * C-based/Cached/Core Computer Vision Library |
3 | | * Liu Liu, 2010-02-01 |
4 | | **********************************************************/ |
5 | | |
6 | | /********************************************************** |
7 | | * CCV - Neural Network Collection |
8 | | **********************************************************/ |
9 | | |
10 | | #ifndef GUARD_ccv_nnc_symbolic_graph_internal_h |
11 | | #define GUARD_ccv_nnc_symbolic_graph_internal_h |
12 | | |
13 | | #include "ccv_nnc.h" |
14 | | #include "ccv_nnc_internal.h" |
15 | | |
16 | | typedef struct { |
17 | | // Start for while loop handling |
18 | | int assign_ref; // Reference to the tensor that the value will be copied from (for parameter passing). Starts at 1. |
19 | | int r_assign_ref; // It is a reverse of the assign_ref. Starts at 1. |
20 | | int bypass_ref; // Some exec may not generate output for this tensor. In that case, use the content from tensor bypass (typical case for case..of). Starts at 1. |
21 | | int r_bypass_ref; // It is a reverse of the bypass_ref. Starts at 1. |
22 | | int p_ref; // Reference to the tensor number in its parent graph. Starts at 1. |
23 | | // End of while loop handling. |
24 | | int alias_ref; // Reference to the tensor. Starts at 1. |
25 | | int pair_ref; // Reference to its pair. Starts at 1. |
26 | | int flags; |
27 | | int ofs[CCV_NNC_MAX_DIM_ALLOC]; |
28 | | int stride[CCV_NNC_MAX_DIM_ALLOC]; |
29 | | ccv_array_t* s_ref; // Reference to the tensor number in its sub graphs, Starts at 1. |
30 | | char* name; |
31 | | ccv_nnc_tensor_param_t info; |
32 | | } ccv_nnc_tensor_symbol_info_t; |
33 | | |
34 | | enum { |
35 | | CCV_NNC_GRAPH_EXEC_CASE_OF_NO_BYPASS = 0x01, // If this flag is set, this case..of won't have any bypass. |
36 | | }; |
37 | | |
38 | | typedef struct { |
39 | | int input_size; |
40 | | int output_size; |
41 | | int graph_ref_size; |
42 | | int flags; // Mark this node as dead. Lower 16 bits is for internal use, such as mark as dead. Higher 16-bit can be set. |
43 | | int pair_ref; // Reference to its pair. Starts at 1. |
44 | | int* inputs; |
45 | | int* outputs; |
46 | | ccv_array_t* outgoings; // Outgoing nodes |
47 | | char* name; |
48 | | ccv_nnc_cmd_t cmd; |
49 | | ccv_nnc_hint_t hint; |
50 | | // Below are only relevant to sub-graph nodes (case_of, while). |
51 | | int _inline_graph_ref[2]; // Reference to the sub-graph. Starts at 1. |
52 | | int* _heap_graph_ref; |
53 | | union { |
54 | | struct { |
55 | | ccv_nnc_graph_case_of_f expr; |
56 | | const void* data; |
57 | | int flags; |
58 | | struct { |
59 | | int offset; |
60 | | int size; |
61 | | } argument; // range for which data as inputs from input section. |
62 | | } case_of; |
63 | | struct { |
64 | | ccv_nnc_graph_while_f expr; |
65 | | const void* data; |
66 | | int* inputs; |
67 | | int input_size; |
68 | | } p_while; |
69 | | }; |
70 | | } ccv_nnc_graph_exec_symbol_info_t; |
71 | | |
72 | | struct ccv_nnc_symbolic_graph_s { |
73 | | ccv_array_t* tensor_symbol_info; // A lit of info for tensor symbols. |
74 | | ccv_array_t* exec_symbol_info; // A list of info for exec symbols. |
75 | | // I think that I can be more explicit about which are sources and which are destinations. |
76 | | ccv_array_t* sources; |
77 | | ccv_array_t* destinations; |
78 | | // Some extra information piggy-back on symbolic graph struct. |
79 | | // Start for while loop handling |
80 | | ccv_array_t* sub_graphs; // A list of its sub-graphs (for while loop). |
81 | | struct ccv_nnc_symbolic_graph_s* pair; // The pair graph (only useful for backward prop graph). |
82 | | struct ccv_nnc_symbolic_graph_s* p; // The parent graph (if current one is a sub-graph). |
83 | | int p_idx; // Reference to the index in its parent graph's sub-graph array, Starts at 1. |
84 | | int exec_idx; // Reference to the index in its parent graph's exec (the graph exec), Starts at 1. |
85 | | // Why some of these I choose to be flat int* array, some of these I choose to be ccv_array_t? |
86 | | // for flat int* array, these are not going to be modified until next time call ccv_nnc_symbolic_graph_backward |
87 | | // for ccv_array_t, we can continue to modify what's inside. |
88 | | int breakpoint_size; |
89 | | ccv_nnc_graph_exec_symbol_t* breakpoints; |
90 | | // End of while loop handling. |
91 | | struct { |
92 | | int tensor; |
93 | | int exec; |
94 | | } reuse; // The reuse slot for tensor or graph exec symbols. |
95 | | // Start for backward (automatic differentiation) handling |
96 | | struct { |
97 | | int tensor_symbol_size; |
98 | | int* tensor_symbol_idx; |
99 | | int exec_symbol_size; |
100 | | int* exec_symbol_idx; |
101 | | } backward; |
102 | | // End of backward (automatic differentiation) handling. |
103 | | // For parallel, get duplicated tensors. |
104 | | struct { |
105 | | int count; |
106 | | int tensor_symbol_size; |
107 | | int* tensor_symbol_idx; |
108 | | int exec_symbol_size; |
109 | | int* exec_symbol_idx; |
110 | | } data_parallel; |
111 | | // Hooks |
112 | | struct { |
113 | | struct { |
114 | | ccv_nnc_tensor_symbol_new_hook_f func; |
115 | | void* context; |
116 | | } tensor_symbol_new; |
117 | | struct { |
118 | | ccv_nnc_tensor_symbol_alias_new_hook_f func; |
119 | | void* context; |
120 | | } tensor_symbol_alias_new; |
121 | | struct { |
122 | | ccv_nnc_graph_exec_symbol_new_hook_f func; |
123 | | void* context; |
124 | | } graph_exec_symbol_new; |
125 | | } hooks; |
126 | | }; |
127 | | |
128 | | typedef void(*ccv_nnc_arena_dispose_f)(void* ptr, void* userdata); |
129 | | typedef struct { |
130 | | void* ptr; |
131 | | void* userdata; |
132 | | ccv_nnc_arena_dispose_f dispose; |
133 | | } ccv_nnc_arena_disposer_t; |
134 | | |
135 | | struct ccv_nnc_tensor_arena_s { |
136 | | intptr_t graph_ref; // A value contains the pointer name of the graph. |
137 | | int sub_arena_size; |
138 | | struct ccv_nnc_tensor_arena_s** sub_arenas; // Corresponding to sub graphs. |
139 | | // This is a table of tensor references to real allocated tensors. |
140 | | int vt_tensor_size; |
141 | | ccv_nnc_tensor_t** vt_tensors; |
142 | | int* vt_alias_refs; // reference to which it is alias to. |
143 | | int* vt_alias_r_refs_p; // pointer to record which tensor this is aliased to. |
144 | | int* vt_alias_r_refs; // array to record which tensor this is aliased to. This is first created when bind a symbol. |
145 | | size_t* vt_sizes; // The size of each tensor. |
146 | | ccv_numeric_data_t* pb_vt_tensors; // pre-bindings for this vt_tensors, this is optional. |
147 | | struct { |
148 | | const ccv_nnc_symbolic_graph_compile_allocator_vtab_t* isa; |
149 | | struct { |
150 | | void* free; |
151 | | } context; |
152 | | } allocator; |
153 | | // This is the allocated non-continuous buffers. |
154 | | int buffer_size; |
155 | | struct { |
156 | | int type; // The type from tensor blocks. |
157 | | int pin_mem; // Whether this memory is pinned. |
158 | | uint64_t size; |
159 | | uint8_t* ptr; |
160 | | }* buffers; |
161 | | // Real allocated tensor header metadata (this is a mixed pool of ccv_tensor_t, ccv_tensor_view_t, |
162 | | // ccv_tensor_multiview_t, thus, it is aligned to a 16-byte boundary). |
163 | | ccv_array_t* tensor_metadata; |
164 | | ccv_array_t* m_tensor_idx; // The index into multi-view tensors in tensor_metadata. |
165 | | ccv_array_t* disposers; // Generic dispose structure that shares life-cycle with the arena. |
166 | | }; |
167 | | |
168 | | struct ccv_nnc_graph_exec_arena_s { |
169 | | intptr_t graph_ref; // A value contains the pointer name of the graph. |
170 | | int sub_arena_size; |
171 | | struct ccv_nnc_graph_exec_arena_s** sub_arenas; // Corresponding to sub graphs. |
172 | | ccv_nnc_graph_exec_t source; |
173 | | ccv_nnc_graph_exec_t destination; |
174 | | int graph_exec_size; |
175 | | ccv_nnc_graph_exec_t graph_execs[1]; |
176 | | }; |
177 | | |
178 | 1 | #define CCV_NNC_ENCODE_WHILE_COUNT_SYMBOL(d) ((int)((~(uint32_t)d) << 4 | 0xe)) |
179 | 40 | #define CCV_NNC_DECODE_WHILE_COUNT_SYMBOL(symbol) ((~(uint32_t)(symbol)) >> 4) |
180 | | |
181 | | inline static void ccv_array_replace_unique_int(ccv_array_t* ints, const int idx, const int outgoing) |
182 | 8.59k | { |
183 | 8.59k | int i; |
184 | 8.59k | int flag = 0; |
185 | 17.2k | for (i = 0; i < ints->rnum;) |
186 | 8.60k | { |
187 | 8.60k | if (*(int*)ccv_array_get(ints, i) == idx) |
188 | 4.28k | { |
189 | 4.28k | if (flag) |
190 | 4 | { |
191 | 4 | if (i < ints->rnum - 1) |
192 | 4 | *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1); |
193 | 4 | --ints->rnum; |
194 | 4 | continue; |
195 | 4 | } |
196 | 4.28k | *(int*)ccv_array_get(ints, i) = outgoing; |
197 | 4.28k | flag = 1; |
198 | 4.31k | } else if (*(int*)ccv_array_get(ints, i) == outgoing) { |
199 | | // Remove this from the list. |
200 | 4.24k | if (flag) |
201 | 0 | { |
202 | 0 | if (i < ints->rnum - 1) |
203 | 0 | *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1); |
204 | 0 | --ints->rnum; |
205 | 0 | continue; |
206 | 0 | } |
207 | 4.24k | flag = 1; |
208 | 4.24k | } |
209 | 8.60k | ++i; |
210 | 8.60k | } |
211 | 8.59k | if (!flag) |
212 | 70 | ccv_array_push(ints, &outgoing); |
213 | 8.59k | } Unexecuted instantiation: ccv_nnc_tensor_io.c:ccv_array_replace_unique_int Unexecuted instantiation: ccv_nnc_symbolic_graph.c:ccv_array_replace_unique_int Unexecuted instantiation: ccv_nnc_symbolic_graph_io.c:ccv_array_replace_unique_int Unexecuted instantiation: ccv_nnc_symbolic_graph_compile.c:ccv_array_replace_unique_int ccv_nnc_symbolic_graph_backward.c:ccv_array_replace_unique_int Line | Count | Source | 182 | 8.58k | { | 183 | 8.58k | int i; | 184 | 8.58k | int flag = 0; | 185 | 17.1k | for (i = 0; i < ints->rnum;) | 186 | 8.56k | { | 187 | 8.56k | if (*(int*)ccv_array_get(ints, i) == idx) | 188 | 4.28k | { | 189 | 4.28k | if (flag) | 190 | 0 | { | 191 | 0 | if (i < ints->rnum - 1) | 192 | 0 | *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1); | 193 | 0 | --ints->rnum; | 194 | 0 | continue; | 195 | 0 | } | 196 | 4.28k | *(int*)ccv_array_get(ints, i) = outgoing; | 197 | 4.28k | flag = 1; | 198 | 4.28k | } else if (*(int*)ccv_array_get(ints, i) == outgoing) { | 199 | | // Remove this from the list. | 200 | 4.23k | if (flag) | 201 | 0 | { | 202 | 0 | if (i < ints->rnum - 1) | 203 | 0 | *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1); | 204 | 0 | --ints->rnum; | 205 | 0 | continue; | 206 | 0 | } | 207 | 4.23k | flag = 1; | 208 | 4.23k | } | 209 | 8.56k | ++i; | 210 | 8.56k | } | 211 | 8.58k | if (!flag) | 212 | 66 | ccv_array_push(ints, &outgoing); | 213 | 8.58k | } |
Unexecuted instantiation: ccv_nnc_symbolic_graph_while.c:ccv_array_replace_unique_int Unexecuted instantiation: ccv_nnc_symbolic_graph_case_of.c:ccv_array_replace_unique_int Unexecuted instantiation: ccv_nnc_symbolic_graph_minimize.c:ccv_array_replace_unique_int ccv_nnc_symbolic_graph_parallel.c:ccv_array_replace_unique_int Line | Count | Source | 182 | 16 | { | 183 | 16 | int i; | 184 | 16 | int flag = 0; | 185 | 60 | for (i = 0; i < ints->rnum;) | 186 | 44 | { | 187 | 44 | if (*(int*)ccv_array_get(ints, i) == idx) | 188 | 8 | { | 189 | 8 | if (flag) | 190 | 4 | { | 191 | 4 | if (i < ints->rnum - 1) | 192 | 4 | *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1); | 193 | 4 | --ints->rnum; | 194 | 4 | continue; | 195 | 4 | } | 196 | 4 | *(int*)ccv_array_get(ints, i) = outgoing; | 197 | 4 | flag = 1; | 198 | 36 | } else if (*(int*)ccv_array_get(ints, i) == outgoing) { | 199 | | // Remove this from the list. | 200 | 8 | if (flag) | 201 | 0 | { | 202 | 0 | if (i < ints->rnum - 1) | 203 | 0 | *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1); | 204 | 0 | --ints->rnum; | 205 | 0 | continue; | 206 | 0 | } | 207 | 8 | flag = 1; | 208 | 8 | } | 209 | 40 | ++i; | 210 | 40 | } | 211 | 16 | if (!flag) | 212 | 4 | ccv_array_push(ints, &outgoing); | 213 | 16 | } |
Unexecuted instantiation: ccv_nnc_symbolic_graph_simplify.c:ccv_array_replace_unique_int Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_compression.c:ccv_array_replace_unique_int Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_reduction.c:ccv_array_replace_unique_int Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_array_replace_unique_int Unexecuted instantiation: ccv_nnc_symbolic_graph_chain_decomposition.c:ccv_array_replace_unique_int |
214 | | |
215 | | void ccv_nnc_symbolic_graph_symbol_infer(const ccv_nnc_symbolic_graph_t* const symbolic_graph, const ccv_nnc_graph_visit_t* const visit, 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, const ccv_nnc_tensor_symbol_info_t* const p_tensor_symbol_info, const int p_tensor_symbol_info_size, ccv_nnc_tensor_symbol_info_t* const tensor_symbol_info, ccv_nnc_graph_exec_symbol_info_t* const exec_symbol_info); |
216 | | |
217 | | int ccv_nnc_over_tensor_symbol_aliases(const ccv_nnc_tensor_symbol_info_t* const tensor_a, const ccv_nnc_tensor_symbol_info_t* const tensor_b); |
218 | | int ccv_nnc_tensor_symbol_map_raw(ccv_nnc_symbolic_graph_t* const graph, const ccv_nnc_tensor_symbol_t symbol); |
219 | | |
220 | | typedef struct { |
221 | | int flags; |
222 | | int* chain_ids; |
223 | | int* chain_pos; |
224 | | ccv_sparse_matrix_t* deps; |
225 | | } ccv_nnc_exec_dep_t; |
226 | | |
227 | | ccv_nnc_exec_dep_t ccv_nnc_exec_dep_new(const ccv_nnc_symbolic_graph_t* const graph, const ccv_nnc_graph_visit_t* const visit); |
228 | | void ccv_nnc_exec_dep_free(const ccv_nnc_exec_dep_t exec_dep); |
229 | | |
230 | | inline static int ccv_nnc_exec_dep_hop(const ccv_nnc_exec_dep_t exec_dep, const int d, ccv_sparse_matrix_vector_t* const vector, const int dd) |
231 | 0 | { |
232 | | // Check if dd is d's ancestor. |
233 | 0 | const int dd_chain_id = exec_dep.chain_ids[dd]; |
234 | 0 | const int dd_chain_pos = exec_dep.chain_pos[dd]; |
235 | 0 | if (exec_dep.chain_ids[d] == dd_chain_id) |
236 | 0 | return exec_dep.chain_pos[d] - dd_chain_pos; |
237 | 0 | const ccv_numeric_data_t cell = vector ? ccv_get_sparse_matrix_cell_from_vector(exec_dep.deps, vector, dd_chain_id) : ccv_get_sparse_matrix_cell(exec_dep.deps, d, dd_chain_id); |
238 | | // Check if the chain pos is greater than or equal to dd_chain_pos. If it is, it is an ancestor. |
239 | 0 | if (cell.i32 && cell.i32[0] > 0 && cell.i32[0] >= dd_chain_pos) |
240 | 0 | return cell.i32[0] - dd_chain_pos + cell.i32[1]; |
241 | 0 | return -1; |
242 | 0 | } Unexecuted instantiation: ccv_nnc_tensor_io.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph_io.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph_compile.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph_backward.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph_while.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph_case_of.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph_minimize.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph_parallel.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph_simplify.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_compression.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_reduction.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_nnc_exec_dep_hop Unexecuted instantiation: ccv_nnc_symbolic_graph_chain_decomposition.c:ccv_nnc_exec_dep_hop |
243 | | |
244 | | inline static int ccv_nnc_exec_dep_check(const ccv_nnc_exec_dep_t exec_dep, const int d, ccv_sparse_matrix_vector_t* const vector, const int dd) |
245 | 81 | { |
246 | | // Check if dd is d's ancestor. |
247 | 81 | const int dd_chain_id = exec_dep.chain_ids[dd]; |
248 | 81 | const int dd_chain_pos = exec_dep.chain_pos[dd]; |
249 | 81 | if (exec_dep.chain_ids[d] == dd_chain_id) |
250 | 38 | return exec_dep.chain_pos[d] > dd_chain_pos; |
251 | 43 | if (vector == (ccv_sparse_matrix_vector_t*)1) // Special sentinel value to say that we don't have vector found. |
252 | 22 | return 0; |
253 | 21 | const ccv_numeric_data_t cell = vector ? ccv_get_sparse_matrix_cell_from_vector(exec_dep.deps, vector, dd_chain_id) : ccv_get_sparse_matrix_cell(exec_dep.deps, d, dd_chain_id)0 ; |
254 | | // Check if the chain pos is greater than or equal to dd_chain_pos. If it is, it is an ancestor. |
255 | 21 | if (cell.i32 && cell.i32[0] > 010 ) |
256 | 10 | return cell.i32[0] >= dd_chain_pos; |
257 | 11 | return 0; |
258 | 21 | } Unexecuted instantiation: ccv_nnc_tensor_io.c:ccv_nnc_exec_dep_check Unexecuted instantiation: ccv_nnc_symbolic_graph.c:ccv_nnc_exec_dep_check Unexecuted instantiation: ccv_nnc_symbolic_graph_io.c:ccv_nnc_exec_dep_check Unexecuted instantiation: ccv_nnc_symbolic_graph_compile.c:ccv_nnc_exec_dep_check Unexecuted instantiation: ccv_nnc_symbolic_graph_backward.c:ccv_nnc_exec_dep_check Unexecuted instantiation: ccv_nnc_symbolic_graph_while.c:ccv_nnc_exec_dep_check Unexecuted instantiation: ccv_nnc_symbolic_graph_case_of.c:ccv_nnc_exec_dep_check Unexecuted instantiation: ccv_nnc_symbolic_graph_minimize.c:ccv_nnc_exec_dep_check Unexecuted instantiation: ccv_nnc_symbolic_graph_parallel.c:ccv_nnc_exec_dep_check Unexecuted instantiation: ccv_nnc_symbolic_graph_simplify.c:ccv_nnc_exec_dep_check Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_compression.c:ccv_nnc_exec_dep_check Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_reduction.c:ccv_nnc_exec_dep_check ccv_cnnp_model_gradient_checkpointing.c:ccv_nnc_exec_dep_check Line | Count | Source | 245 | 81 | { | 246 | | // Check if dd is d's ancestor. | 247 | 81 | const int dd_chain_id = exec_dep.chain_ids[dd]; | 248 | 81 | const int dd_chain_pos = exec_dep.chain_pos[dd]; | 249 | 81 | if (exec_dep.chain_ids[d] == dd_chain_id) | 250 | 38 | return exec_dep.chain_pos[d] > dd_chain_pos; | 251 | 43 | if (vector == (ccv_sparse_matrix_vector_t*)1) // Special sentinel value to say that we don't have vector found. | 252 | 22 | return 0; | 253 | 21 | const ccv_numeric_data_t cell = vector ? ccv_get_sparse_matrix_cell_from_vector(exec_dep.deps, vector, dd_chain_id) : ccv_get_sparse_matrix_cell(exec_dep.deps, d, dd_chain_id)0 ; | 254 | | // Check if the chain pos is greater than or equal to dd_chain_pos. If it is, it is an ancestor. | 255 | 21 | if (cell.i32 && cell.i32[0] > 010 ) | 256 | 10 | return cell.i32[0] >= dd_chain_pos; | 257 | 11 | return 0; | 258 | 21 | } |
Unexecuted instantiation: ccv_nnc_symbolic_graph_chain_decomposition.c:ccv_nnc_exec_dep_check |
259 | | |
260 | | #endif |
261 | | |