Bug Summary

File:nnc/ccv_cnnp_model_core.c
Warning:line 374, column 1
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ccv_cnnp_model_core.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +sse2 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/liu/actions-runner/_work/ccv/ccv/lib/nnc -fcoverage-compilation-dir=/home/liu/actions-runner/_work/ccv/ccv/lib/nnc -resource-dir /usr/local/lib/clang/19 -I ../ -I /usr/local/cuda/include -D HAVE_CBLAS -D HAVE_LIBPNG -D HAVE_LIBJPEG -D HAVE_FFTW3 -D HAVE_PTHREAD -D HAVE_LIBLINEAR -D HAVE_TESSERACT -D HAVE_AVCODEC -D HAVE_AVFORMAT -D HAVE_AVUTIL -D HAVE_SWSCALE -D HAVE_SSE2 -D HAVE_GSL -D HAVE_CUDA -D HAVE_CUDNN -D HAVE_NCCL -D USE_SYSTEM_CUB -I /usr/local/include -internal-isystem /usr/local/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/liu/actions-runner/_work/ccv/ccv/_analyze/2025-03-23-203046-130396-1 -x c ccv_cnnp_model_core.c
1#include "ccv_nnc.h"
2#include "ccv_nnc_easy.h"
3#include "ccv_nnc_internal.h"
4#include "ccv_internal.h"
5#include "_ccv_cnnp_model.h"
6#include "3rdparty/khash/khash.h"
7
8// MARK - Baisc Layers
9
10static const ccv_cnnp_model_vtab_t ccv_cnnp_input_isa;
11
12#define CCV_CNNP_IS_MODEL_INPUT(x)((x)->isa == &ccv_cnnp_input_isa) ((x)->isa == &ccv_cnnp_input_isa)
13
14#define CCV_CNNP_IS_MODEL_PARAMETER(x)((x)->param_ref != 0 || (x)->param_sel != 0) ((x)->param_ref != 0 || (x)->param_sel != 0)
15
16typedef struct {
17 ccv_cnnp_model_t super;
18 int sequence_size;
19 ccv_cnnp_model_t* sequence[1];
20} ccv_cnnp_sequential_model_t;
21
22static void _ccv_cnnp_sequential_model_deinit(ccv_cnnp_model_t* const super)
23{
24 ccv_cnnp_sequential_model_t* const self = (ccv_cnnp_sequential_model_t*)super;
25 int i, j = 0;
26 for (i = 0; i < self->sequence_size; i++)
27 {
28 ccv_cnnp_model_t* const model = self->sequence[i];
29 if (model->deinit_state)
30 continue;
31 ccv_cnnp_model_deinit(model);
32 self->sequence[j++] = model;
33 }
34 self->sequence_size = j;
35}
36
37static void _ccv_cnnp_sequential_model_dealloc(ccv_cnnp_model_t* const super)
38{
39 ccv_cnnp_sequential_model_t* const self = (ccv_cnnp_sequential_model_t*)super;
40 int i;
41 for (i = 0; i < self->sequence_size; i++)
42 ccv_cnnp_model_free(self->sequence[i]);
43}
44
45static void _ccv_cnnp_sequential_model_build(ccv_cnnp_model_t* const super, 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)
46{
47 ccv_cnnp_sequential_model_t* const self = (ccv_cnnp_sequential_model_t*)super;
48 PRINT(CCV_CLI_VERBOSE, "[cnnp_sequential_model_build] 1. %p, sequence_size: %d\n", self, self->sequence_size)do { if ((CCV_CLI_VERBOSE & ccv_cli_get_output_levels()))
{ printf("[cnnp_sequential_model_build] 1. %p, sequence_size: %d\n"
, self, self->sequence_size); fflush(stdout); } } while (0
)
;
49 ccv_cnnp_model_t* const sub_model = self->sequence[0];
50 // Go through each sub model to build the graph.
51 ccv_nnc_tensor_symbol_t input;
52 sub_model->data = self->super.data;
53 ccv_cnnp_model_build(sub_model, graph, inputs, input_size, &input, 1);
54 sub_model->data = 0;
55 int i;
56 for (i = 1; i < self->sequence_size; i++)
57 {
58 ccv_nnc_tensor_symbol_t output;
59 ccv_cnnp_model_t* const sub_model = self->sequence[i];
60 // Go through each sub model to build the graph.
61 sub_model->data = self->super.data;
62 ccv_cnnp_model_build(sub_model, graph, &input, 1, &output, 1);
63 sub_model->data = 0;
64 input = output;
65 }
66 outputs[0] = input;
67 PRINT(CCV_CLI_VERBOSE, "[cnnp_sequential_model_build] 2. %p\n", self)do { if ((CCV_CLI_VERBOSE & ccv_cli_get_output_levels()))
{ printf("[cnnp_sequential_model_build] 2. %p\n", self); fflush
(stdout); } } while (0)
;
68}
69
70static void _ccv_cnnp_sequential_model_init_states(ccv_cnnp_model_t* const super, ccv_nnc_symbolic_graph_t* const graph, const ccv_cnnp_state_initializer_f initializer, void* const context)
71{
72 ccv_cnnp_sequential_model_t* const self = (ccv_cnnp_sequential_model_t*)super;
73 int i;
74 for (i = 0; i < self->sequence_size; i++)
75 ccv_cnnp_model_init_states(self->sequence[i], graph, initializer, context);
76}
77
78static void _ccv_cnnp_sequential_model_set_is_test(ccv_cnnp_model_t* const super, const int is_test, const ccv_cnnp_cmd_updater_f updater, void* const context)
79{
80 ccv_cnnp_sequential_model_t* const self = (ccv_cnnp_sequential_model_t*)super;
81 int i;
82 for (i = 0; i < self->sequence_size; i++)
83 ccv_cnnp_model_set_is_test(self->sequence[i], is_test, updater, context);
84}
85
86static ccv_cnnp_model_t* _ccv_cnnp_sequential_model_copy(const ccv_cnnp_model_t* const super, void* const context);
87
88static void _ccv_cnnp_sequential_model_add_to_parameter_indices(ccv_cnnp_model_t* const super, const int index, ccv_array_t* const parameter_indices)
89{
90 ccv_cnnp_sequential_model_t* const self = (ccv_cnnp_sequential_model_t*)super;
91 int i;
92 for (i = 0; i < self->sequence_size; i++)
93 ccv_cnnp_model_add_to_parameter_indices(self->sequence[i], index, parameter_indices);
94}
95
96static void _ccv_cnnp_sequential_model_notify(const ccv_cnnp_model_t* const super, const int tag, void* const payload)
97{
98 ccv_cnnp_sequential_model_t* const self = (ccv_cnnp_sequential_model_t*)super;
99 int i;
100 for (i = 0; i < self->sequence_size; i++)
101 ccv_cnnp_model_notify(self->sequence[i], tag, payload);
102}
103
104static const ccv_cnnp_model_vtab_t ccv_cnnp_sequential_model_isa = {
105 .deinit = _ccv_cnnp_sequential_model_deinit,
106 .dealloc = _ccv_cnnp_sequential_model_dealloc,
107 .build = _ccv_cnnp_sequential_model_build,
108 .init_states = _ccv_cnnp_sequential_model_init_states,
109 .copy = _ccv_cnnp_sequential_model_copy,
110 .set_is_test = _ccv_cnnp_sequential_model_set_is_test,
111 .add_to_parameter_indices = _ccv_cnnp_sequential_model_add_to_parameter_indices,
112 .notify = _ccv_cnnp_sequential_model_notify,
113};
114
115KHASH_MAP_INIT_INT64(model, ccv_cnnp_model_t*)typedef struct kh_model_s { khint_t n_buckets, size, n_occupied
, upper_bound; khint32_t *flags; khint64_t *keys; ccv_cnnp_model_t
* *vals; } kh_model_t; static inline __attribute__ ((__unused__
)) kh_model_t *kh_init_model(void) { return (kh_model_t*)calloc
(1,sizeof(kh_model_t)); } static inline __attribute__ ((__unused__
)) void kh_destroy_model(kh_model_t *h) { if (h) { free((void
*)h->keys); free(h->flags); free((void *)h->vals); free
(h); } } static inline __attribute__ ((__unused__)) void kh_clear_model
(kh_model_t *h) { if (h && h->flags) { memset(h->
flags, 0xaa, ((h->n_buckets) < 16? 1 : (h->n_buckets
)>>4) * sizeof(khint32_t)); h->size = h->n_occupied
= 0; } } static inline __attribute__ ((__unused__)) khint_t kh_get_model
(const kh_model_t *h, khint64_t key) { if (h->n_buckets) {
khint_t k, i, last, mask, step = 0; mask = h->n_buckets -
1; k = (khint32_t)((key)>>33^(key)^(key)<<11); i
= k & mask; last = i; while (!((h->flags[i>>4]>>
((i&0xfU)<<1))&2) && (((h->flags[i>>
4]>>((i&0xfU)<<1))&1) || !((h->keys[i]
) == (key)))) { i = (i + (++step)) & mask; if (i == last)
return h->n_buckets; } return ((h->flags[i>>4]>>
((i&0xfU)<<1))&3)? h->n_buckets : i; } else return
0; } static inline __attribute__ ((__unused__)) int kh_resize_model
(kh_model_t *h, khint_t new_n_buckets) { khint32_t *new_flags
= 0; khint_t j = 1; { (--(new_n_buckets), (new_n_buckets)|=(
new_n_buckets)>>1, (new_n_buckets)|=(new_n_buckets)>>
2, (new_n_buckets)|=(new_n_buckets)>>4, (new_n_buckets)
|=(new_n_buckets)>>8, (new_n_buckets)|=(new_n_buckets)>>
16, ++(new_n_buckets)); if (new_n_buckets < 4) new_n_buckets
= 4; if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER
+ 0.5)) j = 0; else { new_flags = (khint32_t*)malloc(((new_n_buckets
) < 16? 1 : (new_n_buckets)>>4) * sizeof(khint32_t))
; if (!new_flags) return -1; memset(new_flags, 0xaa, ((new_n_buckets
) < 16? 1 : (new_n_buckets)>>4) * sizeof(khint32_t))
; if (h->n_buckets < new_n_buckets) { khint64_t *new_keys
= (khint64_t*)realloc((void *)h->keys,new_n_buckets * sizeof
(khint64_t)); if (!new_keys) { free(new_flags); return -1; } h
->keys = new_keys; if (1) { ccv_cnnp_model_t* *new_vals = (
ccv_cnnp_model_t**)realloc((void *)h->vals,new_n_buckets *
sizeof(ccv_cnnp_model_t*)); if (!new_vals) { free(new_flags)
; return -1; } h->vals = new_vals; } } } } if (j) { for (j
= 0; j != h->n_buckets; ++j) { if (((h->flags[j>>
4]>>((j&0xfU)<<1))&3) == 0) { khint64_t key
= h->keys[j]; ccv_cnnp_model_t* val; khint_t new_mask; new_mask
= new_n_buckets - 1; if (1) val = h->vals[j]; (h->flags
[j>>4]|=1ul<<((j&0xfU)<<1)); while (1) {
khint_t k, i, step = 0; k = (khint32_t)((key)>>33^(key
)^(key)<<11); i = k & new_mask; while (!((new_flags
[i>>4]>>((i&0xfU)<<1))&2)) i = (i +
(++step)) & new_mask; (new_flags[i>>4]&=~(2ul<<
((i&0xfU)<<1))); if (i < h->n_buckets &&
((h->flags[i>>4]>>((i&0xfU)<<1))&
3) == 0) { { khint64_t tmp = h->keys[i]; h->keys[i] = key
; key = tmp; } if (1) { ccv_cnnp_model_t* tmp = h->vals[i]
; h->vals[i] = val; val = tmp; } (h->flags[i>>4]|=
1ul<<((i&0xfU)<<1)); } else { h->keys[i] =
key; if (1) h->vals[i] = val; break; } } } } if (h->n_buckets
> new_n_buckets) { h->keys = (khint64_t*)realloc((void
*)h->keys,new_n_buckets * sizeof(khint64_t)); if (1) h->
vals = (ccv_cnnp_model_t**)realloc((void *)h->vals,new_n_buckets
* sizeof(ccv_cnnp_model_t*)); } free(h->flags); h->flags
= new_flags; h->n_buckets = new_n_buckets; h->n_occupied
= h->size; h->upper_bound = (khint_t)(h->n_buckets *
__ac_HASH_UPPER + 0.5); } return 0; } static inline __attribute__
((__unused__)) khint_t kh_put_model(kh_model_t *h, khint64_t
key, int *ret) { khint_t x; if (h->n_occupied >= h->
upper_bound) { if (h->n_buckets > (h->size<<1)
) { if (kh_resize_model(h, h->n_buckets - 1) < 0) { *ret
= -1; return h->n_buckets; } } else if (kh_resize_model(h
, h->n_buckets + 1) < 0) { *ret = -1; return h->n_buckets
; } } { khint_t k, i, site, last, mask = h->n_buckets - 1,
step = 0; x = site = h->n_buckets; k = (khint32_t)((key)>>
33^(key)^(key)<<11); i = k & mask; if (((h->flags
[i>>4]>>((i&0xfU)<<1))&2)) x = i; else
{ last = i; while (!((h->flags[i>>4]>>((i&
0xfU)<<1))&2) && (((h->flags[i>>4]
>>((i&0xfU)<<1))&1) || !((h->keys[i]) ==
(key)))) { if (((h->flags[i>>4]>>((i&0xfU
)<<1))&1)) site = i; i = (i + (++step)) & mask;
if (i == last) { x = site; break; } } if (x == h->n_buckets
) { if (((h->flags[i>>4]>>((i&0xfU)<<
1))&2) && site != h->n_buckets) x = site; else
x = i; } } } if (((h->flags[x>>4]>>((x&0xfU
)<<1))&2)) { h->keys[x] = key; (h->flags[x>>
4]&=~(3ul<<((x&0xfU)<<1))); ++h->size;
++h->n_occupied; *ret = 1; } else if (((h->flags[x>>
4]>>((x&0xfU)<<1))&1)) { h->keys[x] = key
; (h->flags[x>>4]&=~(3ul<<((x&0xfU)<<
1))); ++h->size; *ret = 2; } else *ret = 0; return x; } static
inline __attribute__ ((__unused__)) void kh_del_model(kh_model_t
*h, khint_t x) { if (x != h->n_buckets && !((h->
flags[x>>4]>>((x&0xfU)<<1))&3)) { (
h->flags[x>>4]|=1ul<<((x&0xfU)<<1));
--h->size; } }
116
117static ccv_cnnp_model_t* _ccv_cnnp_sequential_model_copy(const ccv_cnnp_model_t* const super, void* const context)
118{
119 const ccv_cnnp_sequential_model_t* const self = (const ccv_cnnp_sequential_model_t*)super;
120 ccv_cnnp_sequential_model_t* const sequential_model = (ccv_cnnp_sequential_model_t*)cccalloccalloc(1, sizeof(ccv_cnnp_sequential_model_t) + sizeof(ccv_cnnp_model_t*) * (self->sequence_size - 1) + sizeof(ccv_nnc_tensor_symbol_t));
121 sequential_model->super.isa = &ccv_cnnp_sequential_model_isa;
122 sequential_model->super.input_size = 1;
123 sequential_model->super.outputs = (ccv_nnc_tensor_symbol_t*)(sequential_model->sequence + self->sequence_size);
124 sequential_model->super.output_size = 1;
125 ccv_cnnp_model_copy_name(&sequential_model->super, self->super.name);
126 sequential_model->sequence_size = self->sequence_size;
127 int i;
128 khash_t(model)kh_model_t* model_map = context ? (khash_t(model)kh_model_t*)context : kh_init(model)kh_init_model();
129 for (i = 0; i < self->sequence_size; i++)
130 {
131 ccv_cnnp_model_t* const sub_model = self->sequence[i];
132 int ret;
133 khiter_t k = kh_put(model, model_map, (uint64_t)(uintptr_t)sub_model, &ret)kh_put_model(model_map, (uint64_t)(uintptr_t)sub_model, &
ret)
;
134 ccv_cnnp_model_t* model_copy;
135 if (ret != 0)
136 model_copy = kh_val(model_map, k)((model_map)->vals[k]) = _ccv_cnnp_model_copy(sub_model, model_map);
137 else
138 model_copy = kh_val(model_map, k)((model_map)->vals[k]);
139 sequential_model->sequence[i] = model_copy;
140 }
141 if (!context)
142 kh_destroy(model, model_map)kh_destroy_model(model_map);
143 return (ccv_cnnp_model_t*)sequential_model;
144}
145
146ccv_cnnp_model_t* ccv_cnnp_sequential_new(ccv_cnnp_model_t* const* const models, const int model_size, const int is_trainable, const char* const name)
147{
148 assert(model_size > 0)((void) sizeof ((model_size > 0) ? 1 : 0), __extension__ (
{ if (model_size > 0) ; else __assert_fail ("model_size > 0"
, "ccv_cnnp_model_core.c", 148, __extension__ __PRETTY_FUNCTION__
); }))
;
149 ccv_cnnp_sequential_model_t* const sequential_model = (ccv_cnnp_sequential_model_t*)cccalloccalloc(1, sizeof(ccv_cnnp_sequential_model_t) + sizeof(ccv_cnnp_model_t*) * (model_size - 1) + sizeof(ccv_nnc_tensor_symbol_t));
150 sequential_model->super.isa = &ccv_cnnp_sequential_model_isa;
151 sequential_model->super.input_size = models[0]->input_size;
152 sequential_model->super.outputs = (ccv_nnc_tensor_symbol_t*)(sequential_model->sequence + model_size);
153 sequential_model->super.output_size = 1;
154 sequential_model->super.is_trainable = is_trainable;
155 ccv_cnnp_model_copy_name(&sequential_model->super, name);
156 sequential_model->sequence_size = model_size;
157 memcpy(sequential_model->sequence, models, sizeof(ccv_cnnp_model_t*) * model_size);
158 return (ccv_cnnp_model_t*)sequential_model;
159}
160
161typedef struct {
162 ccv_cnnp_model_t super;
163 // The model's outputs, it is different from super.output_size, as latter is for actual tensor symbols.
164 int model_output_size;
165 // The name is similar to sequential model, but it is just topological sorted models.
166 int sequence_size;
167 int* model_outputs; // Which model, as in sequences, have some outputs.
168 ccv_cnnp_model_io_t sequence[1];
169} ccv_cnnp_functional_model_t;
170
171static void _ccv_cnnp_functional_model_deinit(ccv_cnnp_model_t* const super)
172{
173 ccv_cnnp_functional_model_t* const self = (ccv_cnnp_functional_model_t*)super;
174 int i, j = 0, k;
175 for (i = 0; i < self->sequence_size; i++)
176 {
177 ccv_cnnp_model_t* const model = self->sequence[i]->model;
178 if (!model || model->deinit_state)
179 continue;
180 self->sequence[j++] = (ccv_cnnp_model_io_t)model;
181 // Go through all their IO to remove itself as model.
182 assert(model->io)((void) sizeof ((model->io) ? 1 : 0), __extension__ ({ if (
model->io) ; else __assert_fail ("model->io", "ccv_cnnp_model_core.c"
, 182, __extension__ __PRETTY_FUNCTION__); }))
;
183 for (k = 0; k < model->io->rnum; k++)
184 {
185 ccv_cnnp_model_io_t model_io = *(ccv_cnnp_model_io_t*)ccv_array_get(model->io, k)((void*)(((char*)((model->io)->data)) + (size_t)(model->
io)->rsize * (size_t)(k)))
;
186 model_io->model = 0;
187 }
188 }
189 for (i = 0; i < j; i++)
190 ccv_cnnp_model_deinit((ccv_cnnp_model_t*)self->sequence[i]);
191 self->sequence_size = j;
192}
193
194static void _ccv_cnnp_functional_model_dealloc(ccv_cnnp_model_t* const super)
195{
196 ccv_cnnp_functional_model_t* const self = (ccv_cnnp_functional_model_t*)super;
197 int i;
198 for (i = 0; i < self->sequence_size; i++)
199 ccv_cnnp_model_free((ccv_cnnp_model_t*)self->sequence[i]);
200}
201
202KHASH_MAP_INIT_INT64(io_node, ccv_array_t*)typedef struct kh_io_node_s { khint_t n_buckets, size, n_occupied
, upper_bound; khint32_t *flags; khint64_t *keys; ccv_array_t
* *vals; } kh_io_node_t; static inline __attribute__ ((__unused__
)) kh_io_node_t *kh_init_io_node(void) { return (kh_io_node_t
*)calloc(1,sizeof(kh_io_node_t)); } static inline __attribute__
((__unused__)) void kh_destroy_io_node(kh_io_node_t *h) { if
(h) { free((void *)h->keys); free(h->flags); free((void
*)h->vals); free(h); } } static inline __attribute__ ((__unused__
)) void kh_clear_io_node(kh_io_node_t *h) { if (h && h
->flags) { memset(h->flags, 0xaa, ((h->n_buckets) <
16? 1 : (h->n_buckets)>>4) * sizeof(khint32_t)); h->
size = h->n_occupied = 0; } } static inline __attribute__ (
(__unused__)) khint_t kh_get_io_node(const kh_io_node_t *h, khint64_t
key) { if (h->n_buckets) { khint_t k, i, last, mask, step
= 0; mask = h->n_buckets - 1; k = (khint32_t)((key)>>
33^(key)^(key)<<11); i = k & mask; last = i; while (
!((h->flags[i>>4]>>((i&0xfU)<<1))&
2) && (((h->flags[i>>4]>>((i&0xfU)
<<1))&1) || !((h->keys[i]) == (key)))) { i = (i +
(++step)) & mask; if (i == last) return h->n_buckets;
} return ((h->flags[i>>4]>>((i&0xfU)<<
1))&3)? h->n_buckets : i; } else return 0; } static inline
__attribute__ ((__unused__)) int kh_resize_io_node(kh_io_node_t
*h, khint_t new_n_buckets) { khint32_t *new_flags = 0; khint_t
j = 1; { (--(new_n_buckets), (new_n_buckets)|=(new_n_buckets
)>>1, (new_n_buckets)|=(new_n_buckets)>>2, (new_n_buckets
)|=(new_n_buckets)>>4, (new_n_buckets)|=(new_n_buckets)
>>8, (new_n_buckets)|=(new_n_buckets)>>16, ++(new_n_buckets
)); if (new_n_buckets < 4) new_n_buckets = 4; if (h->size
>= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0
; else { new_flags = (khint32_t*)malloc(((new_n_buckets) <
16? 1 : (new_n_buckets)>>4) * sizeof(khint32_t)); if (
!new_flags) return -1; memset(new_flags, 0xaa, ((new_n_buckets
) < 16? 1 : (new_n_buckets)>>4) * sizeof(khint32_t))
; if (h->n_buckets < new_n_buckets) { khint64_t *new_keys
= (khint64_t*)realloc((void *)h->keys,new_n_buckets * sizeof
(khint64_t)); if (!new_keys) { free(new_flags); return -1; } h
->keys = new_keys; if (1) { ccv_array_t* *new_vals = (ccv_array_t
**)realloc((void *)h->vals,new_n_buckets * sizeof(ccv_array_t
*)); if (!new_vals) { free(new_flags); return -1; } h->vals
= new_vals; } } } } if (j) { for (j = 0; j != h->n_buckets
; ++j) { if (((h->flags[j>>4]>>((j&0xfU)<<
1))&3) == 0) { khint64_t key = h->keys[j]; ccv_array_t
* val; khint_t new_mask; new_mask = new_n_buckets - 1; if (1)
val = h->vals[j]; (h->flags[j>>4]|=1ul<<((
j&0xfU)<<1)); while (1) { khint_t k, i, step = 0; k
= (khint32_t)((key)>>33^(key)^(key)<<11); i = k &
new_mask; while (!((new_flags[i>>4]>>((i&0xfU
)<<1))&2)) i = (i + (++step)) & new_mask; (new_flags
[i>>4]&=~(2ul<<((i&0xfU)<<1))); if (
i < h->n_buckets && ((h->flags[i>>4]>>
((i&0xfU)<<1))&3) == 0) { { khint64_t tmp = h->
keys[i]; h->keys[i] = key; key = tmp; } if (1) { ccv_array_t
* tmp = h->vals[i]; h->vals[i] = val; val = tmp; } (h->
flags[i>>4]|=1ul<<((i&0xfU)<<1)); } else
{ h->keys[i] = key; if (1) h->vals[i] = val; break; } }
} } if (h->n_buckets > new_n_buckets) { h->keys = (
khint64_t*)realloc((void *)h->keys,new_n_buckets * sizeof(
khint64_t)); if (1) h->vals = (ccv_array_t**)realloc((void
*)h->vals,new_n_buckets * sizeof(ccv_array_t*)); } free(h
->flags); h->flags = new_flags; h->n_buckets = new_n_buckets
; h->n_occupied = h->size; h->upper_bound = (khint_t
)(h->n_buckets * __ac_HASH_UPPER + 0.5); } return 0; } static
inline __attribute__ ((__unused__)) khint_t kh_put_io_node(kh_io_node_t
*h, khint64_t key, int *ret) { khint_t x; if (h->n_occupied
>= h->upper_bound) { if (h->n_buckets > (h->size
<<1)) { if (kh_resize_io_node(h, h->n_buckets - 1) <
0) { *ret = -1; return h->n_buckets; } } else if (kh_resize_io_node
(h, h->n_buckets + 1) < 0) { *ret = -1; return h->n_buckets
; } } { khint_t k, i, site, last, mask = h->n_buckets - 1,
step = 0; x = site = h->n_buckets; k = (khint32_t)((key)>>
33^(key)^(key)<<11); i = k & mask; if (((h->flags
[i>>4]>>((i&0xfU)<<1))&2)) x = i; else
{ last = i; while (!((h->flags[i>>4]>>((i&
0xfU)<<1))&2) && (((h->flags[i>>4]
>>((i&0xfU)<<1))&1) || !((h->keys[i]) ==
(key)))) { if (((h->flags[i>>4]>>((i&0xfU
)<<1))&1)) site = i; i = (i + (++step)) & mask;
if (i == last) { x = site; break; } } if (x == h->n_buckets
) { if (((h->flags[i>>4]>>((i&0xfU)<<
1))&2) && site != h->n_buckets) x = site; else
x = i; } } } if (((h->flags[x>>4]>>((x&0xfU
)<<1))&2)) { h->keys[x] = key; (h->flags[x>>
4]&=~(3ul<<((x&0xfU)<<1))); ++h->size;
++h->n_occupied; *ret = 1; } else if (((h->flags[x>>
4]>>((x&0xfU)<<1))&1)) { h->keys[x] = key
; (h->flags[x>>4]&=~(3ul<<((x&0xfU)<<
1))); ++h->size; *ret = 2; } else *ret = 0; return x; } static
inline __attribute__ ((__unused__)) void kh_del_io_node(kh_io_node_t
*h, khint_t x) { if (x != h->n_buckets && !((h->
flags[x>>4]>>((x&0xfU)<<1))&3)) { (
h->flags[x>>4]|=1ul<<((x&0xfU)<<1));
--h->size; } }
203
204typedef struct {
205 ccv_array_t* nodes;
206 ccv_nnc_graph_exec_symbol_new_hook_f previous_func;
207 void* previous_context;
208} ccv_functional_model_build_node_hook_t;
209
210static void _ccv_cnnp_functional_model_build_node_new(void* context, const ccv_nnc_graph_exec_symbol_t symbol, const ccv_nnc_cmd_t cmd, const ccv_nnc_tensor_symbol_t* const inputs, const int input_size, const ccv_nnc_tensor_symbol_t* const outputs, const int output_size, const char* const name)
211{
212 ccv_functional_model_build_node_hook_t* const hook = (ccv_functional_model_build_node_hook_t*)context;
213 ccv_array_push(hook->nodes, &symbol);
214 if (hook->previous_func)
215 hook->previous_func(hook->previous_context, symbol, cmd, inputs, input_size, outputs, output_size, name);
216}
217
218static void _ccv_cnnp_functional_model_build(ccv_cnnp_model_t* const super, 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)
219{
220 ccv_cnnp_functional_model_t* const self = (ccv_cnnp_functional_model_t*)super;
221 PRINT(CCV_CLI_VERBOSE, "[cnnp_functional_model_build] 1. %p, input_size: %d, output_size: %d\n", self, input_size, output_size)do { if ((CCV_CLI_VERBOSE & ccv_cli_get_output_levels()))
{ printf("[cnnp_functional_model_build] 1. %p, input_size: %d, output_size: %d\n"
, self, input_size, output_size); fflush(stdout); } } while (
0)
;
222 assert(self->super.input_size == input_size)((void) sizeof ((self->super.input_size == input_size) ? 1
: 0), __extension__ ({ if (self->super.input_size == input_size
) ; else __assert_fail ("self->super.input_size == input_size"
, "ccv_cnnp_model_core.c", 222, __extension__ __PRETTY_FUNCTION__
); }))
;
223 assert(self->super.output_size == output_size)((void) sizeof ((self->super.output_size == output_size) ?
1 : 0), __extension__ ({ if (self->super.output_size == output_size
) ; else __assert_fail ("self->super.output_size == output_size"
, "ccv_cnnp_model_core.c", 223, __extension__ __PRETTY_FUNCTION__
); }))
;
224 int i, j, k;
225 for (i = 0; i < self->super.input_size; i++)
226 self->sequence[i]->outputs[0] = self->sequence[i]->model->outputs[0] = inputs[i]; // Assigning the output symbol of input layer to be the input symbol.
227 ccv_array_t* input_symbols = ccv_array_new(sizeof(ccv_nnc_tensor_symbol_t), 1, 0);
228 ccv_array_t* parameter_indices = 0;
229 khash_t(io_node)kh_io_node_t* io_node_map = kh_init(io_node)kh_init_io_node();
230 for (i = self->super.input_size; i < self->sequence_size; i++)
231 {
232 ccv_cnnp_model_t* const sub_model = self->sequence[i]->model;
233 ccv_array_clear(input_symbols);
234 const ccv_array_t* const incomings = self->sequence[i]->incomings;
235 if (incomings)
236 for (j = 0; j < incomings->rnum; j++)
237 {
238 const ccv_cnnp_model_io_t input = *(ccv_cnnp_model_io_t*)ccv_array_get(incomings, j)((void*)(((char*)((incomings)->data)) + (size_t)(incomings
)->rsize * (size_t)(j)))
;
239 if (CCV_CNNP_IS_MODEL_PARAMETER(input)((input)->param_ref != 0 || (input)->param_sel != 0))
240 {
241 if (!parameter_indices)
242 parameter_indices = ccv_array_new(sizeof(int), 0, 0);
243 else
244 ccv_array_clear(parameter_indices);
245 const int param_sel = input->param_sel > 0 ? input->param_sel - 1 : input->param_sel;
246 assert(input->param_sel != 0)((void) sizeof ((input->param_sel != 0) ? 1 : 0), __extension__
({ if (input->param_sel != 0) ; else __assert_fail ("input->param_sel != 0"
, "ccv_cnnp_model_core.c", 246, __extension__ __PRETTY_FUNCTION__
); }))
;
247 ccv_cnnp_model_add_to_parameter_indices(input->model, param_sel, parameter_indices);
248 assert(parameter_indices->rnum > 0)((void) sizeof ((parameter_indices->rnum > 0) ? 1 : 0),
__extension__ ({ if (parameter_indices->rnum > 0) ; else
__assert_fail ("parameter_indices->rnum > 0", "ccv_cnnp_model_core.c"
, 248, __extension__ __PRETTY_FUNCTION__); }))
;
249 const int param_ref = input->param_ref > 0 ? input->param_ref - 1 : input->param_ref;
250 assert(input->param_ref != 0)((void) sizeof ((input->param_ref != 0) ? 1 : 0), __extension__
({ if (input->param_ref != 0) ; else __assert_fail ("input->param_ref != 0"
, "ccv_cnnp_model_core.c", 250, __extension__ __PRETTY_FUNCTION__
); }))
;
251 if (param_ref >= 0)
252 {
253 assert(param_ref < parameter_indices->rnum)((void) sizeof ((param_ref < parameter_indices->rnum) ?
1 : 0), __extension__ ({ if (param_ref < parameter_indices
->rnum) ; else __assert_fail ("param_ref < parameter_indices->rnum"
, "ccv_cnnp_model_core.c", 253, __extension__ __PRETTY_FUNCTION__
); }))
;
254 const ccv_nnc_tensor_symbol_t parameter = ccv_cnnp_parameter_from_indice(super, *(int*)ccv_array_get(parameter_indices, param_ref)((void*)(((char*)((parameter_indices)->data)) + (size_t)(parameter_indices
)->rsize * (size_t)(param_ref)))
);
255 ccv_array_push(input_symbols, &parameter);
256 } else // Otherwise, all of them.
257 for (k = 0; k < parameter_indices->rnum; k++)
258 {
259 const ccv_nnc_tensor_symbol_t parameter = ccv_cnnp_parameter_from_indice(super, *(int*)ccv_array_get(parameter_indices, k)((void*)(((char*)((parameter_indices)->data)) + (size_t)(parameter_indices
)->rsize * (size_t)(k)))
);
260 ccv_array_push(input_symbols, &parameter);
261 }
262 } else {
263 for (k = 0; k < input->model->output_size; k++)
264 ccv_array_push(input_symbols, &input->outputs[k]);
265 }
266 }
267 // Go through each sub model to build the graph.
268 ccv_array_t* nodes;
269 ccv_functional_model_build_node_hook_t hook;
270 const ccv_array_t* const dependencies = self->sequence[i]->dependencies;
271 if ((dependencies && dependencies->rnum > 0) || self->sequence[i]->dependents > 0)
272 {
273 int ret;
274 khiter_t k = kh_put(io_node, io_node_map, (uint64_t)(uintptr_t)self->sequence[i], &ret)kh_put_io_node(io_node_map, (uint64_t)(uintptr_t)self->sequence
[i], &ret)
;
275 if (ret != 0)
276 nodes = kh_val(io_node_map, k)((io_node_map)->vals[k]) = ccv_array_new(sizeof(ccv_nnc_graph_exec_symbol_t), 1, 0);
277 else
278 nodes = kh_val(io_node_map, k)((io_node_map)->vals[k]);
279 hook.nodes = nodes;
280 hook.previous_context = ccv_nnc_graph_exec_symbol_new_hook(graph, _ccv_cnnp_functional_model_build_node_new, &hook, &hook.previous_func);
281 }
282 sub_model->data = self->super.data;
283 ccv_cnnp_model_build(sub_model, graph, (ccv_nnc_tensor_symbol_t*)ccv_array_get(input_symbols, 0)((void*)(((char*)((input_symbols)->data)) + (size_t)(input_symbols
)->rsize * (size_t)(0)))
, input_symbols->rnum, self->sequence[i]->outputs, sub_model->output_size);
284 if ((dependencies && dependencies->rnum > 0) || self->sequence[i]->dependents > 0)
285 {
286 ccv_nnc_graph_exec_symbol_new_hook(graph, hook.previous_func, hook.previous_context, 0);
287 if (dependencies)
288 for (j = 0; j < dependencies->rnum; j++)
289 {
290 const ccv_cnnp_model_io_t dependency = *(ccv_cnnp_model_io_t*)ccv_array_get(dependencies, j)((void*)(((char*)((dependencies)->data)) + (size_t)(dependencies
)->rsize * (size_t)(j)))
;
291 khiter_t k = kh_get(io_node, io_node_map, (uint64_t)(uintptr_t)dependency)kh_get_io_node(io_node_map, (uint64_t)(uintptr_t)dependency);
292 if (k == kh_end(io_node_map)((io_node_map)->n_buckets))
293 continue;
294 const ccv_array_t* const dependency_nodes = kh_val(io_node_map, k)((io_node_map)->vals[k]);
295 int x, y;
296 for (y = 0; y < dependency_nodes->rnum; y++)
297 for (x = 0; x < nodes->rnum; x++)
298 ccv_nnc_graph_exec_symbol_concat(graph, *(ccv_nnc_graph_exec_symbol_t*)ccv_array_get(dependency_nodes, y)((void*)(((char*)((dependency_nodes)->data)) + (size_t)(dependency_nodes
)->rsize * (size_t)(y)))
, *(ccv_nnc_graph_exec_symbol_t*)ccv_array_get(nodes, x)((void*)(((char*)((nodes)->data)) + (size_t)(nodes)->rsize
* (size_t)(x)))
);
299 }
300 }
301 sub_model->data = 0;
302 }
303 khiter_t it;
304 for (it = kh_begin(io_node_map)(khint_t)(0); it != kh_end(io_node_map)((io_node_map)->n_buckets); ++it)
305 {
306 if (!kh_exist(io_node_map, it)(!(((io_node_map)->flags[(it)>>4]>>(((it)&
0xfU)<<1))&3))
)
307 continue;
308 ccv_array_t* const nodes = kh_val(io_node_map, it)((io_node_map)->vals[it]);
309 ccv_array_free(nodes);
310 }
311 kh_destroy(io_node, io_node_map)kh_destroy_io_node(io_node_map);
312 ccv_array_free(input_symbols);
313 if (parameter_indices)
314 ccv_array_free(parameter_indices);
315 for (i = 0, k = 0; k < self->model_output_size; k++)
316 {
317 ccv_cnnp_model_t* const sub_model = self->sequence[self->model_outputs[k]]->model;
318 for (j = 0; j < sub_model->output_size; j++)
319 outputs[i + j] = self->sequence[self->model_outputs[k]]->outputs[j];
320 i += sub_model->output_size;
321 }
322 assert(i == output_size)((void) sizeof ((i == output_size) ? 1 : 0), __extension__ ({
if (i == output_size) ; else __assert_fail ("i == output_size"
, "ccv_cnnp_model_core.c", 322, __extension__ __PRETTY_FUNCTION__
); }))
;
323 PRINT(CCV_CLI_VERBOSE, "[cnnp_functional_model_build] 2. %p\n", self)do { if ((CCV_CLI_VERBOSE & ccv_cli_get_output_levels()))
{ printf("[cnnp_functional_model_build] 2. %p\n", self); fflush
(stdout); } } while (0)
;
324}
325
326static void _ccv_cnnp_functional_model_init_states(ccv_cnnp_model_t* const super, ccv_nnc_symbolic_graph_t* const graph, const ccv_cnnp_state_initializer_f initializer, void* const context)
327{
328 ccv_cnnp_functional_model_t* const self = (ccv_cnnp_functional_model_t*)super;
329 int i;
330 for (i = self->super.input_size; i < self->sequence_size; i++)
331 ccv_cnnp_model_init_states(self->sequence[i]->model, graph, initializer, context);
332}
333
334static void _ccv_cnnp_functional_model_set_is_test(ccv_cnnp_model_t* const super, const int is_test, const ccv_cnnp_cmd_updater_f updater, void* const context)
335{
336 ccv_cnnp_functional_model_t* const self = (ccv_cnnp_functional_model_t*)super;
337 int i;
338 for (i = self->super.input_size; i < self->sequence_size; i++)
339 ccv_cnnp_model_set_is_test(self->sequence[i]->model, is_test, updater, context);
340}
341
342static void _ccv_cnnp_functional_model_add_to_parameter_indices(ccv_cnnp_model_t* const super, const int index, ccv_array_t* const parameter_indices)
343{
344 ccv_cnnp_functional_model_t* const self = (ccv_cnnp_functional_model_t*)super;
345 int i;
346 for (i = self->super.input_size; i < self->sequence_size; i++)
347 ccv_cnnp_model_add_to_parameter_indices(self->sequence[i]->model, index, parameter_indices);
348}
349
350static void _ccv_cnnp_functional_model_notify(const ccv_cnnp_model_t* const super, const int tag, void* const payload)
351{
352 ccv_cnnp_functional_model_t* const self = (ccv_cnnp_functional_model_t*)super;
353 int i;
354 for (i = 0; i < self->sequence_size; i++)
355 {
356 const ccv_cnnp_model_t* const model = self->sequence[i]->model;
357 ccv_cnnp_model_notify(model, tag, payload);
358 }
359}
360
361static ccv_cnnp_model_t* _ccv_cnnp_functional_model_copy(const ccv_cnnp_model_t* const super, void* const context);
362
363static const ccv_cnnp_model_vtab_t ccv_cnnp_functional_model_isa = {
364 .deinit = _ccv_cnnp_functional_model_deinit,
365 .dealloc = _ccv_cnnp_functional_model_dealloc,
366 .build = _ccv_cnnp_functional_model_build,
367 .init_states = _ccv_cnnp_functional_model_init_states,
368 .copy = _ccv_cnnp_functional_model_copy,
369 .set_is_test = _ccv_cnnp_functional_model_set_is_test,
370 .add_to_parameter_indices = _ccv_cnnp_functional_model_add_to_parameter_indices,
371 .notify = _ccv_cnnp_functional_model_notify,
372};
373
374KHASH_MAP_INIT_INT64(model_io, ccv_cnnp_model_io_t)typedef struct kh_model_io_s { khint_t n_buckets, size, n_occupied
, upper_bound; khint32_t *flags; khint64_t *keys; ccv_cnnp_model_io_t
*vals; } kh_model_io_t; static inline __attribute__ ((__unused__
)) kh_model_io_t *kh_init_model_io(void) { return (kh_model_io_t
*)calloc(1,sizeof(kh_model_io_t)); } static inline __attribute__
((__unused__)) void kh_destroy_model_io(kh_model_io_t *h) { if
(h) { free((void *)h->keys); free(h->flags); free((void
*)h->vals); free(h); } } static inline __attribute__ ((__unused__
)) void kh_clear_model_io(kh_model_io_t *h) { if (h &&
h->flags) { memset(h->flags, 0xaa, ((h->n_buckets) <
16? 1 : (h->n_buckets)>>4) * sizeof(khint32_t)); h->
size = h->n_occupied = 0; } } static inline __attribute__ (
(__unused__)) khint_t kh_get_model_io(const kh_model_io_t *h,
khint64_t key) { if (h->n_buckets) { khint_t k, i, last, mask
, step = 0; mask = h->n_buckets - 1; k = (khint32_t)((key)
>>33^(key)^(key)<<11); i = k & mask; last = i
; while (!((h->flags[i>>4]>>((i&0xfU)<<
1))&2) && (((h->flags[i>>4]>>((i&
0xfU)<<1))&1) || !((h->keys[i]) == (key)))) { i =
(i + (++step)) & mask; if (i == last) return h->n_buckets
; } return ((h->flags[i>>4]>>((i&0xfU)<<
1))&3)? h->n_buckets : i; } else return 0; } static inline
__attribute__ ((__unused__)) int kh_resize_model_io(kh_model_io_t
*h, khint_t new_n_buckets) { khint32_t *new_flags = 0; khint_t
j = 1; { (--(new_n_buckets), (new_n_buckets)|=(new_n_buckets
)>>1, (new_n_buckets)|=(new_n_buckets)>>2, (new_n_buckets
)|=(new_n_buckets)>>4, (new_n_buckets)|=(new_n_buckets)
>>8, (new_n_buckets)|=(new_n_buckets)>>16, ++(new_n_buckets
)); if (new_n_buckets < 4) new_n_buckets = 4; if (h->size
>= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0
; else { new_flags = (khint32_t*)malloc(((new_n_buckets) <
16? 1 : (new_n_buckets)>>4) * sizeof(khint32_t)); if (
!new_flags) return -1; memset(new_flags, 0xaa, ((new_n_buckets
) < 16? 1 : (new_n_buckets)>>4) * sizeof(khint32_t))
; if (h->n_buckets < new_n_buckets) { khint64_t *new_keys
= (khint64_t*)realloc((void *)h->keys,new_n_buckets * sizeof
(khint64_t)); if (!new_keys) { free(new_flags); return -1; } h
->keys = new_keys; if (1) { ccv_cnnp_model_io_t *new_vals =
(ccv_cnnp_model_io_t*)realloc((void *)h->vals,new_n_buckets
* sizeof(ccv_cnnp_model_io_t)); if (!new_vals) { free(new_flags
); return -1; } h->vals = new_vals; } } } } if (j) { for (
j = 0; j != h->n_buckets; ++j) { if (((h->flags[j>>
4]>>((j&0xfU)<<1))&3) == 0) { khint64_t key
= h->keys[j]; ccv_cnnp_model_io_t val; khint_t new_mask; new_mask
= new_n_buckets - 1; if (1) val = h->vals[j]; (h->flags
[j>>4]|=1ul<<((j&0xfU)<<1)); while (1) {
khint_t k, i, step = 0; k = (khint32_t)((key)>>33^(key
)^(key)<<11); i = k & new_mask; while (!((new_flags
[i>>4]>>((i&0xfU)<<1))&2)) i = (i +
(++step)) & new_mask; (new_flags[i>>4]&=~(2ul<<
((i&0xfU)<<1))); if (i < h->n_buckets &&
((h->flags[i>>4]>>((i&0xfU)<<1))&
3) == 0) { { khint64_t tmp = h->keys[i]; h->keys[i] = key
; key = tmp; } if (1) { ccv_cnnp_model_io_t tmp = h->vals[
i]; h->vals[i] = val; val = tmp; } (h->flags[i>>4
]|=1ul<<((i&0xfU)<<1)); } else { h->keys[i
] = key; if (1) h->vals[i] = val; break; } } } } if (h->
n_buckets > new_n_buckets) { h->keys = (khint64_t*)realloc
((void *)h->keys,new_n_buckets * sizeof(khint64_t)); if (1
) h->vals = (ccv_cnnp_model_io_t*)realloc((void *)h->vals
,new_n_buckets * sizeof(ccv_cnnp_model_io_t)); } free(h->flags
); h->flags = new_flags; h->n_buckets = new_n_buckets; h
->n_occupied = h->size; h->upper_bound = (khint_t)(h
->n_buckets * __ac_HASH_UPPER + 0.5); } return 0; } static
inline __attribute__ ((__unused__)) khint_t kh_put_model_io(
kh_model_io_t *h, khint64_t key, int *ret) { khint_t x; if (h
->n_occupied >= h->upper_bound) { if (h->n_buckets
> (h->size<<1)) { if (kh_resize_model_io(h, h->
n_buckets - 1) < 0) { *ret = -1; return h->n_buckets; }
} else if (kh_resize_model_io(h, h->n_buckets + 1) < 0
) { *ret = -1; return h->n_buckets; } } { khint_t k, i, site
, last, mask = h->n_buckets - 1, step = 0; x = site = h->
n_buckets; k = (khint32_t)((key)>>33^(key)^(key)<<
11); i = k & mask; if (((h->flags[i>>4]>>(
(i&0xfU)<<1))&2)) x = i; else { last = i; while
(!((h->flags[i>>4]>>((i&0xfU)<<1))&
2) && (((h->flags[i>>4]>>((i&0xfU)
<<1))&1) || !((h->keys[i]) == (key)))) { if (((h
->flags[i>>4]>>((i&0xfU)<<1))&1)
) site = i; i = (i + (++step)) & mask; if (i == last) { x
= site; break; } } if (x == h->n_buckets) { if (((h->flags
[i>>4]>>((i&0xfU)<<1))&2) &&
site != h->n_buckets) x = site; else x = i; } } } if (((h
->flags[x>>4]>>((x&0xfU)<<1))&2)
) { h->keys[x] = key; (h->flags[x>>4]&=~(3ul<<
((x&0xfU)<<1))); ++h->size; ++h->n_occupied; *
ret = 1; } else if (((h->flags[x>>4]>>((x&
0xfU)<<1))&1)) { h->keys[x] = key; (h->flags[
x>>4]&=~(3ul<<((x&0xfU)<<1))); ++h->
size; *ret = 2; } else *ret = 0; return x; } static inline __attribute__
((__unused__)) void kh_del_model_io(kh_model_io_t *h, khint_t
x) { if (x != h->n_buckets && !((h->flags[x>>
4]>>((x&0xfU)<<1))&3)) { (h->flags[x>>
4]|=1ul<<((x&0xfU)<<1)); --h->size; } }
14
Taking true branch
15
Taking false branch
16
Calling 'kh_resize_model_io'
17
Taking true branch
18
Assuming the condition is false
19
Taking false branch
20
'?' condition is true
21
Assuming 'new_flags' is non-null
22
Taking false branch
23
'?' condition is true
24
Taking true branch
25
Storing uninitialized value
26
Assuming 'new_keys' is non-null
27
Taking false branch
28
Taking true branch
29
Assuming 'new_vals' is non-null
30
Taking false branch
31
Taking true branch
32
Loop condition is false. Execution continues on line 374
33
Taking false branch
34
Returning from 'kh_resize_model_io'
35
Taking false branch
36
Assuming right operand of bit shift is less than 32
37
Assuming the condition is true
38
Taking true branch
39
Assuming the condition is false
40
Taking false branch
41
Assuming the condition is false
42
Taking false branch
48
Assuming field 'n_occupied' is >= field 'upper_bound'
49
Taking true branch
50
Taking true branch
51
Calling 'kh_resize_model_io'
52
Taking false branch
53
Assuming the condition is false
54
Taking false branch
55
'?' condition is true
56
Assuming 'new_flags' is non-null
57
Taking false branch
58
'?' condition is true
59
Taking false branch
60
Taking true branch
61
The value 0 is assigned to 'j'
62
Loop condition is true. Entering loop body
63
Assuming the condition is true
64
Taking true branch
65
Assigned value is garbage or undefined
375
376static ccv_cnnp_model_t* _ccv_cnnp_functional_model_copy(const ccv_cnnp_model_t* const super, void* const context)
377{
378 const ccv_cnnp_functional_model_t* const self = (const ccv_cnnp_functional_model_t*)super;
379 ccv_cnnp_functional_model_t* const functional_model = (ccv_cnnp_functional_model_t*)cccalloccalloc(1, sizeof(ccv_cnnp_functional_model_t) + sizeof(ccv_cnnp_model_t*) * (self->sequence_size - 1) + sizeof(ccv_nnc_tensor_symbol_t) * self->super.output_size + sizeof(int) * self->model_output_size);
380 functional_model->super.isa = &ccv_cnnp_functional_model_isa;
381 functional_model->super.outputs = (ccv_nnc_tensor_symbol_t*)(functional_model->sequence + self->sequence_size);
382 functional_model->super.output_size = self->super.output_size;
383 functional_model->super.input_size = self->super.input_size;
384 ccv_cnnp_model_copy_name(&functional_model->super, self->super.name);
385 functional_model->sequence_size = self->sequence_size;
386 functional_model->model_output_size = self->model_output_size;
387 functional_model->model_outputs = (int*)(functional_model->super.outputs + functional_model->super.output_size);
388 memcpy(functional_model->model_outputs, self->model_outputs, sizeof(int) * self->model_output_size);
389 // Now the difficult part, copy over the model_io.
390 khash_t(model_io)kh_model_io_t* model_io_map = kh_init(model_io)kh_init_model_io();
391 khash_t(model)kh_model_t* model_map = context ? (khash_t(model)kh_model_t*)context : kh_init(model)kh_init_model();
1
Assuming 'context' is null
2
'?' condition is false
392 int i, j;
393 for (i = 0; i < self->sequence_size; i++)
3
Assuming 'i' is >= field 'sequence_size'
4
Loop condition is false. Execution continues on line 419
394 {
395 const ccv_cnnp_model_t* const sub_model = self->sequence[i]->model;
396 int ret;
397 khiter_t k = kh_put(model, model_map, (uint64_t)(uintptr_t)sub_model, &ret)kh_put_model(model_map, (uint64_t)(uintptr_t)sub_model, &
ret)
;
398 ccv_cnnp_model_t* model_copy;
399 if (ret != 0)
400 model_copy = kh_val(model_map, k)((model_map)->vals[k]) = _ccv_cnnp_model_copy(sub_model, model_map);
401 else
402 model_copy = kh_val(model_map, k)((model_map)->vals[k]);
403 ccv_cnnp_model_io_t model_io = functional_model->sequence[i] = ccmallocmalloc(sizeof(struct ccv_cnnp_model_io_s) + sizeof(ccv_nnc_tensor_symbol_t) * sub_model->output_size);
404 model_io->param_ref = 0;
405 model_io->param_sel = 0;
406 model_io->visit = 0;
407 model_io->model = model_copy;
408 model_io->dependencies = 0;
409 model_io->dependents = 0;
410 model_io->incomings = 0;
411 model_io->outgoings = 0;
412 model_io->outputs = (ccv_nnc_tensor_symbol_t*)(model_io + 1);
413 if (!model_copy->io)
414 model_copy->io = ccv_array_new(sizeof(ccv_cnnp_model_io_t), 1, 0);
415 ccv_array_push(model_copy->io, &model_io);
416 k = kh_put(model_io, model_io_map, (uint64_t)(uintptr_t)self->sequence[i], &ret)kh_put_model_io(model_io_map, (uint64_t)(uintptr_t)self->sequence
[i], &ret)
;
417 kh_val(model_io_map, k)((model_io_map)->vals[k]) = functional_model->sequence[i];
418 }
419 for (i = self->super.input_size; i < self->sequence_size; i++)
5
Assuming 'i' is < field 'sequence_size'
6
Loop condition is true. Entering loop body
420 {
421 if (self->sequence[i]->incomings)
7
Assuming field 'incomings' is non-null
8
Taking true branch
422 for (j = 0; j < self->sequence[i]->incomings->rnum; j++)
9
Loop condition is true. Entering loop body
45
Loop condition is true. Entering loop body
423 {
424 const ccv_cnnp_model_io_t input = *(ccv_cnnp_model_io_t*)ccv_array_get(self->sequence[i]->incomings, j)((void*)(((char*)((self->sequence[i]->incomings)->data
)) + (size_t)(self->sequence[i]->incomings)->rsize *
(size_t)(j)))
;
425 if (CCV_CNNP_IS_MODEL_PARAMETER(input)((input)->param_ref != 0 || (input)->param_sel != 0)) // I am pretty sure this is not in the model_io_map.
10
Assuming field 'param_ref' is equal to 0
11
Assuming field 'param_sel' is not equal to 0
12
Taking true branch
46
Assuming field 'param_ref' is not equal to 0
426 {
427 int ret;
428 khiter_t k = kh_put(model_io, model_io_map, (uint64_t)(uintptr_t)input, &ret)kh_put_model_io(model_io_map, (uint64_t)(uintptr_t)input, &
ret)
;
13
Calling 'kh_put_model_io'
43
Returning from 'kh_put_model_io'
47
Calling 'kh_put_model_io'
429 if (ret
43.1
'ret' is equal to 0
!= 0)
44
Taking false branch
430 {
431 // The model may not exist on the map due to wrapping (it is inside another sequential or functional model).
432 khiter_t m = kh_get(model, model_map, (uint64_t)(uintptr_t)input->model)kh_get_model(model_map, (uint64_t)(uintptr_t)input->model);
433 assert(m != kh_end(model_map))((void) sizeof ((m != ((model_map)->n_buckets)) ? 1 : 0), __extension__
({ if (m != ((model_map)->n_buckets)) ; else __assert_fail
("m != kh_end(model_map)", "ccv_cnnp_model_core.c", 433, __extension__
__PRETTY_FUNCTION__); }))
;
434 ccv_cnnp_model_t* const model_copy = kh_val(model_map, m)((model_map)->vals[m]);
435 ccv_cnnp_model_io_t model_io = ccmallocmalloc(sizeof(struct ccv_cnnp_model_io_s));
436 model_io->param_ref = input->param_ref;
437 model_io->param_sel = input->param_sel;
438 model_io->visit = 0;
439 model_io->model = model_copy;
440 model_io->incomings = 0;
441 model_io->dependencies = 0;
442 model_io->dependents = 0;
443 model_io->outgoings = 0;
444 model_io->outputs = 0;
445 if (!model_copy->io)
446 model_copy->io = ccv_array_new(sizeof(ccv_cnnp_model_io_t), 1, 0);
447 ccv_array_push(model_copy->io, &model_io);
448 kh_val(model_io_map, k)((model_io_map)->vals[k]) = model_io;
449 if (input->outgoings)
450 {
451 model_io->outgoings = ccv_array_new(sizeof(ccv_cnnp_model_io_t), input->outgoings->rnum, 0);
452 int x;
453 for (x = 0; x < input->outgoings->rnum; x++)
454 {
455 khiter_t k = kh_get(model_io, model_io_map, (uint64_t)(uintptr_t)(*(ccv_cnnp_model_io_t*)ccv_array_get(input->outgoings, x)))kh_get_model_io(model_io_map, (uint64_t)(uintptr_t)(*(ccv_cnnp_model_io_t
*)((void*)(((char*)((input->outgoings)->data)) + (size_t
)(input->outgoings)->rsize * (size_t)(x)))))
;
456 assert(k != kh_end(model_io_map))((void) sizeof ((k != ((model_io_map)->n_buckets)) ? 1 : 0
), __extension__ ({ if (k != ((model_io_map)->n_buckets)) ;
else __assert_fail ("k != kh_end(model_io_map)", "ccv_cnnp_model_core.c"
, 456, __extension__ __PRETTY_FUNCTION__); }))
;
457 ccv_cnnp_model_io_t outgoing_io = kh_val(model_io_map, k)((model_io_map)->vals[k]);
458 ccv_array_push(model_io->outgoings, &outgoing_io);
459 }
460 }
461 }
462 }
463 }
464 }
465 if (!context)
466 kh_destroy(model, model_map)kh_destroy_model(model_map);
467 for (i = 0; i < self->sequence_size; i++)
468 {
469 const ccv_cnnp_model_io_t model_io = self->sequence[i];
470 ccv_cnnp_model_io_t model_io_copy = functional_model->sequence[i];
471 model_io_copy->param_ref = model_io->param_ref;
472 model_io_copy->param_sel = model_io->param_sel;
473 if (model_io->incomings)
474 {
475 model_io_copy->incomings = ccv_array_new(sizeof(ccv_cnnp_model_io_t), model_io->incomings->rnum, 0);
476 for (j = 0; j < model_io->incomings->rnum; j++)
477 {
478 khiter_t k = kh_get(model_io, model_io_map, (uint64_t)(uintptr_t)(*(ccv_cnnp_model_io_t*)ccv_array_get(model_io->incomings, j)))kh_get_model_io(model_io_map, (uint64_t)(uintptr_t)(*(ccv_cnnp_model_io_t
*)((void*)(((char*)((model_io->incomings)->data)) + (size_t
)(model_io->incomings)->rsize * (size_t)(j)))))
;
479 assert(k != kh_end(model_io_map))((void) sizeof ((k != ((model_io_map)->n_buckets)) ? 1 : 0
), __extension__ ({ if (k != ((model_io_map)->n_buckets)) ;
else __assert_fail ("k != kh_end(model_io_map)", "ccv_cnnp_model_core.c"
, 479, __extension__ __PRETTY_FUNCTION__); }))
;
480 ccv_cnnp_model_io_t input_io = kh_val(model_io_map, k)((model_io_map)->vals[k]);
481 ccv_array_push(model_io_copy->incomings, &input_io);
482 }
483 }
484 if (model_io->dependencies)
485 {
486 model_io_copy->dependencies = ccv_array_new(sizeof(ccv_cnnp_model_io_t), model_io->dependencies->rnum, 0);
487 for (j = 0; j < model_io->dependencies->rnum; j++)
488 {
489 khiter_t k = kh_get(model_io, model_io_map, (uint64_t)(uintptr_t)(*(ccv_cnnp_model_io_t*)ccv_array_get(model_io->dependencies, j)))kh_get_model_io(model_io_map, (uint64_t)(uintptr_t)(*(ccv_cnnp_model_io_t
*)((void*)(((char*)((model_io->dependencies)->data)) + (
size_t)(model_io->dependencies)->rsize * (size_t)(j))))
)
;
490 assert(k != kh_end(model_io_map))((void) sizeof ((k != ((model_io_map)->n_buckets)) ? 1 : 0
), __extension__ ({ if (k != ((model_io_map)->n_buckets)) ;
else __assert_fail ("k != kh_end(model_io_map)", "ccv_cnnp_model_core.c"
, 490, __extension__ __PRETTY_FUNCTION__); }))
;
491 ccv_cnnp_model_io_t input_io = kh_val(model_io_map, k)((model_io_map)->vals[k]);
492 ccv_array_push(model_io_copy->dependencies, &input_io);
493 }
494 }
495 model_io_copy->dependents = model_io->dependents;
496 if (model_io->outgoings)
497 {
498 model_io_copy->outgoings = ccv_array_new(sizeof(ccv_cnnp_model_io_t), model_io->outgoings->rnum, 0);
499 for (j = 0; j < model_io->outgoings->rnum; j++)
500 {
501 khiter_t k = kh_get(model_io, model_io_map, (uint64_t)(uintptr_t)(*(ccv_cnnp_model_io_t*)ccv_array_get(model_io->outgoings, j)))kh_get_model_io(model_io_map, (uint64_t)(uintptr_t)(*(ccv_cnnp_model_io_t
*)((void*)(((char*)((model_io->outgoings)->data)) + (size_t
)(model_io->outgoings)->rsize * (size_t)(j)))))
;
502 assert(k != kh_end(model_io_map))((void) sizeof ((k != ((model_io_map)->n_buckets)) ? 1 : 0
), __extension__ ({ if (k != ((model_io_map)->n_buckets)) ;
else __assert_fail ("k != kh_end(model_io_map)", "ccv_cnnp_model_core.c"
, 502, __extension__ __PRETTY_FUNCTION__); }))
;
503 ccv_cnnp_model_io_t outgoing_io = kh_val(model_io_map, k)((model_io_map)->vals[k]);
504 ccv_array_push(model_io_copy->outgoings, &outgoing_io);
505 }
506 }
507 }
508 kh_destroy(model_io, model_io_map)kh_destroy_model_io(model_io_map);
509 return (ccv_cnnp_model_t*)functional_model;
510}
511
512ccv_cnnp_model_t* ccv_cnnp_model_new(const ccv_cnnp_model_io_t* const inputs, const int input_size, const ccv_cnnp_model_io_t* const outputs, const int output_size, const int is_trainable, const char* const name)
513{
514 assert(output_size > 0)((void) sizeof ((output_size > 0) ? 1 : 0), __extension__ (
{ if (output_size > 0) ; else __assert_fail ("output_size > 0"
, "ccv_cnnp_model_core.c", 514, __extension__ __PRETTY_FUNCTION__
); }))
;
515 // Do topological sort.
516 ccv_array_t* const reverse_top = ccv_array_new(sizeof(ccv_cnnp_model_io_t), output_size, 0);
517 int i, j, k;
518 // Go through output one by one, reverse traversal them, to detect potential overlap (overlap means, for example,
519 // outputs[1] is an incoming node for outputs[0]. Thus, if we reverse them, we may have outputs[0] build before outputs[1],
520 // hence, having issues.
521 for (i = 0; i < output_size; i++)
522 outputs[i]->visit = 2;
523 for (i = output_size - 1; i >= 0; i--)
524 {
525 if (outputs[i]->visit == 3) // If we need to remove it, no need to visit.
526 continue;
527 assert(outputs[i]->visit == 2)((void) sizeof ((outputs[i]->visit == 2) ? 1 : 0), __extension__
({ if (outputs[i]->visit == 2) ; else __assert_fail ("outputs[i]->visit == 2"
, "ccv_cnnp_model_core.c", 527, __extension__ __PRETTY_FUNCTION__
); }))
;
528 ccv_array_clear(reverse_top);
529 ccv_array_push(reverse_top, &outputs[i]);
530 for (j = 0; j < reverse_top->rnum; j++)
531 {
532 const ccv_cnnp_model_io_t output = *(ccv_cnnp_model_io_t*)ccv_array_get(reverse_top, j)((void*)(((char*)((reverse_top)->data)) + (size_t)(reverse_top
)->rsize * (size_t)(j)))
;
533 assert(!CCV_CNNP_IS_MODEL_INPUT(output->model))((void) sizeof ((!((output->model)->isa == &ccv_cnnp_input_isa
)) ? 1 : 0), __extension__ ({ if (!((output->model)->isa
== &ccv_cnnp_input_isa)) ; else __assert_fail ("!CCV_CNNP_IS_MODEL_INPUT(output->model)"
, "ccv_cnnp_model_core.c", 533, __extension__ __PRETTY_FUNCTION__
); }))
;
534 // If it is input, push it here.
535 if (output->incomings && !CCV_CNNP_IS_MODEL_PARAMETER(output)((output)->param_ref != 0 || (output)->param_sel != 0))
536 for (k = 0; k < output->incomings->rnum; k++)
537 {
538 const ccv_cnnp_model_io_t input = *(ccv_cnnp_model_io_t*)ccv_array_get(output->incomings, k)((void*)(((char*)((output->incomings)->data)) + (size_t
)(output->incomings)->rsize * (size_t)(k)))
;
539 // If it is an input or parameter, skip.
540 if (CCV_CNNP_IS_MODEL_INPUT(input->model)((input->model)->isa == &ccv_cnnp_input_isa) || CCV_CNNP_IS_MODEL_PARAMETER(input)((input)->param_ref != 0 || (input)->param_sel != 0))
541 continue;
542 if (input->visit == 1 || input->visit == 3) // Visited, skip.
543 continue;
544 // If this is an output, we need to remove it from the output array. Otherwise mark it as visited.
545 input->visit = input->visit == 2 ? 3 : 1;
546 ccv_array_push(reverse_top, &input);
547 }
548 // Similar for dependencies.
549 if (output->dependencies && !CCV_CNNP_IS_MODEL_PARAMETER(output)((output)->param_ref != 0 || (output)->param_sel != 0))
550 for (k = 0; k < output->dependencies->rnum; k++)
551 {
552 const ccv_cnnp_model_io_t dependency = *(ccv_cnnp_model_io_t*)ccv_array_get(output->dependencies, k)((void*)(((char*)((output->dependencies)->data)) + (size_t
)(output->dependencies)->rsize * (size_t)(k)))
;
553 // If it is an input or parameter, skip.
554 if (CCV_CNNP_IS_MODEL_INPUT(dependency->model)((dependency->model)->isa == &ccv_cnnp_input_isa) || CCV_CNNP_IS_MODEL_PARAMETER(dependency)((dependency)->param_ref != 0 || (dependency)->param_sel
!= 0)
)
555 continue;
556 if (dependency->visit == 1 || dependency->visit == 3) // Visited, skip.
557 continue;
558 // If this is an output, we need to remove it from the output array. Otherwise mark it as visited.
559 dependency->visit = dependency->visit == 2 ? 3 : 1;
560 ccv_array_push(reverse_top, &dependency);
561 }
562 }
563 for (j = 1; j < reverse_top->rnum; j++)
564 {
565 const ccv_cnnp_model_io_t output = *(ccv_cnnp_model_io_t*)ccv_array_get(reverse_top, j)((void*)(((char*)((reverse_top)->data)) + (size_t)(reverse_top
)->rsize * (size_t)(j)))
;
566 if (output->visit == 1) // Clean the visit back.
567 output->visit = 0;
568 }
569 }
570 ccv_array_clear(reverse_top);
571 for (i = 0; i < output_size; i++) // We will assign sequence in reverse order, thus, reverse the reverse top when copying the outputs.
572 {
573 if (outputs[output_size - 1 - i]->visit == 2)
574 ccv_array_push(reverse_top, &outputs[output_size - 1 - i]);
575 assert(outputs[output_size - 1 - i]->visit == 2 || outputs[output_size - 1 - i]->visit == 3)((void) sizeof ((outputs[output_size - 1 - i]->visit == 2 ||
outputs[output_size - 1 - i]->visit == 3) ? 1 : 0), __extension__
({ if (outputs[output_size - 1 - i]->visit == 2 || outputs
[output_size - 1 - i]->visit == 3) ; else __assert_fail ("outputs[output_size - 1 - i]->visit == 2 || outputs[output_size - 1 - i]->visit == 3"
, "ccv_cnnp_model_core.c", 575, __extension__ __PRETTY_FUNCTION__
); }))
;
576 outputs[output_size - 1 - i]->visit = 0; // Clean up all visits.
577 }
578 // Go from the output, until we meet inputs.
579 uint64_t input_bitmask[((input_size - 1) >> 6) + 1];
580 memset(input_bitmask, 0, sizeof(uint64_t) * (((input_size - 1) >> 6) + 1));
581 int tensor_output_size = 0; // io can be mapped to multiple tensor outputs, therefore, need to compute the exact tensor output size.
582 for (i = 0; i < output_size; i++)
583 tensor_output_size += outputs[i]->model->output_size;
584 for (i = 0; i < reverse_top->rnum; i++)
585 {
586 const ccv_cnnp_model_io_t output = *(ccv_cnnp_model_io_t*)ccv_array_get(reverse_top, i)((void*)(((char*)((reverse_top)->data)) + (size_t)(reverse_top
)->rsize * (size_t)(i)))
;
587 assert(!CCV_CNNP_IS_MODEL_INPUT(output->model))((void) sizeof ((!((output->model)->isa == &ccv_cnnp_input_isa
)) ? 1 : 0), __extension__ ({ if (!((output->model)->isa
== &ccv_cnnp_input_isa)) ; else __assert_fail ("!CCV_CNNP_IS_MODEL_INPUT(output->model)"
, "ccv_cnnp_model_core.c", 587, __extension__ __PRETTY_FUNCTION__
); }))
;
588 // If it is input, push it here.
589 if (output->incomings && !CCV_CNNP_IS_MODEL_PARAMETER(output)((output)->param_ref != 0 || (output)->param_sel != 0))
590 for (j = 0; j < output->incomings->rnum; j++)
591 {
592 const ccv_cnnp_model_io_t input = *(ccv_cnnp_model_io_t*)ccv_array_get(output->incomings, j)((void*)(((char*)((output->incomings)->data)) + (size_t
)(output->incomings)->rsize * (size_t)(j)))
;
593 ++input->visit; // Mark it as visited.
594 if (input->visit != input->outgoings->rnum + input->dependents) // Not all dependencies visited.
595 continue;
596 if (!CCV_CNNP_IS_MODEL_INPUT(input->model)((input->model)->isa == &ccv_cnnp_input_isa) && !CCV_CNNP_IS_MODEL_PARAMETER(input)((input)->param_ref != 0 || (input)->param_sel != 0))
597 ccv_array_push(reverse_top, &input);
598 else if (CCV_CNNP_IS_MODEL_INPUT(input->model)((input->model)->isa == &ccv_cnnp_input_isa)) {
599 for (k = 0; k < input_size; k++)
600 if (input == inputs[k])
601 break;
602 assert(k < input_size)((void) sizeof ((k < input_size) ? 1 : 0), __extension__ (
{ if (k < input_size) ; else __assert_fail ("k < input_size"
, "ccv_cnnp_model_core.c", 602, __extension__ __PRETTY_FUNCTION__
); }))
;
603 input_bitmask[k >> 6] |= ((uint64_t)1 << (k & 63));
604 }
605 }
606 if (output->dependencies && !CCV_CNNP_IS_MODEL_PARAMETER(output)((output)->param_ref != 0 || (output)->param_sel != 0))
607 for (j = 0; j < output->dependencies->rnum; j++)
608 {
609 const ccv_cnnp_model_io_t dependency = *(ccv_cnnp_model_io_t*)ccv_array_get(output->dependencies, j)((void*)(((char*)((output->dependencies)->data)) + (size_t
)(output->dependencies)->rsize * (size_t)(j)))
;
610 ++dependency->visit; // Mark it as visited.
611 if (dependency->visit != (dependency->outgoings ? dependency->outgoings->rnum : 0) + dependency->dependents) // Not all dependencies visited.
612 continue;
613 if (!CCV_CNNP_IS_MODEL_INPUT(dependency->model)((dependency->model)->isa == &ccv_cnnp_input_isa) && !CCV_CNNP_IS_MODEL_PARAMETER(dependency)((dependency)->param_ref != 0 || (dependency)->param_sel
!= 0)
)
614 ccv_array_push(reverse_top, &dependency);
615 else if (CCV_CNNP_IS_MODEL_INPUT(dependency->model)((dependency->model)->isa == &ccv_cnnp_input_isa)) {
616 for (k = 0; k < input_size; k++)
617 if (dependency == inputs[k])
618 break;
619 assert(k < input_size)((void) sizeof ((k < input_size) ? 1 : 0), __extension__ (
{ if (k < input_size) ; else __assert_fail ("k < input_size"
, "ccv_cnnp_model_core.c", 619, __extension__ __PRETTY_FUNCTION__
); }))
;
620 input_bitmask[k >> 6] |= ((uint64_t)1 << (k & 63));
621 }
622 }
623 }
624 for (i = 0; i < reverse_top->rnum; i++)
625 {
626 const ccv_cnnp_model_io_t output = *(ccv_cnnp_model_io_t*)ccv_array_get(reverse_top, i)((void*)(((char*)((reverse_top)->data)) + (size_t)(reverse_top
)->rsize * (size_t)(i)))
;
627 output->visit = 0; // Clean the visit back.
628 }
629 for (i = 0; i < input_size; i++)
630 inputs[i]->visit = 0; // Clean the visit back.
631 for (i = 0; i < input_size; i++)
632 { assert((input_bitmask[i >> 6] & ((uint64_t)1 << (i & 63))))((void) sizeof (((input_bitmask[i >> 6] & ((uint64_t
)1 << (i & 63)))) ? 1 : 0), __extension__ ({ if ((input_bitmask
[i >> 6] & ((uint64_t)1 << (i & 63)))) ; else
__assert_fail ("(input_bitmask[i >> 6] & ((uint64_t)1 << (i & 63)))"
, "ccv_cnnp_model_core.c", 632, __extension__ __PRETTY_FUNCTION__
); }))
; } // Assuming they all match.
633 const int sequence_size = reverse_top->rnum + input_size;
634 ccv_cnnp_functional_model_t* const functional_model = (ccv_cnnp_functional_model_t*)cccalloccalloc(1, sizeof(ccv_cnnp_functional_model_t) + sizeof(ccv_cnnp_model_t*) * (sequence_size - 1) + sizeof(ccv_nnc_tensor_symbol_t) * tensor_output_size + sizeof(int) * output_size);
635 functional_model->super.isa = &ccv_cnnp_functional_model_isa;
636 functional_model->super.outputs = (ccv_nnc_tensor_symbol_t*)(functional_model->sequence + sequence_size);
637 functional_model->super.output_size = tensor_output_size;
638 functional_model->super.input_size = input_size;
639 functional_model->super.is_trainable = is_trainable;
640 functional_model->model_output_size = output_size;
641 functional_model->model_outputs = (int*)(functional_model->super.outputs + tensor_output_size);
642 ccv_cnnp_model_copy_name(&functional_model->super, name);
643 functional_model->sequence_size = sequence_size;
644 memcpy(functional_model->sequence, inputs, sizeof(ccv_cnnp_model_io_t) * input_size);
645 for (i = 0; i < reverse_top->rnum; i++)
646 functional_model->sequence[input_size + i] = *(ccv_cnnp_model_io_t*)ccv_array_get(reverse_top, reverse_top->rnum - 1 - i)((void*)(((char*)((reverse_top)->data)) + (size_t)(reverse_top
)->rsize * (size_t)(reverse_top->rnum - 1 - i)))
;
647 for (i = 0; i < output_size; i++)
648 {
649 for (j = sequence_size - 1; j >= input_size; j--)
650 if (functional_model->sequence[j] == outputs[i])
651 {
652 functional_model->model_outputs[i] = j;
653 break;
654 }
655 }
656 ccv_array_free(reverse_top);
657 return (ccv_cnnp_model_t*)functional_model;
658}
659
660static ccv_cnnp_model_t* _ccv_cnnp_input_copy(const ccv_cnnp_model_t* const self, void* const context)
661{
662 ccv_cnnp_model_t* const input = (ccv_cnnp_model_t*)cccalloccalloc(1, sizeof(ccv_cnnp_model_t) + sizeof(ccv_nnc_tensor_symbol_t));
663 input->isa = &ccv_cnnp_input_isa;
664 input->outputs = (ccv_nnc_tensor_symbol_t*)(input + 1);
665 input->output_size = 1;
666 return input;
667}
668
669static const ccv_cnnp_model_vtab_t ccv_cnnp_input_isa = {
670 .copy = _ccv_cnnp_input_copy,
671};
672
673ccv_cnnp_model_io_t ccv_cnnp_input(void)
674{
675 ccv_cnnp_model_t* const input = (ccv_cnnp_model_t*)cccalloccalloc(1, sizeof(ccv_cnnp_model_t) + sizeof(ccv_nnc_tensor_symbol_t));
676 input->isa = &ccv_cnnp_input_isa;
677 input->io = ccv_array_new(sizeof(ccv_cnnp_model_io_t), 1, 0);
678 ccv_cnnp_model_io_t input_io = ccmallocmalloc(sizeof(struct ccv_cnnp_model_io_s) + sizeof(ccv_nnc_tensor_symbol_t));
679 input_io->param_ref = 0;
680 input_io->param_sel = 0;
681 input_io->visit = 0;
682 input_io->incomings = 0;
683 input_io->dependencies = 0;
684 input_io->dependents = 0;
685 input_io->outgoings = 0;
686 input_io->model = input;
687 input_io->outputs = (ccv_nnc_tensor_symbol_t*)(input_io + 1);
688 ccv_array_push(input->io, &input_io);
689 input->outputs = (ccv_nnc_tensor_symbol_t*)(input + 1);
690 input->output_size = 1;
691 return input_io;
692}
693
694// MARK - Dynamic Layer
695
696typedef struct {
697 ccv_cnnp_model_t super;
698 ccv_cnnp_model_dynamic_f func;
699 void* context;
700 ccv_cnnp_model_t* model;
701} ccv_cnnp_dynamic_model_t;
702
703static void _ccv_cnnp_dynamic_model_deinit(ccv_cnnp_model_t* const super)
704{
705 ccv_cnnp_dynamic_model_t* const self = (ccv_cnnp_dynamic_model_t*)super;
706 if (self->model)
707 ccv_cnnp_model_deinit(self->model);
708}
709
710static void _ccv_cnnp_dynamic_model_dealloc(ccv_cnnp_model_t* const super)
711{
712 ccv_cnnp_dynamic_model_t* const self = (ccv_cnnp_dynamic_model_t*)super;
713 if (self->model)
714 ccv_cnnp_model_free(self->model);
715}
716
717static void _ccv_cnnp_dynamic_model_build(ccv_cnnp_model_t* const super, 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)
718{
719 ccv_cnnp_dynamic_model_t* const self = (ccv_cnnp_dynamic_model_t*)super;
720 PRINT(CCV_CLI_VERBOSE, "[cnnp_dynamic_model_build] 1. %p, func: %p\n", self, self->func)do { if ((CCV_CLI_VERBOSE & ccv_cli_get_output_levels()))
{ printf("[cnnp_dynamic_model_build] 1. %p, func: %p\n", self
, self->func); fflush(stdout); } } while (0)
;
721 if (!self->model)
722 {
723 ccv_nnc_tensor_param_t input_params[input_size];
724 int i;
725 for (i = 0; i < input_size; i++)
726 input_params[i] = ccv_nnc_tensor_symbol_params(graph, inputs[i]);
727 self->model = self->func(input_params, input_size, self->context);
728 // Update to use the settings of the compiled model.
729 self->super.input_size = self->model->input_size;
730 self->super.outputs = self->model->outputs;
731 self->super.output_size = self->model->output_size;
732 }
733 self->model->data = self->super.data;
734 ccv_cnnp_model_build(self->model, graph, inputs, input_size, outputs, output_size);
735 self->model->data = 0;
736 PRINT(CCV_CLI_VERBOSE, "[cnnp_dynamic_model_build] 2. %p\n", self)do { if ((CCV_CLI_VERBOSE & ccv_cli_get_output_levels()))
{ printf("[cnnp_dynamic_model_build] 2. %p\n", self); fflush
(stdout); } } while (0)
;
737}
738
739static void _ccv_cnnp_dynamic_model_init_states(ccv_cnnp_model_t* const super, ccv_nnc_symbolic_graph_t* const graph, const ccv_cnnp_state_initializer_f initializer, void* const context)
740{
741 ccv_cnnp_dynamic_model_t* const self = (ccv_cnnp_dynamic_model_t*)super;
742 assert(self->model)((void) sizeof ((self->model) ? 1 : 0), __extension__ ({ if
(self->model) ; else __assert_fail ("self->model", "ccv_cnnp_model_core.c"
, 742, __extension__ __PRETTY_FUNCTION__); }))
;
743 ccv_cnnp_model_init_states(self->model, graph, initializer, context);
744}
745
746static void _ccv_cnnp_dynamic_model_set_is_test(ccv_cnnp_model_t* const super, const int is_test, const ccv_cnnp_cmd_updater_f updater, void* const context)
747{
748 ccv_cnnp_dynamic_model_t* const self = (ccv_cnnp_dynamic_model_t*)super;
749 assert(self->model)((void) sizeof ((self->model) ? 1 : 0), __extension__ ({ if
(self->model) ; else __assert_fail ("self->model", "ccv_cnnp_model_core.c"
, 749, __extension__ __PRETTY_FUNCTION__); }))
;
750 ccv_cnnp_model_set_is_test(self->model, is_test, updater, context);
751}
752
753static ccv_cnnp_model_t* _ccv_cnnp_dynamic_model_copy(const ccv_cnnp_model_t* const super, void* const context);
754
755static void _ccv_cnnp_dynamic_model_add_to_parameter_indices(ccv_cnnp_model_t* const super, const int index, ccv_array_t* const parameter_indices)
756{
757 ccv_cnnp_dynamic_model_t* const self = (ccv_cnnp_dynamic_model_t*)super;
758 assert(self->model)((void) sizeof ((self->model) ? 1 : 0), __extension__ ({ if
(self->model) ; else __assert_fail ("self->model", "ccv_cnnp_model_core.c"
, 758, __extension__ __PRETTY_FUNCTION__); }))
;
759 ccv_cnnp_model_add_to_parameter_indices(self->model, index, parameter_indices);
760}
761
762static void _ccv_cnnp_dynamic_model_notify(const ccv_cnnp_model_t* const super, const int tag, void* const payload)
763{
764 ccv_cnnp_dynamic_model_t* const self = (ccv_cnnp_dynamic_model_t*)super;
765 if (self->model)
766 ccv_cnnp_model_notify(self->model, tag, payload);
767}
768
769static const ccv_cnnp_model_vtab_t ccv_cnnp_dynamic_model_isa = {
770 .deinit = _ccv_cnnp_dynamic_model_deinit,
771 .dealloc = _ccv_cnnp_dynamic_model_dealloc,
772 .build = _ccv_cnnp_dynamic_model_build,
773 .init_states = _ccv_cnnp_dynamic_model_init_states,
774 .copy = _ccv_cnnp_dynamic_model_copy,
775 .set_is_test = _ccv_cnnp_dynamic_model_set_is_test,
776 .add_to_parameter_indices = _ccv_cnnp_dynamic_model_add_to_parameter_indices,
777 .notify = _ccv_cnnp_dynamic_model_notify,
778};
779
780ccv_cnnp_model_t* ccv_cnnp_dynamic_new(ccv_cnnp_model_dynamic_f func, void* const context, const char* const name)
781{
782 ccv_cnnp_dynamic_model_t* const dynamic_model = (ccv_cnnp_dynamic_model_t*)cccalloccalloc(1, sizeof(ccv_cnnp_dynamic_model_t));
783 dynamic_model->super.isa = &ccv_cnnp_dynamic_model_isa;
784 dynamic_model->super.is_trainable = -1;
785 dynamic_model->func = func;
786 dynamic_model->context = context;
787 ccv_cnnp_model_copy_name(&dynamic_model->super, name);
788 return (ccv_cnnp_model_t*)dynamic_model;
789}
790
791static ccv_cnnp_model_t* _ccv_cnnp_dynamic_model_copy(const ccv_cnnp_model_t* const super, void* const context)
792{
793 const ccv_cnnp_dynamic_model_t* const self = (const ccv_cnnp_dynamic_model_t*)super;
794 return ccv_cnnp_dynamic_new(self->func, self->context, self->super.name);
795}
796
797// MARK - Command Layer
798
799typedef struct {
800 ccv_cnnp_model_t super;
801 ccv_nnc_cmd_t cmd;
802 ccv_nnc_hint_t hint;
803 ccv_nnc_tensor_symbol_t* input_symbols; // This is only valid for INIT_SHARED_TENSOR / INIT_SHARED_TENSOR_AS_TRAINABLE
804 ccv_nnc_tensor_symbol_t* output_symbols; // This is just for the output symbol (in case we need to have no tensor symbol).
805 ccv_cnnp_cmd_exec_io_t* inputs;
806 int flags;
807 int input_size;
808 int* outputs;
809 int output_size;
810} ccv_cnnp_model_cmd_exec_t;
811
812static void _ccv_cnnp_cmd_exec_build(ccv_cnnp_model_t* const super, 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)
813{
814 ccv_cnnp_model_cmd_exec_t* const self = (ccv_cnnp_model_cmd_exec_t*)super;
815 PRINT(CCV_CLI_VERBOSE, "[cnnp_cmd_exec_build] -\n")do { if ((CCV_CLI_VERBOSE & ccv_cli_get_output_levels()))
{ printf("[cnnp_cmd_exec_build] -\n"); fflush(stdout); } } while
(0)
;
816 ccv_nnc_tensor_param_t input_params[ccv_max(1, self->input_size)({ typeof (1) _a = (1); typeof (self->input_size) _b = (self
->input_size); (_a > _b) ? _a : _b; })
];
817 int i, j;
818 for (i = 0, j = 0; i < self->input_size; i++)
819 if (self->inputs[i].type == CCV_CNNP_IO)
820 {
821 self->input_symbols[i] = inputs[j++];
822 input_params[i] = ccv_nnc_tensor_symbol_params(graph, self->input_symbols[i]);
823 } else if (self->inputs[i].type == CCV_CNNP_NO_TENSOR) {
824 self->input_symbols[i] = NO_TENSOR_SYMBOL(const ccv_nnc_tensor_symbol_t){.d = CCV_NNC_NO_TENSOR_SYMBOL
}
;
825 } else if (!self->input_symbols[i].graph) {
826 // Otherwise, we only create this symbol if it doesn't exist.
827 const ccv_nnc_tensor_param_t params = self->inputs[i].init_state.info;
828 input_params[i] = params;
829 self->input_symbols[i] = ccv_nnc_tensor_symbol_new(graph, params, 0);
830 }
831 // We cannot simply mark the outputs as auto, because the subsequent build call may require this output to have params setup.
832 // Infer the parameters here.
833 ccv_nnc_tensor_param_t output_params[ccv_max(1, self->output_size)({ typeof (1) _a = (1); typeof (self->output_size) _b = (self
->output_size); (_a > _b) ? _a : _b; })
];
834 ccv_nnc_hint_tensor_auto(self->cmd, input_params, self->input_size, self->hint, output_params, self->output_size);
835 for (i = 0, j = 0; i < self->output_size; i++)
836 if (self->outputs[i] == CCV_CNNP_IO)
837 self->output_symbols[i] = outputs[j++] = ccv_nnc_tensor_symbol_new(graph, output_params[i], 0);
838 else if (self->outputs[i] == CCV_CNNP_TENSOR_NOT_OUTPUT)
839 self->output_symbols[i] = ccv_nnc_tensor_symbol_new(graph, output_params[i], 0);
840 else
841 self->output_symbols[i] = NO_TENSOR_SYMBOL(const ccv_nnc_tensor_symbol_t){.d = CCV_NNC_NO_TENSOR_SYMBOL
}
;
842 ccv_nnc_graph_exec_symbol_new(graph, self->cmd, self->input_symbols, self->input_size, self->output_symbols, self->output_size, 0);
843}
844
845static void _ccv_cnnp_cmd_exec_init_states(ccv_cnnp_model_t* const super, ccv_nnc_symbolic_graph_t* const graph, const ccv_cnnp_state_initializer_f initializer, void* const context)
846{
847 ccv_cnnp_model_cmd_exec_t* const self = (ccv_cnnp_model_cmd_exec_t*)super;
848 int i;
849 for (i = 0; i < self->input_size; i++)
850 if (self->inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR || self->inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR_AS_TRAINABLE)
851 self->inputs[i].init_state.init(self->input_symbols[i], initializer, context, self->inputs[i].init_state.context);
852}
853
854static void _ccv_cnnp_cmd_exec_add_to_output(ccv_cnnp_model_t* const super, const ccv_cnnp_add_to_array_f add_to_array, void* const outputs)
855{
856 ccv_cnnp_model_cmd_exec_t* const self = (ccv_cnnp_model_cmd_exec_t*)super;
857 int i;
858 for (i = 0; i < self->input_size; i++)
859 if (self->inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR)
860 add_to_array(outputs, self->input_symbols[i], 0); // Push this as retainable because it need to be init.
861}
862
863static void _ccv_cnnp_cmd_exec_add_to_parameter(ccv_cnnp_model_t* const super, const ccv_cnnp_add_to_array_f add_to_array, void* const parameters, const int is_trainable)
864{
865 ccv_cnnp_model_cmd_exec_t* const self = (ccv_cnnp_model_cmd_exec_t*)super;
866 int i;
867 for (i = 0; i < self->input_size; i++)
868 if (self->inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR_AS_TRAINABLE)
869 add_to_array(parameters, self->input_symbols[i], is_trainable); // Push this as parameter.
870}
871
872static void _ccv_cnnp_cmd_exec_deinit(ccv_cnnp_model_t* const super)
873{
874 ccv_cnnp_model_cmd_exec_t* const self = (ccv_cnnp_model_cmd_exec_t*)super;
875 int i, j;
876 for (i = 0; i < self->input_size; i++)
877 if ((self->inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR || self->inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR_AS_TRAINABLE) &&
878 self->inputs[i].init_state.context)
879 {
880 void* const context = self->inputs[i].init_state.context;
881 if (self->inputs[i].init_state.deinit)
882 self->inputs[i].init_state.deinit(context);
883 self->inputs[i].init_state.init = 0;
884 self->inputs[i].init_state.deinit = 0;
885 self->inputs[i].init_state.context = 0;
886 for (j = i + 1; j < self->input_size; j++)
887 if (self->inputs[j].init_state.context == context)
888 {
889 self->inputs[j].init_state.init = 0;
890 self->inputs[j].init_state.deinit = 0;
891 self->inputs[j].init_state.context = 0;
892 }
893 }
894}
895
896static ccv_cnnp_model_t* _ccv_cnnp_cmd_exec_copy(const ccv_cnnp_model_t* const super, void* const context);
897
898static const ccv_cnnp_model_vtab_t ccv_cnnp_cmd_exec_isa = {
899 .build = _ccv_cnnp_cmd_exec_build,
900 .init_states = _ccv_cnnp_cmd_exec_init_states,
901 .add_to_parameter = _ccv_cnnp_cmd_exec_add_to_parameter,
902 .add_to_output = _ccv_cnnp_cmd_exec_add_to_output,
903 .deinit = _ccv_cnnp_cmd_exec_deinit,
904 .copy = _ccv_cnnp_cmd_exec_copy,
905};
906
907static ccv_cnnp_model_t* _ccv_cnnp_cmd_exec(const ccv_nnc_cmd_t cmd, int copy_io, const ccv_nnc_hint_t hint, const int flags, const ccv_cnnp_cmd_exec_io_t* const inputs, const int input_size, const int* const outputs, const int output_size, const int is_trainable, const char* const name)
908{
909 assert(input_size >= 0)((void) sizeof ((input_size >= 0) ? 1 : 0), __extension__ (
{ if (input_size >= 0) ; else __assert_fail ("input_size >= 0"
, "ccv_cnnp_model_core.c", 909, __extension__ __PRETTY_FUNCTION__
); }))
;
910 assert(output_size > 0)((void) sizeof ((output_size > 0) ? 1 : 0), __extension__ (
{ if (output_size > 0) ; else __assert_fail ("output_size > 0"
, "ccv_cnnp_model_core.c", 910, __extension__ __PRETTY_FUNCTION__
); }))
;
911 int i;
912 int io_input_size = 0;
913 for (i = 0; i < input_size; i++)
914 if (inputs[i].type == CCV_CNNP_IO)
915 ++io_input_size;
916 else {
917 assert(inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR || inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR_AS_TRAINABLE)((void) sizeof ((inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR
|| inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR_AS_TRAINABLE
) ? 1 : 0), __extension__ ({ if (inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR
|| inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR_AS_TRAINABLE
) ; else __assert_fail ("inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR || inputs[i].type == CCV_CNNP_INIT_SHARED_TENSOR_AS_TRAINABLE"
, "ccv_cnnp_model_core.c", 917, __extension__ __PRETTY_FUNCTION__
); }))
;
918 assert(inputs[i].init_state.init)((void) sizeof ((inputs[i].init_state.init) ? 1 : 0), __extension__
({ if (inputs[i].init_state.init) ; else __assert_fail ("inputs[i].init_state.init"
, "ccv_cnnp_model_core.c", 918, __extension__ __PRETTY_FUNCTION__
); }))
;
919 }
920 int io_output_size = 0;
921 for (i = 0; i < output_size; i++)
922 if (outputs[i] == CCV_CNNP_IO)
923 ++io_output_size;
924 else {
925 assert(outputs[i] == CCV_CNNP_TENSOR_NOT_OUTPUT || outputs[i] == CCV_CNNP_NO_TENSOR)((void) sizeof ((outputs[i] == CCV_CNNP_TENSOR_NOT_OUTPUT || outputs
[i] == CCV_CNNP_NO_TENSOR) ? 1 : 0), __extension__ ({ if (outputs
[i] == CCV_CNNP_TENSOR_NOT_OUTPUT || outputs[i] == CCV_CNNP_NO_TENSOR
) ; else __assert_fail ("outputs[i] == CCV_CNNP_TENSOR_NOT_OUTPUT || outputs[i] == CCV_CNNP_NO_TENSOR"
, "ccv_cnnp_model_core.c", 925, __extension__ __PRETTY_FUNCTION__
); }))
;
926 }
927 assert(io_output_size > 0)((void) sizeof ((io_output_size > 0) ? 1 : 0), __extension__
({ if (io_output_size > 0) ; else __assert_fail ("io_output_size > 0"
, "ccv_cnnp_model_core.c", 927, __extension__ __PRETTY_FUNCTION__
); }))
;
928 ccv_cnnp_model_cmd_exec_t* const model_cmd_exec = (ccv_cnnp_model_cmd_exec_t*)cccalloccalloc(1, sizeof(ccv_cnnp_model_cmd_exec_t) + sizeof(ccv_nnc_tensor_symbol_t) * (io_output_size + input_size + output_size) + sizeof(ccv_cnnp_cmd_exec_io_t) * input_size + sizeof(int) * output_size);
929 model_cmd_exec->super.isa = &ccv_cnnp_cmd_exec_isa;
930 model_cmd_exec->super.input_size = io_input_size;
931 model_cmd_exec->super.outputs = (ccv_nnc_tensor_symbol_t*)(model_cmd_exec + 1);
932 model_cmd_exec->super.output_size = io_output_size;
933 model_cmd_exec->super.is_trainable = is_trainable;
934 ccv_cnnp_model_copy_name(&model_cmd_exec->super, name);
935 model_cmd_exec->cmd = cmd;
936 model_cmd_exec->hint = hint;
937 model_cmd_exec->flags = flags;
938 model_cmd_exec->input_size = input_size;
939 model_cmd_exec->input_symbols = model_cmd_exec->super.outputs + io_output_size;
940 model_cmd_exec->output_symbols = model_cmd_exec->input_symbols + input_size;
941 model_cmd_exec->inputs = (ccv_cnnp_cmd_exec_io_t*)(model_cmd_exec->output_symbols + output_size);
942 if (input_size > 0)
943 {
944 memcpy(model_cmd_exec->inputs, inputs, sizeof(ccv_cnnp_cmd_exec_io_t) * input_size);
945 if (copy_io)
946 for (i = 0; i < input_size; i++)
947 if (inputs[i].type != CCV_CNNP_IO && inputs[i].init_state.copy)
948 model_cmd_exec->inputs[i].init_state.context = inputs[i].init_state.copy(inputs[i].init_state.context);
949 }
950 model_cmd_exec->output_size = output_size;
951 model_cmd_exec->outputs = (int*)(model_cmd_exec->inputs + input_size);
952 if (output_size > 0)
953 memcpy(model_cmd_exec->outputs, outputs, sizeof(int) * output_size);
954 return (ccv_cnnp_model_t*)model_cmd_exec;
955}
956
957ccv_cnnp_model_t* ccv_cnnp_cmd_exec(const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, const ccv_cnnp_cmd_exec_io_t* const inputs, const int input_size, const int* const outputs, const int output_size, const int is_trainable, const char* const name)
958{
959 return _ccv_cnnp_cmd_exec(cmd, 0, hint, flags, inputs, input_size, outputs, output_size, is_trainable, name);
960}
961
962static ccv_cnnp_model_t* _ccv_cnnp_cmd_exec_copy(const ccv_cnnp_model_t* const super, void* const context)
963{
964 const ccv_cnnp_model_cmd_exec_t* const self = (const ccv_cnnp_model_cmd_exec_t*)super;
965 return _ccv_cnnp_cmd_exec(self->cmd, 1, self->hint, self->flags, self->inputs, self->input_size, self->outputs, self->output_size, self->super.is_trainable, self->super.name);
966}
967
968static void _ccv_cnnp_cmd_exec_io_copy(const ccv_nnc_tensor_symbol_t tensor_symbol, const ccv_cnnp_state_initializer_f initializer, void* const initializer_context, void* const context)
969{
970 initializer(initializer_context, CMD_DATA_TRANSFER_FORWARD()ccv_nnc_cmd(CCV_NNC_DATA_TRANSFER_FORWARD, 0, ccv_nnc_cmd_auto
, 0)
, ccv_nnc_no_hint, 0, (ccv_nnc_tensor_t*)context, tensor_symbol);
971}
972
973ccv_cnnp_cmd_exec_io_init_state_t ccv_cnnp_cmd_exec_io_copy(const ccv_nnc_tensor_t* const tensor)
974{
975 return (ccv_cnnp_cmd_exec_io_init_state_t){
976 .info = tensor->info,
977 .context = (void *)tensor,
978 .init = _ccv_cnnp_cmd_exec_io_copy,
979 };
980}
981
982typedef struct {
983 ccv_nnc_cmd_t cmd;
984 ccv_nnc_hint_t hint;
985 int flags;
986} ccv_cnnp_cmd_exec_io_set_by_t;
987
988static void _ccv_cnnp_cmd_exec_io_set_by(const ccv_nnc_tensor_symbol_t tensor_symbol, const ccv_cnnp_state_initializer_f initializer, void* const initializer_context, void* const context)
989{
990 const ccv_cnnp_cmd_exec_io_set_by_t* const set_by = (ccv_cnnp_cmd_exec_io_set_by_t*)context;
991 initializer(initializer_context, set_by->cmd, set_by->hint, set_by->flags, 0, tensor_symbol);
992}
993
994static void* _ccv_cnnp_cmd_exec_io_set_by_copy(void* const context)
995{
996 ccv_cnnp_cmd_exec_io_set_by_t* const set_by = (ccv_cnnp_cmd_exec_io_set_by_t*)ccmallocmalloc(sizeof(ccv_cnnp_cmd_exec_io_set_by_t));
997 memcpy(set_by, context, sizeof(ccv_cnnp_cmd_exec_io_set_by_t));
998 return set_by;
999}
1000
1001ccv_cnnp_cmd_exec_io_init_state_t ccv_cnnp_cmd_exec_io_set_by(const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, const ccv_nnc_tensor_param_t params)
1002{
1003 ccv_cnnp_cmd_exec_io_set_by_t* const set_by = (ccv_cnnp_cmd_exec_io_set_by_t*)ccmallocmalloc(sizeof(ccv_cnnp_cmd_exec_io_set_by_t));
1004 set_by->cmd = cmd;
1005 set_by->hint = hint;
1006 set_by->flags = flags;
1007 return (ccv_cnnp_cmd_exec_io_init_state_t){
1008 .info = params,
1009 .context = set_by,
1010 .init = _ccv_cnnp_cmd_exec_io_set_by,
1011 .copy = _ccv_cnnp_cmd_exec_io_set_by_copy,
1012 .deinit = ccfreefree,
1013 };
1014}