/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/_ccv_cnnp_model.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_cnnp_model_internal_h |
11 | | #define GUARD_ccv_cnnp_model_internal_h |
12 | | |
13 | | #include "ccv_nnc.h" |
14 | | #include "_ccv_nnc_stream.h" |
15 | | #include "_ccv_nnc_xpu_alloc.h" |
16 | | #include "3rdparty/khash/khash.h" |
17 | | |
18 | | typedef void(*ccv_cnnp_cmd_updater_f)(void* const context, const ccv_nnc_graph_exec_symbol_t symbol, const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint); |
19 | | typedef void(*ccv_cnnp_add_to_array_f)(void* const context, const ccv_nnc_tensor_symbol_t symbol, const int is_trainable); |
20 | | /** |
21 | | * This is the virtual table of the model. |
22 | | */ |
23 | | typedef struct { |
24 | | void (*deinit)(ccv_cnnp_model_t* const self); /**< It can be nil. */ |
25 | | void (*dealloc)(ccv_cnnp_model_t* const self); /**< It can be nil. This is different from deinit because you should only free other models in this method. */ |
26 | | void (*build)(ccv_cnnp_model_t* const self, ccv_nnc_symbolic_graph_t* const graph, const ccv_nnc_tensor_symbol_t* const inputs, const int input_size, ccv_nnc_tensor_symbol_t* const outputs, const int output_size); /**< Call this graph to build computation. No need to specify input size or output size, as it is defined along in the model already. */ |
27 | | void (*init_states)(ccv_cnnp_model_t* const self, ccv_nnc_symbolic_graph_t* const graph, const ccv_cnnp_state_initializer_f initializer, void* const context); /**< This is called to init ccv_nnc_tensor_symbol_t with a exec. */ |
28 | | void (*add_to_parameter)(ccv_cnnp_model_t* const self, const ccv_cnnp_add_to_array_f add_to_array, void* const parameters, const int is_trainable); /**< This is called to add ccv_nnc_tensor_symbol_t to as list of parameters. */ |
29 | | void (*add_to_output)(ccv_cnnp_model_t* const self, const ccv_cnnp_add_to_array_f add_to_array, void* const outputs); /**< This is called to add ccv_nnc_tensor_symbol_t to as list of outputs for retention. The final outputs are already added. This method is optional for any additional values we want to retain. */ |
30 | | ccv_cnnp_model_t* (*copy)(const ccv_cnnp_model_t* const self, void* const context); /**< This is called to make a deep copy of itself. */ |
31 | | void (*set_is_test)(ccv_cnnp_model_t* const self, const int is_test, const ccv_cnnp_cmd_updater_f updater, void* const context); /**< This is called when it is switched between test or training. */ |
32 | | void (*add_to_parameter_indices)(ccv_cnnp_model_t* const self, const int index, ccv_array_t* const parameter_indices); /**< This is called when we try to get parameter indices out of a given model */ |
33 | | void (*notify)(const ccv_cnnp_model_t* const self, const int tag, void* const payload); /**< This is called when we want to notify something to this model. */ |
34 | | } ccv_cnnp_model_vtab_t; |
35 | | |
36 | | struct ccv_cnnp_model_io_s { |
37 | | int param_ref; // Reference to parameter in the model, starts with 1. 0 means no such thing. |
38 | | int param_sel; // Selector to parameter in the model, starts with 1. 0 means no selector. |
39 | | int visit; // Temporary bits stored in the ccv_cnnp_model_io_t object, whoever uses it should clean it up. |
40 | | ccv_cnnp_model_t* model; // Reference back to the model who holds it. This is required because the model is the one whole holds the io. |
41 | | ccv_array_t* incomings; // Array of ccv_cnnp_model_io_t. The order is important because it impacts the order of symbols. |
42 | | ccv_array_t* dependencies; // Array of ccv_cnnp_model_io_t. |
43 | | int dependents; // Number of dependents. |
44 | | ccv_array_t* outgoings; // Array of ccv_cnnp_model_io_t. |
45 | | ccv_nnc_tensor_symbol_t* outputs; // This is different from the outputs from a model. A model could be reused, causing the outputs on that model to be the most recent one. This keeps the outputs of each. |
46 | | }; |
47 | | |
48 | | enum { |
49 | | CCV_CNNP_MODEL_GRAPH_FIT_MODE, // This mode computes loss, backprop, and then apply gradients. |
50 | | CCV_CNNP_MODEL_GRAPH_MULTISTAGE_MODE_NO_GRAD, // This mode allows you to only use ccv_cnnp_model_evaluate (others require gradient). |
51 | | CCV_CNNP_MODEL_GRAPH_MULTISTAGE_MODE, // This mode allows you to use ccv_cnnp_model_evaluate, ccv_cnnp_model_backward, ccv_cnnp_model_apply_gradients separately. |
52 | | }; |
53 | | |
54 | | enum { |
55 | | CCV_CNNP_COMPILED_DATA_GRADIENT_NONE, |
56 | | CCV_CNNP_COMPILED_DATA_GRADIENT_TRAINABLES, |
57 | | CCV_CNNP_COMPILED_DATA_GRADIENT_TRAINABLES_AND_INPUTS, |
58 | | }; |
59 | | |
60 | | enum { |
61 | | CCV_CNNP_REWIND_GRAPH_EXEC, |
62 | | CCV_CNNP_REWIND_TENSOR, |
63 | | }; |
64 | | |
65 | | typedef struct { |
66 | | int type; |
67 | | union { |
68 | | ccv_nnc_tensor_symbol_t tensor; |
69 | | ccv_nnc_graph_exec_symbol_t graph_exec; |
70 | | }; |
71 | | } ccv_cnnp_rewind_symbol_t; |
72 | | |
73 | 1.64k | #define CCV_NNC_TENSOR(tv) ((ccv_nnc_tensor_t*)((uintptr_t)(tv) & ~(uintptr_t)1)) |
74 | 930 | #define CCV_NNC_INIT_V(v) ((uint32_t*)((uintptr_t)(v) & ~(uintptr_t)1)) |
75 | | |
76 | | // This contains relevant information after model compilation. |
77 | | typedef struct { |
78 | | int graph_mode; |
79 | | int gradient_mode; // Have init gradient graph. |
80 | | int is_test; |
81 | | int stream_type; |
82 | | int parallel_count; // Physical parameter / internal tensor count. |
83 | | int outgrad_size; |
84 | | uint64_t disable_outgrad; |
85 | | ccv_nnc_symbolic_graph_compile_param_t compile_params; |
86 | | ccv_nnc_xpu_alloc_t xpu_alloc; |
87 | | ccv_nnc_graph_t* graph; |
88 | | ccv_nnc_tensor_arena_t* tensor_arena; |
89 | | ccv_nnc_graph_exec_arena_t* graph_exec_arena; |
90 | | khash_t(stream_map)* stream_map; // Keeps track of streams on both GPU / CPU and devices so it can be used properly during execution. |
91 | | ccv_array_t* parameters; |
92 | | uint64_t* parameter_flags; |
93 | | ccv_array_t* internals; // Additional symbols need to retain. |
94 | | ccv_nnc_tensor_symbol_t* gradients; |
95 | | ccv_nnc_tensor_symbol_t* outgrads; |
96 | | ccv_nnc_tensor_symbol_t* updated_parameters; |
97 | | ccv_nnc_graph_exec_symbol_t* update_nodes; |
98 | | ccv_nnc_tensor_symbol_map_t* saved_aux; |
99 | | ccv_array_t* rewindables; |
100 | | ccv_array_t* gradient_checkpoints; |
101 | | struct { |
102 | | int size; |
103 | | uint32_t* v; // If the last is 1, we know it is incomplete (thus, the tensors_init_1 hasn't been called yet. This is to save RAM usage. |
104 | | } tensors_init; |
105 | | struct { |
106 | | ccv_nnc_tensor_t** internals; // Additional need to retained tensors. |
107 | | ccv_nnc_tensor_t** parameters; |
108 | | ccv_nnc_tensor_t** gradients; |
109 | | ccv_nnc_tensor_t** accum_gradients; |
110 | | } tensors; |
111 | | struct { |
112 | | ccv_array_t* parameters; |
113 | | ccv_array_t* internals; |
114 | | } ids; |
115 | | struct { |
116 | | int to_op_size; |
117 | | int to_size; |
118 | | ccv_nnc_graph_exec_t* to_ops; |
119 | | ccv_nnc_graph_exec_symbol_t* tos; |
120 | | ccv_nnc_graph_static_schedule_t* schedule; // The partial schedule for running evaluate step. |
121 | | } evaluate; // Data related to ccv_cnnp_model_evaluate |
122 | | struct { |
123 | | int count; // Called backward how many times. Starting with 0. |
124 | | int from_op_size; |
125 | | ccv_nnc_graph_exec_t* from_ops; // These are the ops in the main graph. |
126 | | int to_size; |
127 | | ccv_nnc_graph_exec_symbol_t* tos; |
128 | | ccv_nnc_graph_t* accum; // The graph to accumulate gradients. |
129 | | ccv_nnc_tensor_arena_t* tensor_arena; |
130 | | ccv_nnc_graph_exec_arena_t* graph_exec_arena; |
131 | | ccv_nnc_tensor_symbol_t* gradients; // The new gradients. |
132 | | ccv_nnc_tensor_symbol_t* accum_gradients; // The old accumulate gradients. |
133 | | ccv_nnc_tensor_symbol_t* updated_accum_gradients; // The new accumulate gradients. |
134 | | ccv_nnc_graph_static_schedule_t* schedule; // The partial schedule for running backward step. |
135 | | } backward; |
136 | | struct { |
137 | | ccv_nnc_graph_t* graph; |
138 | | ccv_nnc_tensor_arena_t* tensor_arena; |
139 | | ccv_nnc_graph_exec_arena_t* graph_exec_arena; |
140 | | } apply_gradients; |
141 | | struct { |
142 | | ccv_nnc_cmd_t minimizer; |
143 | | ccv_array_t* parameters; |
144 | | int max_saved_aux_size; |
145 | | } minimize; |
146 | | ccv_nnc_cmd_t loss; |
147 | | ccv_nnc_tensor_symbol_t* f; |
148 | | ccv_nnc_tensor_symbol_t fits[1]; |
149 | | } ccv_cnnp_compiled_data_t; |
150 | | |
151 | | struct ccv_cnnp_model_s { |
152 | | const ccv_cnnp_model_vtab_t* isa; |
153 | | int input_size; // This is the best effort number, mostly just for subclass to use. |
154 | | int output_size; |
155 | | int max_stream_count; |
156 | | int deinit_state; // If it is 1, it is already deinit. |
157 | | ccv_array_t* io; // The opaque io that can be nil. |
158 | | ccv_array_t* parameter_indices; // The indexes for parameters in the final model. |
159 | | ccv_nnc_symbolic_graph_t* graph; |
160 | | ccv_nnc_tensor_symbol_t* inputs; // Unlike outputs, which is not dynamically allocated, inputs is dynamically allocated, and may be 0. |
161 | | ccv_nnc_tensor_symbol_t* outputs; |
162 | | char* name; |
163 | | struct { |
164 | | ccv_cnnp_model_notify_f func; |
165 | | void* context; |
166 | | } notify_hook; |
167 | | ccv_cnnp_compiled_data_t* compiled_data; |
168 | | int parallel_count; // How many parallel devices. |
169 | | int memory_compression; // Whether to enable memory compression for training phase. |
170 | | int gradient_checkpointing; // Whether to enable gradient checkpointing for training phase. |
171 | | int is_trainable; // Whether this model can be trained or not. |
172 | | int memory_reduction; // Whether to enable memory reduction techniques for training phase. |
173 | | int exec_flags; // The flags to be applied to the execution nodes. |
174 | | size_t workspace_size; // Set the default workspace size. |
175 | | struct { |
176 | | ccv_cnnp_model_io_reader_f reader; |
177 | | ccv_cnnp_model_io_writer_f writer; |
178 | | } rw; |
179 | | void* data; // Temporary storage for some internal functions. |
180 | | }; |
181 | | |
182 | | KHASH_MAP_INIT_STR(ccv_cnnp_model_name_bank, int) |
183 | | |
184 | | typedef struct { |
185 | | int sequence; |
186 | | khash_t(ccv_cnnp_model_name_bank)* bank; |
187 | | const char* name; |
188 | | } ccv_cnnp_model_name_t; |
189 | | |
190 | | typedef struct { |
191 | | int it; |
192 | | ccv_cnnp_model_t* model; |
193 | | khash_t(ccv_cnnp_model_name_bank)* bank; |
194 | | ccv_array_t* sequences; |
195 | | } ccv_cnnp_model_sequence_t; |
196 | | |
197 | | static inline void ccv_cnnp_model_push(ccv_cnnp_model_t* const self, ccv_cnnp_model_sequence_t* const model_sequence) |
198 | 2.78k | { |
199 | | // Reset to 0. |
200 | 2.78k | if (!model_sequence->sequences) |
201 | 2.30k | model_sequence->sequences = ccv_array_new(sizeof(ccv_cnnp_model_name_t), 1, 0); |
202 | 2.78k | khash_t(ccv_cnnp_model_name_bank)* bank = model_sequence->sequences->rnum > 0 ? ((ccv_cnnp_model_name_t*)215 ccv_array_get215 (model_sequence->sequences, model_sequence->sequences->rnum - 1))->bank : model_sequence->bank2.56k ; |
203 | 2.78k | int ret; |
204 | 2.78k | khiter_t k = kh_put(ccv_cnnp_model_name_bank, bank, self->name ? self->name : "", &ret); |
205 | 2.78k | int sequence; |
206 | 2.78k | if (ret != 0) |
207 | 2.50k | sequence = kh_val(bank, k) = 0; |
208 | 273 | else |
209 | 273 | sequence = ++kh_val(bank, k); |
210 | 2.78k | ccv_cnnp_model_name_t name = { |
211 | 2.78k | .bank = kh_init(ccv_cnnp_model_name_bank), |
212 | 2.78k | .name = self->name, |
213 | 2.78k | .sequence = sequence, |
214 | 2.78k | }; |
215 | 2.78k | ccv_array_push(model_sequence->sequences, &name); |
216 | 2.78k | model_sequence->model = self; |
217 | 2.78k | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_cnnp_model_push ccv_cnnp_model.c:ccv_cnnp_model_push Line | Count | Source | 198 | 1.25k | { | 199 | | // Reset to 0. | 200 | 1.25k | if (!model_sequence->sequences) | 201 | 1.25k | model_sequence->sequences = ccv_array_new(sizeof(ccv_cnnp_model_name_t), 1, 0); | 202 | 1.25k | khash_t(ccv_cnnp_model_name_bank)* bank = model_sequence->sequences->rnum > 0 ? ((ccv_cnnp_model_name_t*)0 ccv_array_get0 (model_sequence->sequences, model_sequence->sequences->rnum - 1))->bank : model_sequence->bank; | 203 | 1.25k | int ret; | 204 | 1.25k | khiter_t k = kh_put(ccv_cnnp_model_name_bank, bank, self->name ? self->name : "", &ret); | 205 | 1.25k | int sequence; | 206 | 1.25k | if (ret != 0) | 207 | 1.25k | sequence = kh_val(bank, k) = 0; | 208 | 0 | else | 209 | 0 | sequence = ++kh_val(bank, k); | 210 | 1.25k | ccv_cnnp_model_name_t name = { | 211 | 1.25k | .bank = kh_init(ccv_cnnp_model_name_bank), | 212 | 1.25k | .name = self->name, | 213 | 1.25k | .sequence = sequence, | 214 | 1.25k | }; | 215 | 1.25k | ccv_array_push(model_sequence->sequences, &name); | 216 | 1.25k | model_sequence->model = self; | 217 | 1.25k | } |
Unexecuted instantiation: ccv_cnnp_model_io.c:ccv_cnnp_model_push ccv_cnnp_model_core.c:ccv_cnnp_model_push Line | Count | Source | 198 | 1.52k | { | 199 | | // Reset to 0. | 200 | 1.52k | if (!model_sequence->sequences) | 201 | 1.04k | model_sequence->sequences = ccv_array_new(sizeof(ccv_cnnp_model_name_t), 1, 0); | 202 | 1.52k | khash_t(ccv_cnnp_model_name_bank)* bank = model_sequence->sequences->rnum > 0 ? ((ccv_cnnp_model_name_t*)215 ccv_array_get215 (model_sequence->sequences, model_sequence->sequences->rnum - 1))->bank : model_sequence->bank1.31k ; | 203 | 1.52k | int ret; | 204 | 1.52k | khiter_t k = kh_put(ccv_cnnp_model_name_bank, bank, self->name ? self->name : "", &ret); | 205 | 1.52k | int sequence; | 206 | 1.52k | if (ret != 0) | 207 | 1.25k | sequence = kh_val(bank, k) = 0; | 208 | 273 | else | 209 | 273 | sequence = ++kh_val(bank, k); | 210 | 1.52k | ccv_cnnp_model_name_t name = { | 211 | 1.52k | .bank = kh_init(ccv_cnnp_model_name_bank), | 212 | 1.52k | .name = self->name, | 213 | 1.52k | .sequence = sequence, | 214 | 1.52k | }; | 215 | 1.52k | ccv_array_push(model_sequence->sequences, &name); | 216 | 1.52k | model_sequence->model = self; | 217 | 1.52k | } |
Unexecuted instantiation: ccv_cnnp_model_addons.c:ccv_cnnp_model_push Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_cnnp_model_push |
218 | | |
219 | | static inline void ccv_cnnp_model_pop(const ccv_cnnp_model_t* const self, ccv_cnnp_model_sequence_t* const model_sequence) |
220 | 2.78k | { |
221 | 2.78k | khash_t(ccv_cnnp_model_name_bank)* const bank = ((ccv_cnnp_model_name_t*)ccv_array_get(model_sequence->sequences, model_sequence->sequences->rnum - 1))->bank; |
222 | 2.78k | kh_destroy(ccv_cnnp_model_name_bank, bank); |
223 | 2.78k | --model_sequence->sequences->rnum; |
224 | 2.78k | assert(model_sequence->sequences->rnum >= 0); |
225 | 2.78k | model_sequence->model = 0; |
226 | 2.78k | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_cnnp_model_pop ccv_cnnp_model.c:ccv_cnnp_model_pop Line | Count | Source | 220 | 1.25k | { | 221 | 1.25k | khash_t(ccv_cnnp_model_name_bank)* const bank = ((ccv_cnnp_model_name_t*)ccv_array_get(model_sequence->sequences, model_sequence->sequences->rnum - 1))->bank; | 222 | 1.25k | kh_destroy(ccv_cnnp_model_name_bank, bank); | 223 | 1.25k | --model_sequence->sequences->rnum; | 224 | 1.25k | assert(model_sequence->sequences->rnum >= 0); | 225 | 1.25k | model_sequence->model = 0; | 226 | 1.25k | } |
Unexecuted instantiation: ccv_cnnp_model_io.c:ccv_cnnp_model_pop ccv_cnnp_model_core.c:ccv_cnnp_model_pop Line | Count | Source | 220 | 1.52k | { | 221 | 1.52k | khash_t(ccv_cnnp_model_name_bank)* const bank = ((ccv_cnnp_model_name_t*)ccv_array_get(model_sequence->sequences, model_sequence->sequences->rnum - 1))->bank; | 222 | 1.52k | kh_destroy(ccv_cnnp_model_name_bank, bank); | 223 | 1.52k | --model_sequence->sequences->rnum; | 224 | 1.52k | assert(model_sequence->sequences->rnum >= 0); | 225 | 1.52k | model_sequence->model = 0; | 226 | 1.52k | } |
Unexecuted instantiation: ccv_cnnp_model_addons.c:ccv_cnnp_model_pop Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_cnnp_model_pop |
227 | | |
228 | | static inline ccv_cnnp_model_t* _ccv_cnnp_model_copy(const ccv_cnnp_model_t* const model, void* const context) |
229 | 4.30k | { |
230 | 4.30k | assert(model->isa->copy); |
231 | 4.30k | ccv_cnnp_model_t* const copy = model->isa->copy(model, context); |
232 | 4.30k | copy->parallel_count = model->parallel_count; |
233 | 4.30k | copy->memory_compression = model->memory_compression; |
234 | 4.30k | copy->memory_reduction = model->memory_reduction; |
235 | 4.30k | copy->max_stream_count = model->max_stream_count; |
236 | 4.30k | copy->gradient_checkpointing = model->gradient_checkpointing; |
237 | 4.30k | return copy; |
238 | 4.30k | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:_ccv_cnnp_model_copy ccv_cnnp_model.c:_ccv_cnnp_model_copy Line | Count | Source | 229 | 2.20k | { | 230 | 2.20k | assert(model->isa->copy); | 231 | 2.20k | ccv_cnnp_model_t* const copy = model->isa->copy(model, context); | 232 | 2.20k | copy->parallel_count = model->parallel_count; | 233 | 2.20k | copy->memory_compression = model->memory_compression; | 234 | 2.20k | copy->memory_reduction = model->memory_reduction; | 235 | 2.20k | copy->max_stream_count = model->max_stream_count; | 236 | 2.20k | copy->gradient_checkpointing = model->gradient_checkpointing; | 237 | 2.20k | return copy; | 238 | 2.20k | } |
Unexecuted instantiation: ccv_cnnp_model_io.c:_ccv_cnnp_model_copy ccv_cnnp_model_core.c:_ccv_cnnp_model_copy Line | Count | Source | 229 | 2.09k | { | 230 | 2.09k | assert(model->isa->copy); | 231 | 2.09k | ccv_cnnp_model_t* const copy = model->isa->copy(model, context); | 232 | 2.09k | copy->parallel_count = model->parallel_count; | 233 | 2.09k | copy->memory_compression = model->memory_compression; | 234 | 2.09k | copy->memory_reduction = model->memory_reduction; | 235 | 2.09k | copy->max_stream_count = model->max_stream_count; | 236 | 2.09k | copy->gradient_checkpointing = model->gradient_checkpointing; | 237 | 2.09k | return copy; | 238 | 2.09k | } |
Unexecuted instantiation: ccv_cnnp_model_addons.c:_ccv_cnnp_model_copy Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:_ccv_cnnp_model_copy |
239 | | |
240 | | static inline void ccv_cnnp_model_copy_name(ccv_cnnp_model_t* const self, const char* const name) |
241 | 5.33k | { |
242 | 5.33k | if (name) |
243 | 241 | { |
244 | 241 | const size_t len = strnlen(name, 63); |
245 | 241 | const size_t n = len + 1; |
246 | 241 | self->name = (char*)ccmalloc(n); |
247 | | // Don't use strndup because this way I can have custom allocator (for ccmalloc). |
248 | 241 | memcpy(self->name, name, n); |
249 | 241 | self->name[len] = 0; |
250 | 241 | } |
251 | 5.33k | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_cnnp_model_copy_name Unexecuted instantiation: ccv_cnnp_model.c:ccv_cnnp_model_copy_name Unexecuted instantiation: ccv_cnnp_model_io.c:ccv_cnnp_model_copy_name ccv_cnnp_model_core.c:ccv_cnnp_model_copy_name Line | Count | Source | 241 | 1.31k | { | 242 | 1.31k | if (name) | 243 | 93 | { | 244 | 93 | const size_t len = strnlen(name, 63); | 245 | 93 | const size_t n = len + 1; | 246 | 93 | self->name = (char*)ccmalloc(n); | 247 | | // Don't use strndup because this way I can have custom allocator (for ccmalloc). | 248 | 93 | memcpy(self->name, name, n); | 249 | 93 | self->name[len] = 0; | 250 | 93 | } | 251 | 1.31k | } |
ccv_cnnp_model_addons.c:ccv_cnnp_model_copy_name Line | Count | Source | 241 | 4.01k | { | 242 | 4.01k | if (name) | 243 | 148 | { | 244 | 148 | const size_t len = strnlen(name, 63); | 245 | 148 | const size_t n = len + 1; | 246 | 148 | self->name = (char*)ccmalloc(n); | 247 | | // Don't use strndup because this way I can have custom allocator (for ccmalloc). | 248 | 148 | memcpy(self->name, name, n); | 249 | 148 | self->name[len] = 0; | 250 | 148 | } | 251 | 4.01k | } |
Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_cnnp_model_copy_name |
252 | | |
253 | | static inline void ccv_cnnp_model_add_to_parameter(ccv_cnnp_model_t* const self, const ccv_cnnp_add_to_array_f add_to_array, void* const parameters, const int is_trainable) |
254 | 2.64k | { |
255 | 2.64k | if (self->isa->add_to_parameter) |
256 | 2.64k | self->isa->add_to_parameter(self, add_to_array, parameters, is_trainable); |
257 | 2.64k | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_cnnp_model_add_to_parameter ccv_cnnp_model.c:ccv_cnnp_model_add_to_parameter Line | Count | Source | 254 | 1.20k | { | 255 | 1.20k | if (self->isa->add_to_parameter) | 256 | 1.20k | self->isa->add_to_parameter(self, add_to_array, parameters, is_trainable); | 257 | 1.20k | } |
Unexecuted instantiation: ccv_cnnp_model_io.c:ccv_cnnp_model_add_to_parameter ccv_cnnp_model_core.c:ccv_cnnp_model_add_to_parameter Line | Count | Source | 254 | 1.43k | { | 255 | 1.43k | if (self->isa->add_to_parameter) | 256 | 1.43k | self->isa->add_to_parameter(self, add_to_array, parameters, is_trainable); | 257 | 1.43k | } |
Unexecuted instantiation: ccv_cnnp_model_addons.c:ccv_cnnp_model_add_to_parameter Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_cnnp_model_add_to_parameter |
258 | | |
259 | | static inline void ccv_cnnp_model_add_to_output(ccv_cnnp_model_t* const self, const ccv_cnnp_add_to_array_f add_to_array, void* const outputs) |
260 | 2.64k | { |
261 | 2.64k | if (self->isa->add_to_output) |
262 | 176 | self->isa->add_to_output(self, add_to_array, outputs); |
263 | 2.64k | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_cnnp_model_add_to_output ccv_cnnp_model.c:ccv_cnnp_model_add_to_output Line | Count | Source | 260 | 1.20k | { | 261 | 1.20k | if (self->isa->add_to_output) | 262 | 0 | self->isa->add_to_output(self, add_to_array, outputs); | 263 | 1.20k | } |
Unexecuted instantiation: ccv_cnnp_model_io.c:ccv_cnnp_model_add_to_output ccv_cnnp_model_core.c:ccv_cnnp_model_add_to_output Line | Count | Source | 260 | 1.43k | { | 261 | 1.43k | if (self->isa->add_to_output) | 262 | 176 | self->isa->add_to_output(self, add_to_array, outputs); | 263 | 1.43k | } |
Unexecuted instantiation: ccv_cnnp_model_addons.c:ccv_cnnp_model_add_to_output Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_cnnp_model_add_to_output |
264 | | |
265 | | static inline void ccv_cnnp_model_deinit(ccv_cnnp_model_t* const self) |
266 | 8.70k | { |
267 | 8.70k | if (self->deinit_state) |
268 | 3.19k | return; |
269 | 5.50k | if (self->isa->deinit) |
270 | 1.40k | self->isa->deinit(self); |
271 | 5.50k | self->deinit_state = 1; |
272 | 5.50k | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_cnnp_model_deinit ccv_cnnp_model.c:ccv_cnnp_model_deinit Line | Count | Source | 266 | 5.50k | { | 267 | 5.50k | if (self->deinit_state) | 268 | 3.19k | return; | 269 | 2.31k | if (self->isa->deinit) | 270 | 1.08k | self->isa->deinit(self); | 271 | 2.31k | self->deinit_state = 1; | 272 | 2.31k | } |
Unexecuted instantiation: ccv_cnnp_model_io.c:ccv_cnnp_model_deinit ccv_cnnp_model_core.c:ccv_cnnp_model_deinit Line | Count | Source | 266 | 3.19k | { | 267 | 3.19k | if (self->deinit_state) | 268 | 0 | return; | 269 | 3.19k | if (self->isa->deinit) | 270 | 318 | self->isa->deinit(self); | 271 | 3.19k | self->deinit_state = 1; | 272 | 3.19k | } |
Unexecuted instantiation: ccv_cnnp_model_addons.c:ccv_cnnp_model_deinit Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_cnnp_model_deinit |
273 | | |
274 | | typedef struct { |
275 | | int exec_flags; |
276 | | int is_trainable; |
277 | | int is_gradient_checkpointing; |
278 | | int parallel_count; |
279 | | int parallel_rank; |
280 | | ccv_cnnp_model_sequence_t* model_sequence; |
281 | | ccv_cnnp_add_to_array_f add_to_array; |
282 | | ccv_array_t* parameters; |
283 | | struct { |
284 | | void* add_to_parameter; |
285 | | void* add_to_output; |
286 | | } context; |
287 | | ccv_array_t* gradient_checkpoints; |
288 | | } ccv_cnnp_model_build_data_t; // Host temporary data for building models. |
289 | | |
290 | | typedef struct { |
291 | | int input_size; |
292 | | int output_size; |
293 | | int is_trainable; |
294 | | ccv_cnnp_model_t* model; |
295 | | void (*build)(ccv_cnnp_model_t* const self, ccv_nnc_symbolic_graph_t* const graph, const ccv_nnc_tensor_symbol_t* const inputs, const int input_size, ccv_nnc_tensor_symbol_t* const outputs, const int output_size); |
296 | | ccv_array_t* tensor_symbols; |
297 | | ccv_nnc_tensor_symbol_t* inputs; |
298 | | ccv_nnc_tensor_symbol_t* outputs; |
299 | | } ccv_cnnp_model_gradient_checkpoint_t; |
300 | | |
301 | | static inline ccv_nnc_tensor_symbol_t ccv_cnnp_parameter_from_indice(ccv_cnnp_model_t* const self, const int indice) |
302 | 2 | { |
303 | 2 | assert(self->data); |
304 | 2 | ccv_cnnp_model_build_data_t* const build_data = (ccv_cnnp_model_build_data_t*)self->data; |
305 | 2 | assert(indice < build_data->parameters->rnum); |
306 | 2 | return *(ccv_nnc_tensor_symbol_t*)ccv_array_get(build_data->parameters, indice); |
307 | 2 | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_cnnp_parameter_from_indice Unexecuted instantiation: ccv_cnnp_model.c:ccv_cnnp_parameter_from_indice Unexecuted instantiation: ccv_cnnp_model_io.c:ccv_cnnp_parameter_from_indice ccv_cnnp_model_core.c:ccv_cnnp_parameter_from_indice Line | Count | Source | 302 | 2 | { | 303 | 2 | assert(self->data); | 304 | 2 | ccv_cnnp_model_build_data_t* const build_data = (ccv_cnnp_model_build_data_t*)self->data; | 305 | 2 | assert(indice < build_data->parameters->rnum); | 306 | 2 | return *(ccv_nnc_tensor_symbol_t*)ccv_array_get(build_data->parameters, indice); | 307 | 2 | } |
Unexecuted instantiation: ccv_cnnp_model_addons.c:ccv_cnnp_parameter_from_indice Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_cnnp_parameter_from_indice |
308 | | |
309 | | typedef struct { |
310 | | int record; |
311 | | ccv_array_t* tensor_symbols; |
312 | | void* old_tensor_symbol_new_hook_context; |
313 | | ccv_nnc_tensor_symbol_new_hook_f old_tensor_symbol_new_hook; |
314 | | void* old_tensor_symbol_alias_new_hook_context; |
315 | | ccv_nnc_tensor_symbol_alias_new_hook_f old_tensor_symbol_alias_new_hook; |
316 | | } ccv_cnnp_model_gradient_checkpoint_build_context_t; |
317 | | |
318 | | static void _ccv_cnnp_model_gradient_checkpoint_tensor_symbol_new_hook(void* context, const ccv_nnc_tensor_symbol_t symbol, const ccv_nnc_tensor_param_t info, const char* const name) |
319 | 30 | { |
320 | 30 | ccv_cnnp_model_gradient_checkpoint_build_context_t* const build_context = (ccv_cnnp_model_gradient_checkpoint_build_context_t*)context; |
321 | 30 | if (build_context->record) |
322 | 30 | ccv_array_push(build_context->tensor_symbols, &symbol); |
323 | 30 | if (build_context->old_tensor_symbol_new_hook) |
324 | 0 | build_context->old_tensor_symbol_new_hook(build_context->old_tensor_symbol_new_hook_context, symbol, info, name); |
325 | 30 | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_new_hook ccv_cnnp_model.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_new_hook Line | Count | Source | 319 | 30 | { | 320 | 30 | ccv_cnnp_model_gradient_checkpoint_build_context_t* const build_context = (ccv_cnnp_model_gradient_checkpoint_build_context_t*)context; | 321 | 30 | if (build_context->record) | 322 | 30 | ccv_array_push(build_context->tensor_symbols, &symbol); | 323 | 30 | if (build_context->old_tensor_symbol_new_hook) | 324 | 0 | build_context->old_tensor_symbol_new_hook(build_context->old_tensor_symbol_new_hook_context, symbol, info, name); | 325 | 30 | } |
Unexecuted instantiation: ccv_cnnp_model_io.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_new_hook Unexecuted instantiation: ccv_cnnp_model_core.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_new_hook Unexecuted instantiation: ccv_cnnp_model_addons.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_new_hook Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_new_hook |
326 | | |
327 | | static void _ccv_cnnp_model_gradient_checkpoint_tensor_symbol_alias_new_hook(void* context, const ccv_nnc_tensor_symbol_t symbol, const ccv_nnc_tensor_symbol_t from_symbol, const int ofs[CCV_NNC_MAX_DIM_ALLOC], const int inc[CCV_NNC_MAX_DIM_ALLOC], const ccv_nnc_tensor_param_t info, const char* const name) |
328 | 0 | { |
329 | 0 | ccv_cnnp_model_gradient_checkpoint_build_context_t* const build_context = (ccv_cnnp_model_gradient_checkpoint_build_context_t*)context; |
330 | 0 | if (build_context->record) |
331 | 0 | ccv_array_push(build_context->tensor_symbols, &symbol); |
332 | 0 | if (build_context->old_tensor_symbol_alias_new_hook) |
333 | 0 | build_context->old_tensor_symbol_alias_new_hook(build_context->old_tensor_symbol_alias_new_hook_context, symbol, from_symbol, ofs, inc, info, name); |
334 | 0 | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_alias_new_hook Unexecuted instantiation: ccv_cnnp_model.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_alias_new_hook Unexecuted instantiation: ccv_cnnp_model_io.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_alias_new_hook Unexecuted instantiation: ccv_cnnp_model_core.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_alias_new_hook Unexecuted instantiation: ccv_cnnp_model_addons.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_alias_new_hook Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:_ccv_cnnp_model_gradient_checkpoint_tensor_symbol_alias_new_hook |
335 | | |
336 | | static inline void ccv_cnnp_model_build(ccv_cnnp_model_t* const self, ccv_nnc_symbolic_graph_t* const graph, const ccv_nnc_tensor_symbol_t* const inputs, const int input_size, ccv_nnc_tensor_symbol_t* const outputs, const int output_size) |
337 | 5.30k | { |
338 | 5.30k | assert(self->data); |
339 | 5.30k | ccv_cnnp_model_build_data_t* const build_data = (ccv_cnnp_model_build_data_t*)self->data; |
340 | 5.30k | const int old_exec_flags = build_data->exec_flags; |
341 | 5.30k | const int old_is_trainable = build_data->is_trainable; |
342 | 5.30k | if (self->exec_flags) |
343 | 0 | build_data->exec_flags |= self->exec_flags; |
344 | 5.30k | if (self->is_trainable >= 0) |
345 | 5.29k | build_data->is_trainable = self->is_trainable; |
346 | 5.30k | if (self->name && self->name[0] != '\0'286 ) |
347 | 286 | ccv_cnnp_model_push(self, build_data->model_sequence); |
348 | 5.30k | if (self->gradient_checkpointing == 1 && !build_data->is_gradient_checkpointing2 ) |
349 | 2 | { |
350 | 2 | build_data->is_gradient_checkpointing = 1; |
351 | | // Prepare to record gradient checkpoint. We will log the build function, inputs, what are the tensors / graph execs we created. |
352 | 2 | if (!build_data->gradient_checkpoints) |
353 | 2 | build_data->gradient_checkpoints = ccv_array_new(sizeof(ccv_cnnp_model_gradient_checkpoint_t), 0, 0); |
354 | 2 | ccv_cnnp_model_gradient_checkpoint_build_context_t build_context = { |
355 | 2 | .record = 1, |
356 | 2 | .tensor_symbols = ccv_array_new(sizeof(ccv_nnc_tensor_symbol_t), 0, 0), |
357 | 2 | }; |
358 | 2 | build_context.old_tensor_symbol_new_hook_context = ccv_nnc_tensor_symbol_new_hook(graph, _ccv_cnnp_model_gradient_checkpoint_tensor_symbol_new_hook, &build_context, &build_context.old_tensor_symbol_new_hook); |
359 | 2 | build_context.old_tensor_symbol_alias_new_hook_context = ccv_nnc_tensor_symbol_alias_new_hook(graph, _ccv_cnnp_model_gradient_checkpoint_tensor_symbol_alias_new_hook, &build_context, &build_context.old_tensor_symbol_alias_new_hook); |
360 | 2 | if (outputs && output_size0 ) |
361 | 0 | { |
362 | 0 | assert(output_size == self->output_size); |
363 | 0 | self->isa->build(self, graph, inputs, input_size, outputs, output_size); |
364 | 0 | memcpy(self->outputs, outputs, sizeof(ccv_nnc_tensor_symbol_t) * output_size); |
365 | 0 | } else |
366 | 2 | self->isa->build(self, graph, inputs, input_size, self->outputs, self->output_size); |
367 | 2 | ccv_nnc_tensor_symbol_new_hook(graph, build_context.old_tensor_symbol_new_hook, build_context.old_tensor_symbol_new_hook_context, 0); |
368 | 2 | ccv_nnc_tensor_symbol_alias_new_hook(graph, build_context.old_tensor_symbol_alias_new_hook, build_context.old_tensor_symbol_alias_new_hook_context, 0); |
369 | 2 | ccv_cnnp_model_gradient_checkpoint_t checkpoint = { |
370 | 2 | .input_size = input_size, |
371 | 2 | .output_size = (outputs && output_size > 00 ) ? output_size0 : self->output_size, |
372 | 2 | .is_trainable = build_data->is_trainable, |
373 | 2 | .model = self, |
374 | 2 | .build = self->isa->build, |
375 | 2 | .tensor_symbols = build_context.tensor_symbols, |
376 | 2 | .inputs = ccmalloc(sizeof(ccv_nnc_tensor_symbol_t) * (input_size + ((outputs && output_size > 00 ) ? output_size0 : self->output_size))), |
377 | 2 | }; |
378 | 2 | checkpoint.outputs = checkpoint.inputs + input_size; |
379 | 2 | if (input_size > 0) |
380 | 2 | memcpy(checkpoint.inputs, inputs, sizeof(ccv_nnc_tensor_symbol_t) * input_size); |
381 | 2 | if (outputs && output_size > 00 ) |
382 | 0 | memcpy(checkpoint.outputs, outputs, sizeof(ccv_nnc_tensor_symbol_t) * output_size); |
383 | 2 | else if (self->outputs && self->output_size > 0) |
384 | 2 | memcpy(checkpoint.outputs, self->outputs, sizeof(ccv_nnc_tensor_symbol_t) * self->output_size); |
385 | 2 | ccv_array_push(build_data->gradient_checkpoints, &checkpoint); |
386 | 2 | build_data->is_gradient_checkpointing = 0; |
387 | 5.30k | } else { |
388 | | // If we want to disable gradient checkpointing for this model, we simply not log any new tensors created here so there is no mapping for these. |
389 | 5.30k | int old_record; |
390 | 5.30k | ccv_cnnp_model_gradient_checkpoint_build_context_t* build_context = 0; |
391 | 5.30k | if (build_data->is_gradient_checkpointing) |
392 | 36 | { |
393 | 36 | if (self->gradient_checkpointing == -1) |
394 | 0 | { |
395 | 0 | ccv_nnc_tensor_symbol_new_hook_f old_tensor_symbol_new_hook; |
396 | 0 | build_context = ccv_nnc_tensor_symbol_new_hook(graph, 0, 0, &old_tensor_symbol_new_hook); |
397 | | // Set back the build_context. |
398 | 0 | ccv_nnc_tensor_symbol_new_hook(graph, old_tensor_symbol_new_hook, build_context, 0); |
399 | 0 | old_record = build_context->record; |
400 | 0 | build_context->record = 0; |
401 | 36 | } else if (self->gradient_checkpointing == 1) { // Force to turn on gradient checkpointing if it is inside a gradient checkpointing = -1. |
402 | 0 | ccv_nnc_tensor_symbol_new_hook_f old_tensor_symbol_new_hook; |
403 | 0 | build_context = ccv_nnc_tensor_symbol_new_hook(graph, 0, 0, &old_tensor_symbol_new_hook); |
404 | | // Set back the build_context. |
405 | 0 | ccv_nnc_tensor_symbol_new_hook(graph, old_tensor_symbol_new_hook, build_context, 0); |
406 | 0 | old_record = build_context->record; |
407 | 0 | build_context->record = 1; |
408 | 0 | } |
409 | 36 | } |
410 | | // No push checkpoint, easy. |
411 | 5.30k | if (outputs && output_size2.99k ) |
412 | 2.99k | { |
413 | 2.99k | assert(output_size == self->output_size); |
414 | 2.99k | self->isa->build(self, graph, inputs, input_size, outputs, output_size); |
415 | 2.99k | memcpy(self->outputs, outputs, sizeof(ccv_nnc_tensor_symbol_t) * output_size); |
416 | 2.99k | } else |
417 | 2.31k | self->isa->build(self, graph, inputs, input_size, self->outputs, self->output_size); |
418 | 5.30k | if (build_context) // Restore previous state even if our gradient checkpointing controlled whether to turn on recording or not. |
419 | 0 | build_context->record = old_record; |
420 | 5.30k | } |
421 | | // Skip if there is none. This helps to load parameters to a different model when only changes non-parameterized settings (add reshapes, permutations etc). |
422 | | // If it is named, we have to push too. |
423 | 5.30k | if (self->isa->add_to_parameter || self->isa->add_to_output2.66k ) |
424 | 2.64k | { |
425 | | // If we already pushed, no need to push again. |
426 | 2.64k | if (!(self->name && self->name[0] != '\0'150 )) |
427 | 2.49k | ccv_cnnp_model_push(self, build_data->model_sequence); |
428 | 2.64k | build_data->model_sequence->it = 0; |
429 | 2.64k | ccv_cnnp_model_add_to_parameter(self, build_data->add_to_array, build_data->context.add_to_parameter, build_data->is_trainable); |
430 | 2.64k | build_data->model_sequence->it = 0; |
431 | 2.64k | ccv_cnnp_model_add_to_output(self, build_data->add_to_array, build_data->context.add_to_output); |
432 | 2.64k | ccv_cnnp_model_pop(self, build_data->model_sequence); |
433 | 2.66k | } else if (self->name && self->name[0] != '\0'136 ) |
434 | 136 | ccv_cnnp_model_pop(self, build_data->model_sequence); |
435 | 5.30k | build_data->exec_flags = old_exec_flags; |
436 | 5.30k | build_data->is_trainable = old_is_trainable; |
437 | 5.30k | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_cnnp_model_build ccv_cnnp_model.c:ccv_cnnp_model_build Line | Count | Source | 337 | 2.31k | { | 338 | 2.31k | assert(self->data); | 339 | 2.31k | ccv_cnnp_model_build_data_t* const build_data = (ccv_cnnp_model_build_data_t*)self->data; | 340 | 2.31k | const int old_exec_flags = build_data->exec_flags; | 341 | 2.31k | const int old_is_trainable = build_data->is_trainable; | 342 | 2.31k | if (self->exec_flags) | 343 | 0 | build_data->exec_flags |= self->exec_flags; | 344 | 2.31k | if (self->is_trainable >= 0) | 345 | 2.31k | build_data->is_trainable = self->is_trainable; | 346 | 2.31k | if (self->name && self->name[0] != '\0'50 ) | 347 | 50 | ccv_cnnp_model_push(self, build_data->model_sequence); | 348 | 2.31k | if (self->gradient_checkpointing == 1 && !build_data->is_gradient_checkpointing2 ) | 349 | 2 | { | 350 | 2 | build_data->is_gradient_checkpointing = 1; | 351 | | // Prepare to record gradient checkpoint. We will log the build function, inputs, what are the tensors / graph execs we created. | 352 | 2 | if (!build_data->gradient_checkpoints) | 353 | 2 | build_data->gradient_checkpoints = ccv_array_new(sizeof(ccv_cnnp_model_gradient_checkpoint_t), 0, 0); | 354 | 2 | ccv_cnnp_model_gradient_checkpoint_build_context_t build_context = { | 355 | 2 | .record = 1, | 356 | 2 | .tensor_symbols = ccv_array_new(sizeof(ccv_nnc_tensor_symbol_t), 0, 0), | 357 | 2 | }; | 358 | 2 | build_context.old_tensor_symbol_new_hook_context = ccv_nnc_tensor_symbol_new_hook(graph, _ccv_cnnp_model_gradient_checkpoint_tensor_symbol_new_hook, &build_context, &build_context.old_tensor_symbol_new_hook); | 359 | 2 | build_context.old_tensor_symbol_alias_new_hook_context = ccv_nnc_tensor_symbol_alias_new_hook(graph, _ccv_cnnp_model_gradient_checkpoint_tensor_symbol_alias_new_hook, &build_context, &build_context.old_tensor_symbol_alias_new_hook); | 360 | 2 | if (outputs && output_size0 ) | 361 | 0 | { | 362 | 0 | assert(output_size == self->output_size); | 363 | 0 | self->isa->build(self, graph, inputs, input_size, outputs, output_size); | 364 | 0 | memcpy(self->outputs, outputs, sizeof(ccv_nnc_tensor_symbol_t) * output_size); | 365 | 0 | } else | 366 | 2 | self->isa->build(self, graph, inputs, input_size, self->outputs, self->output_size); | 367 | 2 | ccv_nnc_tensor_symbol_new_hook(graph, build_context.old_tensor_symbol_new_hook, build_context.old_tensor_symbol_new_hook_context, 0); | 368 | 2 | ccv_nnc_tensor_symbol_alias_new_hook(graph, build_context.old_tensor_symbol_alias_new_hook, build_context.old_tensor_symbol_alias_new_hook_context, 0); | 369 | 2 | ccv_cnnp_model_gradient_checkpoint_t checkpoint = { | 370 | 2 | .input_size = input_size, | 371 | 2 | .output_size = (outputs && output_size > 00 ) ? output_size0 : self->output_size, | 372 | 2 | .is_trainable = build_data->is_trainable, | 373 | 2 | .model = self, | 374 | 2 | .build = self->isa->build, | 375 | 2 | .tensor_symbols = build_context.tensor_symbols, | 376 | 2 | .inputs = ccmalloc(sizeof(ccv_nnc_tensor_symbol_t) * (input_size + ((outputs && output_size > 00 ) ? output_size0 : self->output_size))), | 377 | 2 | }; | 378 | 2 | checkpoint.outputs = checkpoint.inputs + input_size; | 379 | 2 | if (input_size > 0) | 380 | 2 | memcpy(checkpoint.inputs, inputs, sizeof(ccv_nnc_tensor_symbol_t) * input_size); | 381 | 2 | if (outputs && output_size > 00 ) | 382 | 0 | memcpy(checkpoint.outputs, outputs, sizeof(ccv_nnc_tensor_symbol_t) * output_size); | 383 | 2 | else if (self->outputs && self->output_size > 0) | 384 | 2 | memcpy(checkpoint.outputs, self->outputs, sizeof(ccv_nnc_tensor_symbol_t) * self->output_size); | 385 | 2 | ccv_array_push(build_data->gradient_checkpoints, &checkpoint); | 386 | 2 | build_data->is_gradient_checkpointing = 0; | 387 | 2.31k | } else { | 388 | | // If we want to disable gradient checkpointing for this model, we simply not log any new tensors created here so there is no mapping for these. | 389 | 2.31k | int old_record; | 390 | 2.31k | ccv_cnnp_model_gradient_checkpoint_build_context_t* build_context = 0; | 391 | 2.31k | if (build_data->is_gradient_checkpointing) | 392 | 0 | { | 393 | 0 | if (self->gradient_checkpointing == -1) | 394 | 0 | { | 395 | 0 | ccv_nnc_tensor_symbol_new_hook_f old_tensor_symbol_new_hook; | 396 | 0 | build_context = ccv_nnc_tensor_symbol_new_hook(graph, 0, 0, &old_tensor_symbol_new_hook); | 397 | | // Set back the build_context. | 398 | 0 | ccv_nnc_tensor_symbol_new_hook(graph, old_tensor_symbol_new_hook, build_context, 0); | 399 | 0 | old_record = build_context->record; | 400 | 0 | build_context->record = 0; | 401 | 0 | } else if (self->gradient_checkpointing == 1) { // Force to turn on gradient checkpointing if it is inside a gradient checkpointing = -1. | 402 | 0 | ccv_nnc_tensor_symbol_new_hook_f old_tensor_symbol_new_hook; | 403 | 0 | build_context = ccv_nnc_tensor_symbol_new_hook(graph, 0, 0, &old_tensor_symbol_new_hook); | 404 | | // Set back the build_context. | 405 | 0 | ccv_nnc_tensor_symbol_new_hook(graph, old_tensor_symbol_new_hook, build_context, 0); | 406 | 0 | old_record = build_context->record; | 407 | 0 | build_context->record = 1; | 408 | 0 | } | 409 | 0 | } | 410 | | // No push checkpoint, easy. | 411 | 2.31k | if (outputs && output_size0 ) | 412 | 0 | { | 413 | 0 | assert(output_size == self->output_size); | 414 | 0 | self->isa->build(self, graph, inputs, input_size, outputs, output_size); | 415 | 0 | memcpy(self->outputs, outputs, sizeof(ccv_nnc_tensor_symbol_t) * output_size); | 416 | 0 | } else | 417 | 2.31k | self->isa->build(self, graph, inputs, input_size, self->outputs, self->output_size); | 418 | 2.31k | if (build_context) // Restore previous state even if our gradient checkpointing controlled whether to turn on recording or not. | 419 | 0 | build_context->record = old_record; | 420 | 2.31k | } | 421 | | // Skip if there is none. This helps to load parameters to a different model when only changes non-parameterized settings (add reshapes, permutations etc). | 422 | | // If it is named, we have to push too. | 423 | 2.31k | if (self->isa->add_to_parameter || self->isa->add_to_output1.10k ) | 424 | 1.20k | { | 425 | | // If we already pushed, no need to push again. | 426 | 1.20k | if (!(self->name && self->name[0] != '\0'3 )) | 427 | 1.20k | ccv_cnnp_model_push(self, build_data->model_sequence); | 428 | 1.20k | build_data->model_sequence->it = 0; | 429 | 1.20k | ccv_cnnp_model_add_to_parameter(self, build_data->add_to_array, build_data->context.add_to_parameter, build_data->is_trainable); | 430 | 1.20k | build_data->model_sequence->it = 0; | 431 | 1.20k | ccv_cnnp_model_add_to_output(self, build_data->add_to_array, build_data->context.add_to_output); | 432 | 1.20k | ccv_cnnp_model_pop(self, build_data->model_sequence); | 433 | 1.20k | } else if (1.10k self->name1.10k && self->name[0] != '\0'47 ) | 434 | 47 | ccv_cnnp_model_pop(self, build_data->model_sequence); | 435 | 2.31k | build_data->exec_flags = old_exec_flags; | 436 | 2.31k | build_data->is_trainable = old_is_trainable; | 437 | 2.31k | } |
Unexecuted instantiation: ccv_cnnp_model_io.c:ccv_cnnp_model_build ccv_cnnp_model_core.c:ccv_cnnp_model_build Line | Count | Source | 337 | 2.99k | { | 338 | 2.99k | assert(self->data); | 339 | 2.99k | ccv_cnnp_model_build_data_t* const build_data = (ccv_cnnp_model_build_data_t*)self->data; | 340 | 2.99k | const int old_exec_flags = build_data->exec_flags; | 341 | 2.99k | const int old_is_trainable = build_data->is_trainable; | 342 | 2.99k | if (self->exec_flags) | 343 | 0 | build_data->exec_flags |= self->exec_flags; | 344 | 2.99k | if (self->is_trainable >= 0) | 345 | 2.98k | build_data->is_trainable = self->is_trainable; | 346 | 2.99k | if (self->name && self->name[0] != '\0'236 ) | 347 | 236 | ccv_cnnp_model_push(self, build_data->model_sequence); | 348 | 2.99k | if (self->gradient_checkpointing == 1 && !build_data->is_gradient_checkpointing0 ) | 349 | 0 | { | 350 | 0 | build_data->is_gradient_checkpointing = 1; | 351 | | // Prepare to record gradient checkpoint. We will log the build function, inputs, what are the tensors / graph execs we created. | 352 | 0 | if (!build_data->gradient_checkpoints) | 353 | 0 | build_data->gradient_checkpoints = ccv_array_new(sizeof(ccv_cnnp_model_gradient_checkpoint_t), 0, 0); | 354 | 0 | ccv_cnnp_model_gradient_checkpoint_build_context_t build_context = { | 355 | 0 | .record = 1, | 356 | 0 | .tensor_symbols = ccv_array_new(sizeof(ccv_nnc_tensor_symbol_t), 0, 0), | 357 | 0 | }; | 358 | 0 | build_context.old_tensor_symbol_new_hook_context = ccv_nnc_tensor_symbol_new_hook(graph, _ccv_cnnp_model_gradient_checkpoint_tensor_symbol_new_hook, &build_context, &build_context.old_tensor_symbol_new_hook); | 359 | 0 | build_context.old_tensor_symbol_alias_new_hook_context = ccv_nnc_tensor_symbol_alias_new_hook(graph, _ccv_cnnp_model_gradient_checkpoint_tensor_symbol_alias_new_hook, &build_context, &build_context.old_tensor_symbol_alias_new_hook); | 360 | 0 | if (outputs && output_size) | 361 | 0 | { | 362 | 0 | assert(output_size == self->output_size); | 363 | 0 | self->isa->build(self, graph, inputs, input_size, outputs, output_size); | 364 | 0 | memcpy(self->outputs, outputs, sizeof(ccv_nnc_tensor_symbol_t) * output_size); | 365 | 0 | } else | 366 | 0 | self->isa->build(self, graph, inputs, input_size, self->outputs, self->output_size); | 367 | 0 | ccv_nnc_tensor_symbol_new_hook(graph, build_context.old_tensor_symbol_new_hook, build_context.old_tensor_symbol_new_hook_context, 0); | 368 | 0 | ccv_nnc_tensor_symbol_alias_new_hook(graph, build_context.old_tensor_symbol_alias_new_hook, build_context.old_tensor_symbol_alias_new_hook_context, 0); | 369 | 0 | ccv_cnnp_model_gradient_checkpoint_t checkpoint = { | 370 | 0 | .input_size = input_size, | 371 | 0 | .output_size = (outputs && output_size > 0) ? output_size : self->output_size, | 372 | 0 | .is_trainable = build_data->is_trainable, | 373 | 0 | .model = self, | 374 | 0 | .build = self->isa->build, | 375 | 0 | .tensor_symbols = build_context.tensor_symbols, | 376 | 0 | .inputs = ccmalloc(sizeof(ccv_nnc_tensor_symbol_t) * (input_size + ((outputs && output_size > 0) ? output_size : self->output_size))), | 377 | 0 | }; | 378 | 0 | checkpoint.outputs = checkpoint.inputs + input_size; | 379 | 0 | if (input_size > 0) | 380 | 0 | memcpy(checkpoint.inputs, inputs, sizeof(ccv_nnc_tensor_symbol_t) * input_size); | 381 | 0 | if (outputs && output_size > 0) | 382 | 0 | memcpy(checkpoint.outputs, outputs, sizeof(ccv_nnc_tensor_symbol_t) * output_size); | 383 | 0 | else if (self->outputs && self->output_size > 0) | 384 | 0 | memcpy(checkpoint.outputs, self->outputs, sizeof(ccv_nnc_tensor_symbol_t) * self->output_size); | 385 | 0 | ccv_array_push(build_data->gradient_checkpoints, &checkpoint); | 386 | 0 | build_data->is_gradient_checkpointing = 0; | 387 | 2.99k | } else { | 388 | | // If we want to disable gradient checkpointing for this model, we simply not log any new tensors created here so there is no mapping for these. | 389 | 2.99k | int old_record; | 390 | 2.99k | ccv_cnnp_model_gradient_checkpoint_build_context_t* build_context = 0; | 391 | 2.99k | if (build_data->is_gradient_checkpointing) | 392 | 36 | { | 393 | 36 | if (self->gradient_checkpointing == -1) | 394 | 0 | { | 395 | 0 | ccv_nnc_tensor_symbol_new_hook_f old_tensor_symbol_new_hook; | 396 | 0 | build_context = ccv_nnc_tensor_symbol_new_hook(graph, 0, 0, &old_tensor_symbol_new_hook); | 397 | | // Set back the build_context. | 398 | 0 | ccv_nnc_tensor_symbol_new_hook(graph, old_tensor_symbol_new_hook, build_context, 0); | 399 | 0 | old_record = build_context->record; | 400 | 0 | build_context->record = 0; | 401 | 36 | } else if (self->gradient_checkpointing == 1) { // Force to turn on gradient checkpointing if it is inside a gradient checkpointing = -1. | 402 | 0 | ccv_nnc_tensor_symbol_new_hook_f old_tensor_symbol_new_hook; | 403 | 0 | build_context = ccv_nnc_tensor_symbol_new_hook(graph, 0, 0, &old_tensor_symbol_new_hook); | 404 | | // Set back the build_context. | 405 | 0 | ccv_nnc_tensor_symbol_new_hook(graph, old_tensor_symbol_new_hook, build_context, 0); | 406 | 0 | old_record = build_context->record; | 407 | 0 | build_context->record = 1; | 408 | 0 | } | 409 | 36 | } | 410 | | // No push checkpoint, easy. | 411 | 2.99k | if (outputs && output_size2.99k ) | 412 | 2.99k | { | 413 | 2.99k | assert(output_size == self->output_size); | 414 | 2.99k | self->isa->build(self, graph, inputs, input_size, outputs, output_size); | 415 | 2.99k | memcpy(self->outputs, outputs, sizeof(ccv_nnc_tensor_symbol_t) * output_size); | 416 | 2.99k | } else | 417 | 4 | self->isa->build(self, graph, inputs, input_size, self->outputs, self->output_size); | 418 | 2.99k | if (build_context) // Restore previous state even if our gradient checkpointing controlled whether to turn on recording or not. | 419 | 0 | build_context->record = old_record; | 420 | 2.99k | } | 421 | | // Skip if there is none. This helps to load parameters to a different model when only changes non-parameterized settings (add reshapes, permutations etc). | 422 | | // If it is named, we have to push too. | 423 | 2.99k | if (self->isa->add_to_parameter || self->isa->add_to_output1.55k ) | 424 | 1.43k | { | 425 | | // If we already pushed, no need to push again. | 426 | 1.43k | if (!(self->name && self->name[0] != '\0'147 )) | 427 | 1.29k | ccv_cnnp_model_push(self, build_data->model_sequence); | 428 | 1.43k | build_data->model_sequence->it = 0; | 429 | 1.43k | ccv_cnnp_model_add_to_parameter(self, build_data->add_to_array, build_data->context.add_to_parameter, build_data->is_trainable); | 430 | 1.43k | build_data->model_sequence->it = 0; | 431 | 1.43k | ccv_cnnp_model_add_to_output(self, build_data->add_to_array, build_data->context.add_to_output); | 432 | 1.43k | ccv_cnnp_model_pop(self, build_data->model_sequence); | 433 | 1.55k | } else if (self->name && self->name[0] != '\0'89 ) | 434 | 89 | ccv_cnnp_model_pop(self, build_data->model_sequence); | 435 | 2.99k | build_data->exec_flags = old_exec_flags; | 436 | 2.99k | build_data->is_trainable = old_is_trainable; | 437 | 2.99k | } |
Unexecuted instantiation: ccv_cnnp_model_addons.c:ccv_cnnp_model_build Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_cnnp_model_build |
438 | | |
439 | | static inline void ccv_cnnp_model_init_states(ccv_cnnp_model_t* const self, ccv_nnc_symbolic_graph_t* const graph, const ccv_cnnp_state_initializer_f initializer, void* const context) |
440 | 552 | { |
441 | 552 | if (self->isa->init_states) |
442 | 333 | self->isa->init_states(self, graph, initializer, context); |
443 | 552 | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_cnnp_model_init_states ccv_cnnp_model.c:ccv_cnnp_model_init_states Line | Count | Source | 440 | 45 | { | 441 | 45 | if (self->isa->init_states) | 442 | 45 | self->isa->init_states(self, graph, initializer, context); | 443 | 45 | } |
Unexecuted instantiation: ccv_cnnp_model_io.c:ccv_cnnp_model_init_states ccv_cnnp_model_core.c:ccv_cnnp_model_init_states Line | Count | Source | 440 | 507 | { | 441 | 507 | if (self->isa->init_states) | 442 | 288 | self->isa->init_states(self, graph, initializer, context); | 443 | 507 | } |
Unexecuted instantiation: ccv_cnnp_model_addons.c:ccv_cnnp_model_init_states Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_cnnp_model_init_states |
444 | | |
445 | | static inline void ccv_cnnp_model_set_is_test(ccv_cnnp_model_t* const self, const int is_test, const ccv_cnnp_cmd_updater_f updater, void* const context) |
446 | 1.28k | { |
447 | 1.28k | if (self->isa->set_is_test) |
448 | 269 | self->isa->set_is_test(self, is_test, updater, context); |
449 | 1.28k | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_cnnp_model_set_is_test ccv_cnnp_model.c:ccv_cnnp_model_set_is_test Line | Count | Source | 446 | 175 | { | 447 | 175 | if (self->isa->set_is_test) | 448 | 118 | self->isa->set_is_test(self, is_test, updater, context); | 449 | 175 | } |
Unexecuted instantiation: ccv_cnnp_model_io.c:ccv_cnnp_model_set_is_test ccv_cnnp_model_core.c:ccv_cnnp_model_set_is_test Line | Count | Source | 446 | 1.10k | { | 447 | 1.10k | if (self->isa->set_is_test) | 448 | 151 | self->isa->set_is_test(self, is_test, updater, context); | 449 | 1.10k | } |
Unexecuted instantiation: ccv_cnnp_model_addons.c:ccv_cnnp_model_set_is_test Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_cnnp_model_set_is_test |
450 | | |
451 | | static inline void ccv_cnnp_model_add_to_parameter_indices(ccv_cnnp_model_t* const self, const int index, ccv_array_t* const parameter_indices) |
452 | 13.3k | { |
453 | 13.3k | if (self->isa->add_to_parameter_indices) |
454 | 3.59k | self->isa->add_to_parameter_indices(self, index, parameter_indices); |
455 | 9.75k | else { |
456 | 9.75k | int i; |
457 | 9.75k | if (!self->parameter_indices) |
458 | 4.64k | return; |
459 | 5.11k | if (index == -1) |
460 | 198 | for (i = 0; 97 i < self->parameter_indices->rnum; i++101 ) |
461 | 101 | ccv_array_push(parameter_indices, ccv_array_get(self->parameter_indices, i)); |
462 | 5.01k | else if (index < self->parameter_indices->rnum) |
463 | 5.01k | ccv_array_push(parameter_indices, ccv_array_get(self->parameter_indices, index)); |
464 | 5.11k | } |
465 | 13.3k | } Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_cnnp_model_add_to_parameter_indices ccv_cnnp_model.c:ccv_cnnp_model_add_to_parameter_indices Line | Count | Source | 452 | 398 | { | 453 | 398 | if (self->isa->add_to_parameter_indices) | 454 | 344 | self->isa->add_to_parameter_indices(self, index, parameter_indices); | 455 | 54 | else { | 456 | 54 | int i; | 457 | 54 | if (!self->parameter_indices) | 458 | 0 | return; | 459 | 54 | if (index == -1) | 460 | 92 | for (i = 0; 44 i < self->parameter_indices->rnum; i++48 ) | 461 | 48 | ccv_array_push(parameter_indices, ccv_array_get(self->parameter_indices, i)); | 462 | 10 | else if (index < self->parameter_indices->rnum) | 463 | 10 | ccv_array_push(parameter_indices, ccv_array_get(self->parameter_indices, index)); | 464 | 54 | } | 465 | 398 | } |
Unexecuted instantiation: ccv_cnnp_model_io.c:ccv_cnnp_model_add_to_parameter_indices ccv_cnnp_model_core.c:ccv_cnnp_model_add_to_parameter_indices Line | Count | Source | 452 | 12.9k | { | 453 | 12.9k | if (self->isa->add_to_parameter_indices) | 454 | 3.25k | self->isa->add_to_parameter_indices(self, index, parameter_indices); | 455 | 9.69k | else { | 456 | 9.69k | int i; | 457 | 9.69k | if (!self->parameter_indices) | 458 | 4.64k | return; | 459 | 5.05k | if (index == -1) | 460 | 106 | for (i = 0; 53 i < self->parameter_indices->rnum; i++53 ) | 461 | 53 | ccv_array_push(parameter_indices, ccv_array_get(self->parameter_indices, i)); | 462 | 5.00k | else if (index < self->parameter_indices->rnum) | 463 | 5.00k | ccv_array_push(parameter_indices, ccv_array_get(self->parameter_indices, index)); | 464 | 5.05k | } | 465 | 12.9k | } |
Unexecuted instantiation: ccv_cnnp_model_addons.c:ccv_cnnp_model_add_to_parameter_indices Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_cnnp_model_add_to_parameter_indices |
466 | | |
467 | | typedef struct { |
468 | | uint8_t add_parameter_indices; |
469 | | char prefix; |
470 | | ccv_cnnp_model_sequence_t* sequence; |
471 | | ccv_array_t* symbols; |
472 | | ccv_array_t* ids; |
473 | | ccv_array_t* trainables; |
474 | | } ccv_cnnp_model_add_to_array_context_t; |
475 | | |
476 | | void ccv_cnnp_model_tensors_init_0(const ccv_cnnp_model_t* const model, ccv_cnnp_compiled_data_t* const compiled_data); |
477 | | void ccv_cnnp_model_tensors_init_1(const ccv_cnnp_model_t* const model, ccv_cnnp_compiled_data_t* const compiled_data); |
478 | | int ccv_cnnp_model_tensors_any_to_alloc(const ccv_cnnp_model_t* const model, ccv_cnnp_compiled_data_t* const compiled_data); |
479 | | ccv_nnc_tensor_symbol_t ccv_cnnp_model_get_symbol(ccv_cnnp_model_t* const self, const ccv_nnc_tensor_symbol_t symbol); |
480 | | ccv_nnc_stream_context_t* ccv_cnnp_compiled_data_get_stream(ccv_cnnp_compiled_data_t* const compiled_data, const int type); |
481 | | void ccv_cnnp_model_gradient_checkpoints_cleanup_after_build(ccv_cnnp_compiled_data_t* const compiled_data, ccv_nnc_symbolic_graph_t* const graph); |
482 | | void ccv_cnnp_model_apply_gradient_checkpoints(ccv_cnnp_compiled_data_t* const compiled_data, ccv_nnc_symbolic_graph_t* const graph); |
483 | | void ccv_cnnp_model_add_to_array(void* const context, const ccv_nnc_tensor_symbol_t symbol, const int is_trainable); |
484 | | |
485 | | #endif |