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