File: | nnc/ccv_cnnp_dataframe_addons.c |
Warning: | line 470, column 18 Array access (via field 'i32') results in a null pointer dereference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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_dataframe.h" | |||
6 | #include "3rdparty/sfmt/SFMT.h" | |||
7 | ||||
8 | // MARK - Create Dataframe from Array | |||
9 | ||||
10 | static void _ccv_cnnp_array_enum(const int column_idx, const int* const row_idxs, const int row_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context) | |||
11 | { | |||
12 | int i; | |||
13 | ccv_array_t* const array = (ccv_array_t*)context; | |||
14 | for (i = 0; i < row_size; i++) | |||
15 | data[i] = ccv_array_get(array, row_idxs[i])((void*)(((char*)((array)->data)) + (size_t)(array)->rsize * (size_t)(row_idxs[i]))); | |||
16 | } | |||
17 | ||||
18 | ccv_cnnp_dataframe_t* ccv_cnnp_dataframe_from_array_new(ccv_array_t* const array) | |||
19 | { | |||
20 | const ccv_cnnp_column_data_t array_column_data = { | |||
21 | .data_enum = _ccv_cnnp_array_enum, | |||
22 | .context = array | |||
23 | }; | |||
24 | return ccv_cnnp_dataframe_new(&array_column_data, 1, array->rnum); | |||
25 | } | |||
26 | ||||
27 | typedef struct { | |||
28 | ccv_cnnp_dataframe_tuple_t tuple; | |||
29 | int tensor_offset; | |||
30 | int device_id; | |||
31 | } ccv_cnnp_copy_to_gpu_context_t; | |||
32 | ||||
33 | // MARK - Copy Tensors from CPU to GPU | |||
34 | ||||
35 | static void _ccv_cnnp_tensor_list_deinit(void* const data, void* const context) | |||
36 | { | |||
37 | ccv_cnnp_dataframe_tuple_t* const tuple = (ccv_cnnp_dataframe_tuple_t*)context; | |||
38 | ccv_nnc_tensor_t** const tensor_list = (ccv_nnc_tensor_t**)data; | |||
39 | int i; | |||
40 | for (i = 0; i < tuple->size; i++) | |||
41 | if (tensor_list[i]) | |||
42 | ccv_nnc_tensor_free(tensor_list[i]); | |||
43 | ccfreefree(tensor_list); | |||
44 | } | |||
45 | ||||
46 | static void _ccv_cnnp_copy_to_gpu(void* const* const* const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context) | |||
47 | { | |||
48 | const ccv_cnnp_copy_to_gpu_context_t* const copy_to_gpu_context = (ccv_cnnp_copy_to_gpu_context_t*)context; | |||
49 | int i, j; | |||
50 | for (i = 0; i < batch_size; i++) | |||
51 | { | |||
52 | ccv_nnc_tensor_t* const* const inputs = (ccv_nnc_tensor_t* const*)column_data[0][i] + copy_to_gpu_context->tensor_offset; | |||
53 | ccv_nnc_tensor_t** outputs = (ccv_nnc_tensor_t**)data[i]; | |||
54 | if (!outputs) | |||
55 | outputs = (ccv_nnc_tensor_t**)(data[i] = cccalloccalloc(copy_to_gpu_context->tuple.size, sizeof(ccv_nnc_tensor_t*))); | |||
56 | for (j = 0; j < copy_to_gpu_context->tuple.size; j++) | |||
57 | { | |||
58 | ccv_nnc_tensor_param_t params = inputs[j]->info; | |||
59 | params.type &= ~CCV_TENSOR_CPU_MEMORY; | |||
60 | params.type |= CCV_TENSOR_GPU_MEMORY; // Change to GPU memory. | |||
61 | CCV_TENSOR_SET_DEVICE_ID(params.type, copy_to_gpu_context->device_id)(params.type) = (((params.type) & ~0xfff00) | (((copy_to_gpu_context ->device_id) & 0xfff) << 8)); | |||
62 | outputs[j] = outputs[j] ? ccv_nnc_tensor_resize(outputs[j], params) : ccv_nnc_tensor_new(0, params, 0); | |||
63 | ccv_nnc_tensor_pin_memory(inputs[j]); | |||
64 | } | |||
65 | ccv_nnc_cmd_exec(CMD_DATA_TRANSFER_FORWARD()ccv_nnc_cmd(CCV_NNC_DATA_TRANSFER_FORWARD, 0, ccv_nnc_cmd_auto , 0), ccv_nnc_no_hint, 0, inputs, copy_to_gpu_context->tuple.size, outputs, copy_to_gpu_context->tuple.size, stream_context); | |||
66 | } | |||
67 | } | |||
68 | ||||
69 | int ccv_cnnp_dataframe_copy_to_gpu(ccv_cnnp_dataframe_t* const dataframe, const int column_idx, const int tensor_offset, const int tensor_size, const int device_id, const char* name) | |||
70 | { | |||
71 | assert(tensor_size > 0)((void) sizeof ((tensor_size > 0) ? 1 : 0), __extension__ ( { if (tensor_size > 0) ; else __assert_fail ("tensor_size > 0" , "ccv_cnnp_dataframe_addons.c", 71, __extension__ __PRETTY_FUNCTION__ ); })); | |||
72 | int stream_type = CCV_STREAM_CONTEXT_GPU; | |||
73 | CCV_STREAM_SET_DEVICE_ID(stream_type, device_id)(stream_type) = (((stream_type) & ~0xfff00) | (((device_id ) & 0xfff) << 8)); | |||
74 | ccv_cnnp_copy_to_gpu_context_t* const copy_to_gpu_context = (ccv_cnnp_copy_to_gpu_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_copy_to_gpu_context_t)); | |||
75 | copy_to_gpu_context->tuple.size = tensor_size; | |||
76 | copy_to_gpu_context->tensor_offset = tensor_offset; | |||
77 | copy_to_gpu_context->device_id = device_id; | |||
78 | return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_copy_to_gpu, stream_type, _ccv_cnnp_tensor_list_deinit, COLUMN_ID_LIST(column_idx)(const int []){column_idx}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1), copy_to_gpu_context, (ccv_cnnp_column_data_context_deinit_f)ccfreefree, name); | |||
79 | } | |||
80 | ||||
81 | // MARK - Use Command to Generate Output Tuple | |||
82 | ||||
83 | typedef struct { | |||
84 | ccv_cnnp_dataframe_tuple_t tuple; | |||
85 | int input_offset; | |||
86 | int input_size; | |||
87 | ccv_nnc_cmd_t cmd; | |||
88 | ccv_nnc_hint_t hint; | |||
89 | int flags; | |||
90 | ccv_nnc_tensor_param_t output_params[1]; | |||
91 | } ccv_cnnp_cmd_exec_context_t; | |||
92 | ||||
93 | static void _ccv_cnnp_dataframe_cmd_exec(void* const* const* const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context) | |||
94 | { | |||
95 | const ccv_cnnp_cmd_exec_context_t* const cmd_exec_context = (ccv_cnnp_cmd_exec_context_t*)context; | |||
96 | int i, j; | |||
97 | for (i = 0; i < batch_size; i++) | |||
98 | { | |||
99 | ccv_nnc_tensor_t* const* const inputs = (ccv_nnc_tensor_t* const*)column_data[0][i] + cmd_exec_context->input_offset; | |||
100 | ccv_nnc_tensor_t** outputs = (ccv_nnc_tensor_t**)data[i]; | |||
101 | if (!outputs) | |||
102 | { | |||
103 | outputs = (ccv_nnc_tensor_t**)(data[i] = ccmallocmalloc(sizeof(ccv_nnc_tensor_t*) * cmd_exec_context->tuple.size)); | |||
104 | for (j = 0; j < cmd_exec_context->tuple.size; j++) | |||
105 | outputs[j] = ccv_nnc_tensor_new(0, cmd_exec_context->output_params[j], 0); | |||
106 | } | |||
107 | ccv_nnc_cmd_exec(cmd_exec_context->cmd, cmd_exec_context->hint, cmd_exec_context->flags, inputs, cmd_exec_context->input_size, outputs, cmd_exec_context->tuple.size, stream_context); | |||
108 | } | |||
109 | } | |||
110 | ||||
111 | int ccv_cnnp_dataframe_cmd_exec(ccv_cnnp_dataframe_t* const dataframe, const int column_idx, const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, const int input_offset, const int input_size, const ccv_nnc_tensor_param_t* const output_params, const int output_size, const int stream_type, const char* name) | |||
112 | { | |||
113 | assert(input_size > 0)((void) sizeof ((input_size > 0) ? 1 : 0), __extension__ ( { if (input_size > 0) ; else __assert_fail ("input_size > 0" , "ccv_cnnp_dataframe_addons.c", 113, __extension__ __PRETTY_FUNCTION__ ); })); | |||
114 | assert(output_size > 0)((void) sizeof ((output_size > 0) ? 1 : 0), __extension__ ( { if (output_size > 0) ; else __assert_fail ("output_size > 0" , "ccv_cnnp_dataframe_addons.c", 114, __extension__ __PRETTY_FUNCTION__ ); })); | |||
115 | ccv_cnnp_cmd_exec_context_t* const cmd_exec_context = (ccv_cnnp_cmd_exec_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_cmd_exec_context_t) + sizeof(ccv_nnc_tensor_param_t) * (output_size - 1)); | |||
116 | cmd_exec_context->tuple.size = output_size; | |||
117 | cmd_exec_context->input_offset = input_offset; | |||
118 | cmd_exec_context->input_size = input_size; | |||
119 | cmd_exec_context->cmd = cmd; | |||
120 | cmd_exec_context->hint = hint; | |||
121 | cmd_exec_context->flags = flags; | |||
122 | memcpy(cmd_exec_context->output_params, output_params, sizeof(ccv_nnc_tensor_param_t) * output_size); | |||
123 | return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_dataframe_cmd_exec, stream_type, _ccv_cnnp_tensor_list_deinit, COLUMN_ID_LIST(column_idx)(const int []){column_idx}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1), cmd_exec_context, (ccv_cnnp_column_data_context_deinit_f)ccfreefree, name); | |||
124 | return 0; | |||
125 | } | |||
126 | ||||
127 | // MARK - Make Auxiliary Tensor as a new Column | |||
128 | ||||
129 | static void _ccv_cnnp_tensor_deinit(void* const data, void* const context) | |||
130 | { | |||
131 | ccv_nnc_tensor_free((ccv_nnc_tensor_t*)data); | |||
132 | } | |||
133 | ||||
134 | static void _ccv_cnnp_tensor_new(const int column_idx, const int* const row_idxs, const int row_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context) | |||
135 | { | |||
136 | ccv_nnc_tensor_param_t params = *(ccv_nnc_tensor_param_t*)context; | |||
137 | int i; | |||
138 | for (i = 0; i < row_size; i++) | |||
139 | if (!data[i]) | |||
140 | data[i] = ccv_nnc_tensor_new(0, params, 0); | |||
141 | } | |||
142 | ||||
143 | int ccv_cnnp_dataframe_add_aux(ccv_cnnp_dataframe_t* const dataframe, const ccv_nnc_tensor_param_t params, const char* name) | |||
144 | { | |||
145 | int stream_type = CCV_TENSOR_GET_MEMORY(params.type)((params.type) & 0x3) == CCV_TENSOR_CPU_MEMORY ? 0 : CCV_STREAM_CONTEXT_GPU; | |||
146 | if (stream_type == CCV_STREAM_CONTEXT_GPU) | |||
147 | CCV_STREAM_SET_DEVICE_ID(stream_type, CCV_TENSOR_GET_DEVICE_ID(params.type))(stream_type) = (((stream_type) & ~0xfff00) | ((((((params .type) & 0xfff00) >> 8)) & 0xfff) << 8)); | |||
148 | ccv_nnc_tensor_param_t* const context = (ccv_nnc_tensor_param_t*)ccmallocmalloc(sizeof(ccv_nnc_tensor_param_t)); | |||
149 | context[0] = params; | |||
150 | return ccv_cnnp_dataframe_add(dataframe, _ccv_cnnp_tensor_new, stream_type, _ccv_cnnp_tensor_deinit, context, (ccv_cnnp_column_data_context_deinit_f)ccfreefree, name); | |||
151 | } | |||
152 | ||||
153 | // MARK - Load Tensor from File Path | |||
154 | ||||
155 | static void _ccv_cnnp_image_deinit(void* const data, void* const context) | |||
156 | { | |||
157 | ccv_matrix_free(data); | |||
158 | } | |||
159 | ||||
160 | static void _ccv_cnnp_read_image(void* const* const* const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context) | |||
161 | { | |||
162 | parallel_for(i, batch_size){ int i; for ((i) = 0; (i) < (batch_size); (i)++) { { | |||
163 | if (data[i]) | |||
164 | ccv_matrix_free(data[i]); | |||
165 | off_t structof = (off_t)context; | |||
166 | const char* const filename = *(char* const*)((const char*)column_data[0][i] + structof); | |||
167 | data[i] = 0; | |||
168 | ccv_read(filename, (ccv_dense_matrix_t**)&data[i], CCV_IO_ANY_FILE | CCV_IO_RGB_COLOR)ccv_read_impl(filename, (ccv_dense_matrix_t**)&data[i], CCV_IO_ANY_FILE | CCV_IO_RGB_COLOR, 0, 0, 0); | |||
169 | } parallel_endfor} } | |||
170 | } | |||
171 | ||||
172 | int ccv_cnnp_dataframe_read_image(ccv_cnnp_dataframe_t* const dataframe, const int column_idx, const off_t structof, const char* name) | |||
173 | { | |||
174 | return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_read_image, 0, _ccv_cnnp_image_deinit, COLUMN_ID_LIST(column_idx)(const int []){column_idx}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1), (void*)(uintptr_t)structof, 0, name); | |||
175 | } | |||
176 | ||||
177 | // MARK - Apply Random Jitter to Image | |||
178 | ||||
179 | typedef struct { | |||
180 | sfmt_t sfmt; | |||
181 | int datatype; | |||
182 | ccv_cnnp_random_jitter_t random_jitter; | |||
183 | } ccv_cnnp_random_jitter_context_t; | |||
184 | ||||
185 | static void _ccv_cnnp_image_lighting(ccv_dense_matrix_t* image, const float alpha_r, const float alpha_g, const float alpha_b) | |||
186 | { | |||
187 | assert(CCV_GET_DATA_TYPE(image->type) == CCV_32F)((void) sizeof ((((image->type) & 0xFF000) == CCV_32F) ? 1 : 0), __extension__ ({ if (((image->type) & 0xFF000 ) == CCV_32F) ; else __assert_fail ("CCV_GET_DATA_TYPE(image->type) == CCV_32F" , "ccv_cnnp_dataframe_addons.c", 187, __extension__ __PRETTY_FUNCTION__ ); })); | |||
188 | assert(CCV_GET_CHANNEL(image->type) == CCV_C3)((void) sizeof ((((image->type) & 0xFFF) == CCV_C3) ? 1 : 0), __extension__ ({ if (((image->type) & 0xFFF) == CCV_C3) ; else __assert_fail ("CCV_GET_CHANNEL(image->type) == CCV_C3" , "ccv_cnnp_dataframe_addons.c", 188, __extension__ __PRETTY_FUNCTION__ ); })); | |||
189 | // These eigenvector values can be computed out of imageNet dataset (see ccv_convnet for how that is done). Here I just copied | |||
190 | // from mxnet: https://github.com/apache/incubator-mxnet/blob/master/src/operator/image/image_random-inl.h#L632 | |||
191 | const float pca_r = alpha_r * (55.46 * -0.5675) + alpha_g * (4.794 * 0.7192) + alpha_b * (1.148 * 0.4009); | |||
192 | const float pca_g = alpha_r * (55.46 * -0.5808) + alpha_g * (4.794 * -0.0045) + alpha_b * (1.148 * -0.8140); | |||
193 | const float pca_b = alpha_r * (55.46 * -0.5836) + alpha_g * (4.794 * -0.6948) + alpha_b * (1.148 * 0.4203); | |||
194 | int i; | |||
195 | const int size = image->rows * image->cols; | |||
196 | float* const ptr = image->data.f32; | |||
197 | for (i = 0; i < size; i++) | |||
198 | { | |||
199 | ptr[i * 3] = ccv_clamp(ptr[i * 3] + pca_r, 0, 255)({ typeof (0) _a = (0); typeof (255) _b = (255); typeof (ptr[ i * 3] + pca_r) _x = (ptr[i * 3] + pca_r); (_x < _a) ? _a : ((_x > _b) ? _b : _x); }); | |||
200 | ptr[i * 3 + 1] = ccv_clamp(ptr[i * 3 + 1] + pca_g, 0, 255)({ typeof (0) _a = (0); typeof (255) _b = (255); typeof (ptr[ i * 3 + 1] + pca_g) _x = (ptr[i * 3 + 1] + pca_g); (_x < _a ) ? _a : ((_x > _b) ? _b : _x); }); | |||
201 | ptr[i * 3 + 2] = ccv_clamp(ptr[i * 3 + 2] + pca_b, 0, 255)({ typeof (0) _a = (0); typeof (255) _b = (255); typeof (ptr[ i * 3 + 2] + pca_b) _x = (ptr[i * 3 + 2] + pca_b); (_x < _a ) ? _a : ((_x > _b) ? _b : _x); }); | |||
202 | } | |||
203 | } | |||
204 | ||||
205 | static float _ccv_cnnp_random_logexp(sfmt_t* const sfmt, const float jitter) | |||
206 | { | |||
207 | // We want to get something around logarithmic scale, thus, 0 is no good, and infinity is no good. 1 is the same. | |||
208 | // jitter is some turbulence we want around 1. We want the range range to be around [1 / (1 + jitter), 1 + jitter] | |||
209 | // but the distribution is not uniform (50% fall under 1, and 50% fall above 1). The way to do this is to first | |||
210 | // get to logarithmic range, doing a uniform sampling, and then convert back. | |||
211 | double log_jitter_limit = log(1 + jitter); | |||
212 | double log_random_jitter = sfmt_genrand_real1(sfmt) * 2 * log_jitter_limit - log_jitter_limit; | |||
213 | return (float)exp(log_random_jitter); // Convert it back to exponential form. | |||
214 | } | |||
215 | ||||
216 | static void _ccv_cnnp_image_manip(ccv_dense_matrix_t* image, const ccv_cnnp_random_jitter_t random_jitter, sfmt_t* const sfmt) | |||
217 | { | |||
218 | assert(sfmt && CCV_GET_CHANNEL(image->type) == CCV_C3)((void) sizeof ((sfmt && ((image->type) & 0xFFF ) == CCV_C3) ? 1 : 0), __extension__ ({ if (sfmt && ( (image->type) & 0xFFF) == CCV_C3) ; else __assert_fail ("sfmt && CCV_GET_CHANNEL(image->type) == CCV_C3" , "ccv_cnnp_dataframe_addons.c", 218, __extension__ __PRETTY_FUNCTION__ ); })); | |||
219 | int idx[4] = {0, 1, 2, 3}; | |||
220 | sfmt_genrand_shuffle(sfmt, idx, 4, sizeof(int)); | |||
221 | int i; | |||
222 | for (i = 0; i < 4; i++) | |||
223 | // change the applying order | |||
224 | switch (idx[i]) | |||
225 | { | |||
226 | case 0: | |||
227 | if (random_jitter.brightness == 0) | |||
228 | break; | |||
229 | // introduce some brightness changes to the original image | |||
230 | ccv_scale(image, (ccv_matrix_t**)&image, 0, _ccv_cnnp_random_logexp(sfmt, random_jitter.brightness)); | |||
231 | break; | |||
232 | case 1: | |||
233 | // introduce some saturation changes to the original image | |||
234 | if (random_jitter.saturation == 0) | |||
235 | break; | |||
236 | ccv_saturation(image, &image, 0, _ccv_cnnp_random_logexp(sfmt, random_jitter.saturation)); | |||
237 | break; | |||
238 | case 2: | |||
239 | // introduce some contrast changes to the original image | |||
240 | if (random_jitter.contrast == 0) | |||
241 | break; | |||
242 | ccv_contrast(image, &image, 0, _ccv_cnnp_random_logexp(sfmt, random_jitter.contrast)); | |||
243 | break; | |||
244 | case 3: | |||
245 | if (random_jitter.lighting == 0) | |||
246 | break; | |||
247 | _ccv_cnnp_image_lighting(image, sfmt_genrand_real1(sfmt) * random_jitter.lighting, sfmt_genrand_real1(sfmt) * random_jitter.lighting, sfmt_genrand_real1(sfmt) * random_jitter.lighting); | |||
248 | break; | |||
249 | } | |||
250 | } | |||
251 | ||||
252 | static void _ccv_cnnp_normalize(ccv_dense_matrix_t* const image, const float mean[3], const float inv_std[3]) | |||
253 | { | |||
254 | int i; | |||
255 | const int count = image->rows * image->cols; | |||
256 | float* ap = image->data.f32; | |||
257 | for (i = 0; i < count; i++) | |||
258 | { | |||
259 | ap[i * 3] = (ap[i * 3] - mean[0]) * inv_std[0]; | |||
260 | ap[i * 3 + 1] = (ap[i * 3 + 1] - mean[1]) * inv_std[1]; | |||
261 | ap[i * 3 + 2] = (ap[i * 3 + 2] - mean[2]) * inv_std[2]; | |||
262 | } | |||
263 | } | |||
264 | ||||
265 | static void _ccv_cnnp_random_jitter(void* const* const* const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context) | |||
266 | { | |||
267 | sfmt_t* const sfmt = (sfmt_t*)ccmallocmalloc(sizeof(sfmt_t) * batch_size); | |||
268 | ccv_cnnp_random_jitter_context_t* const ctx = (ccv_cnnp_random_jitter_context_t*)context; | |||
269 | int i; | |||
270 | for (i = 0; i < batch_size; i++) | |||
271 | sfmt_init_gen_rand(&sfmt[i], sfmt_genrand_uint32(&ctx->sfmt)); | |||
272 | const ccv_cnnp_random_jitter_t random_jitter = ctx->random_jitter; | |||
273 | assert(random_jitter.resize.min > 0)((void) sizeof ((random_jitter.resize.min > 0) ? 1 : 0), __extension__ ({ if (random_jitter.resize.min > 0) ; else __assert_fail ("random_jitter.resize.min > 0", "ccv_cnnp_dataframe_addons.c" , 273, __extension__ __PRETTY_FUNCTION__); })); | |||
274 | assert(random_jitter.resize.max >= random_jitter.resize.min)((void) sizeof ((random_jitter.resize.max >= random_jitter .resize.min) ? 1 : 0), __extension__ ({ if (random_jitter.resize .max >= random_jitter.resize.min) ; else __assert_fail ("random_jitter.resize.max >= random_jitter.resize.min" , "ccv_cnnp_dataframe_addons.c", 274, __extension__ __PRETTY_FUNCTION__ ); })); | |||
275 | parallel_for(i, batch_size){ int i; for ((i) = 0; (i) < (batch_size); (i)++) { { | |||
276 | if (data[i]) | |||
277 | ccv_matrix_free(data[i]); | |||
278 | ccv_dense_matrix_t* const input = (ccv_dense_matrix_t*)column_data[0][i]; | |||
279 | const int resize = ccv_clamp((int)(sfmt_genrand_real1(&sfmt[i]) * (random_jitter.resize.max - random_jitter.resize.min) + 0.5) + random_jitter.resize.min, random_jitter.resize.min, random_jitter.resize.max)({ typeof (random_jitter.resize.min) _a = (random_jitter.resize .min); typeof (random_jitter.resize.max) _b = (random_jitter. resize.max); typeof ((int)(sfmt_genrand_real1(&sfmt[i]) * (random_jitter.resize.max - random_jitter.resize.min) + 0.5) + random_jitter.resize.min) _x = ((int)(sfmt_genrand_real1(& sfmt[i]) * (random_jitter.resize.max - random_jitter.resize.min ) + 0.5) + random_jitter.resize.min); (_x < _a) ? _a : ((_x > _b) ? _b : _x); }); | |||
280 | int resize_rows = ccv_max(resize, (int)(input->rows * (float)resize / input->cols + 0.5))({ typeof (resize) _a = (resize); typeof ((int)(input->rows * (float)resize / input->cols + 0.5)) _b = ((int)(input-> rows * (float)resize / input->cols + 0.5)); (_a > _b) ? _a : _b; }); | |||
281 | int resize_cols = ccv_max(resize, (int)(input->cols * (float)resize / input->rows + 0.5))({ typeof (resize) _a = (resize); typeof ((int)(input->cols * (float)resize / input->rows + 0.5)) _b = ((int)(input-> cols * (float)resize / input->rows + 0.5)); (_a > _b) ? _a : _b; }); | |||
282 | if (random_jitter.aspect_ratio > 0) | |||
283 | { | |||
284 | const float aspect_ratio = sqrtf(_ccv_cnnp_random_logexp(&sfmt[i], random_jitter.aspect_ratio)); | |||
285 | resize_rows = (int)(resize_rows * aspect_ratio + 0.5); | |||
286 | resize_cols = (int)(resize_cols / aspect_ratio + 0.5); | |||
287 | } | |||
288 | if (random_jitter.resize.roundup > 0) | |||
289 | { | |||
290 | const int roundup = random_jitter.resize.roundup; | |||
291 | const int roundup_2 = roundup / 2; | |||
292 | resize_rows = (resize_rows + roundup_2) / roundup * roundup; | |||
293 | resize_cols = (resize_cols + roundup_2) / roundup * roundup; | |||
294 | } | |||
295 | const int need_crop = (random_jitter.size.cols > 0 && random_jitter.size.rows > 0 && | |||
296 | ((resize_cols != random_jitter.size.cols || resize_rows != random_jitter.size.rows) || | |||
297 | (random_jitter.offset.x != 0 || random_jitter.offset.y != 0))); | |||
298 | int cropped = 0, crop_x = 0, crop_y = 0; | |||
299 | ccv_dense_matrix_t* sliced = 0; | |||
300 | if (need_crop) | |||
301 | { | |||
302 | // Compute crop x, y. | |||
303 | crop_x = random_jitter.center_crop ? | |||
304 | (resize_cols - random_jitter.size.cols + 1) / 2 : // Otherwise, random select x. | |||
305 | (int)(sfmt_genrand_real1(&sfmt[i]) * (resize_cols - random_jitter.size.cols + 1)); | |||
306 | crop_x = ccv_clamp(crop_x,({ typeof (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter .size.cols) _b = (resize_cols - random_jitter.size.cols); (_a < _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter .size.cols); (_a < _b) ? _a : _b; })); typeof (({ typeof ( 0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter.size.cols); (_a > _b) ? _a : _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter.size .cols); (_a > _b) ? _a : _b; })); typeof (crop_x) _x = (crop_x ); (_x < _a) ? _a : ((_x > _b) ? _b : _x); }) | |||
307 | ccv_min(0, resize_cols - random_jitter.size.cols),({ typeof (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter .size.cols) _b = (resize_cols - random_jitter.size.cols); (_a < _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter .size.cols); (_a < _b) ? _a : _b; })); typeof (({ typeof ( 0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter.size.cols); (_a > _b) ? _a : _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter.size .cols); (_a > _b) ? _a : _b; })); typeof (crop_x) _x = (crop_x ); (_x < _a) ? _a : ((_x > _b) ? _b : _x); }) | |||
308 | ccv_max(0, resize_cols - random_jitter.size.cols))({ typeof (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter .size.cols) _b = (resize_cols - random_jitter.size.cols); (_a < _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter .size.cols); (_a < _b) ? _a : _b; })); typeof (({ typeof ( 0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter.size.cols); (_a > _b) ? _a : _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter.size .cols); (_a > _b) ? _a : _b; })); typeof (crop_x) _x = (crop_x ); (_x < _a) ? _a : ((_x > _b) ? _b : _x); }); | |||
309 | crop_y = random_jitter.center_crop ? | |||
310 | (resize_rows - random_jitter.size.rows + 1) / 2 : // Otherwise, random select y. | |||
311 | (int)(sfmt_genrand_real1(&sfmt[i]) * (resize_rows - random_jitter.size.rows + 1)); | |||
312 | crop_y = ccv_clamp(crop_y,({ typeof (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter .size.rows) _b = (resize_rows - random_jitter.size.rows); (_a < _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter .size.rows); (_a < _b) ? _a : _b; })); typeof (({ typeof ( 0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter.size.rows); (_a > _b) ? _a : _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter.size .rows); (_a > _b) ? _a : _b; })); typeof (crop_y) _x = (crop_y ); (_x < _a) ? _a : ((_x > _b) ? _b : _x); }) | |||
313 | ccv_min(0, resize_rows - random_jitter.size.rows),({ typeof (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter .size.rows) _b = (resize_rows - random_jitter.size.rows); (_a < _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter .size.rows); (_a < _b) ? _a : _b; })); typeof (({ typeof ( 0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter.size.rows); (_a > _b) ? _a : _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter.size .rows); (_a > _b) ? _a : _b; })); typeof (crop_y) _x = (crop_y ); (_x < _a) ? _a : ((_x > _b) ? _b : _x); }) | |||
314 | ccv_max(0, resize_rows - random_jitter.size.rows))({ typeof (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter .size.rows) _b = (resize_rows - random_jitter.size.rows); (_a < _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter .size.rows); (_a < _b) ? _a : _b; })); typeof (({ typeof ( 0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter.size.rows); (_a > _b) ? _a : _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter.size .rows); (_a > _b) ? _a : _b; })); typeof (crop_y) _x = (crop_y ); (_x < _a) ? _a : ((_x > _b) ? _b : _x); }); | |||
315 | if (random_jitter.offset.x != 0) | |||
316 | crop_x += sfmt_genrand_real1(&sfmt[i]) * random_jitter.offset.x * 2 - random_jitter.offset.x; | |||
317 | if (random_jitter.offset.y != 0) | |||
318 | crop_y += sfmt_genrand_real1(&sfmt[i]) * random_jitter.offset.y * 2 - random_jitter.offset.y; | |||
319 | // If we can fill in the whole view (not introducing any 0 padding), we can first crop and then scale down / up. | |||
320 | if (resize_cols >= random_jitter.size.cols && resize_rows >= random_jitter.size.rows) | |||
321 | { | |||
322 | const float scale_x = (float)input->cols / resize_cols; | |||
323 | const float scale_y = (float)input->rows / resize_rows; | |||
324 | const int slice_cols = (int)(random_jitter.size.cols * scale_x + 0.5); | |||
325 | const int slice_rows = (int)(random_jitter.size.rows * scale_y + 0.5); | |||
326 | assert(slice_cols <= input->cols)((void) sizeof ((slice_cols <= input->cols) ? 1 : 0), __extension__ ({ if (slice_cols <= input->cols) ; else __assert_fail ("slice_cols <= input->cols", "ccv_cnnp_dataframe_addons.c" , 326, __extension__ __PRETTY_FUNCTION__); })); | |||
327 | assert(slice_rows <= input->rows)((void) sizeof ((slice_rows <= input->rows) ? 1 : 0), __extension__ ({ if (slice_rows <= input->rows) ; else __assert_fail ("slice_rows <= input->rows", "ccv_cnnp_dataframe_addons.c" , 327, __extension__ __PRETTY_FUNCTION__); })); | |||
328 | const int x = ccv_clamp((int)(crop_x * scale_x + 0.5), 0, input->cols - slice_cols)({ typeof (0) _a = (0); typeof (input->cols - slice_cols) _b = (input->cols - slice_cols); typeof ((int)(crop_x * scale_x + 0.5)) _x = ((int)(crop_x * scale_x + 0.5)); (_x < _a) ? _a : ((_x > _b) ? _b : _x); }); | |||
329 | const int y = ccv_clamp((int)(crop_y * scale_y + 0.5), 0, input->rows - slice_rows)({ typeof (0) _a = (0); typeof (input->rows - slice_rows) _b = (input->rows - slice_rows); typeof ((int)(crop_y * scale_y + 0.5)) _x = ((int)(crop_y * scale_y + 0.5)); (_x < _a) ? _a : ((_x > _b) ? _b : _x); }); | |||
330 | ccv_slice(input, (ccv_matrix_t**)&sliced, 0, y, x, slice_rows, slice_cols); | |||
331 | resize_cols = random_jitter.size.cols; | |||
332 | resize_rows = random_jitter.size.rows; | |||
333 | cropped = 1; | |||
334 | } else | |||
335 | sliced = input; | |||
336 | } else | |||
337 | sliced = input; | |||
338 | ccv_dense_matrix_t* resized = 0; | |||
339 | // Resize. | |||
340 | if (sliced->rows >= resize_rows && sliced->cols >= resize_cols) | |||
341 | { | |||
342 | // If we can fill in the whole view, we can first crop and then scale down / up. | |||
343 | ccv_resample(sliced, &resized, CCV_32F, (double)resize_rows / (double)sliced->rows, (double)resize_cols / (double)sliced->cols, CCV_INTER_AREA); | |||
344 | } else if (sliced->rows != resize_rows || sliced->cols != resize_cols) { | |||
345 | ccv_resample(sliced, &resized, CCV_32F, (double)resize_rows / (double)sliced->rows, (double)resize_cols / (double)sliced->cols, CCV_INTER_CUBIC); | |||
346 | } else { | |||
347 | ccv_shift(sliced, (ccv_matrix_t**)&resized, CCV_32F, 0, 0); // converting to 32f | |||
348 | } | |||
349 | if (sliced != input) | |||
350 | ccv_matrix_free(sliced); | |||
351 | if (random_jitter.symmetric && (sfmt_genrand_uint32(&sfmt[i]) & 1) == 0) | |||
352 | ccv_flip(resized, &resized, 0, CCV_FLIP_X); | |||
353 | _ccv_cnnp_image_manip(resized, random_jitter, &sfmt[i]); | |||
354 | // Apply normalization. Slice will introduce 0 padding, which won't be correct before normalization. | |||
355 | if (random_jitter.normalize.mean[0] != 0 || random_jitter.normalize.std[0] != 1 || | |||
356 | random_jitter.normalize.mean[1] != 0 || random_jitter.normalize.std[1] != 1 || | |||
357 | random_jitter.normalize.mean[2] != 0 || random_jitter.normalize.std[2] != 1) | |||
358 | _ccv_cnnp_normalize(resized, random_jitter.normalize.mean, random_jitter.normalize.std); | |||
359 | // If we haven't cropped in previous step (likely because we have some fill-ins due to the resize down too much). | |||
360 | // Do the crop now. | |||
361 | ccv_dense_matrix_t* patch = 0; | |||
362 | if (!cropped && need_crop) | |||
363 | { | |||
364 | ccv_slice(resized, (ccv_matrix_t**)&patch, CCV_32F, crop_y, crop_x, random_jitter.size.rows, random_jitter.size.cols); | |||
365 | ccv_matrix_free(resized); | |||
366 | } else | |||
367 | patch = resized; | |||
368 | assert(!ccv_any_nan(patch))((void) sizeof ((!ccv_any_nan(patch)) ? 1 : 0), __extension__ ({ if (!ccv_any_nan(patch)) ; else __assert_fail ("!ccv_any_nan(patch)" , "ccv_cnnp_dataframe_addons.c", 368, __extension__ __PRETTY_FUNCTION__ ); })); | |||
369 | data[i] = patch; | |||
370 | } parallel_endfor} } | |||
371 | ccfreefree(sfmt); | |||
372 | } | |||
373 | ||||
374 | int ccv_cnnp_dataframe_image_random_jitter(ccv_cnnp_dataframe_t* const dataframe, const int column_idx, const int datatype, const ccv_cnnp_random_jitter_t random_jitter, const char* name) | |||
375 | { | |||
376 | assert(datatype == CCV_32F)((void) sizeof ((datatype == CCV_32F) ? 1 : 0), __extension__ ({ if (datatype == CCV_32F) ; else __assert_fail ("datatype == CCV_32F" , "ccv_cnnp_dataframe_addons.c", 376, __extension__ __PRETTY_FUNCTION__ ); })); | |||
377 | ccv_cnnp_random_jitter_context_t* const random_jitter_context = (ccv_cnnp_random_jitter_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_random_jitter_context_t)); | |||
378 | if (random_jitter.seed) | |||
379 | sfmt_init_gen_rand(&random_jitter_context->sfmt, (uint32_t)random_jitter.seed); | |||
380 | else | |||
381 | sfmt_init_gen_rand(&random_jitter_context->sfmt, ccv_nnc_stream_context_genrand_uint32(0)); | |||
382 | random_jitter_context->datatype = datatype; | |||
383 | random_jitter_context->random_jitter = random_jitter; | |||
384 | int i; | |||
385 | // The std in the random jitter should be inv_std. | |||
386 | for (i = 0; i < 3; i++) | |||
387 | random_jitter_context->random_jitter.normalize.std[i] = random_jitter_context->random_jitter.normalize.std[i] ? 1. / random_jitter_context->random_jitter.normalize.std[i] : 1; | |||
388 | return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_random_jitter, 0, _ccv_cnnp_image_deinit, COLUMN_ID_LIST(column_idx)(const int []){column_idx}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1), random_jitter_context, (ccv_cnnp_column_data_context_deinit_f)ccfreefree, name); | |||
389 | } | |||
390 | ||||
391 | typedef struct { | |||
392 | int range; | |||
393 | int datatype; | |||
394 | int format; | |||
395 | float onval; | |||
396 | float offval; | |||
397 | off_t structof; | |||
398 | } ccv_cnnp_one_hot_context_t; | |||
399 | ||||
400 | static void _ccv_cnnp_one_hot(void* const* const* const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context) | |||
401 | { | |||
402 | ccv_cnnp_one_hot_context_t* const one_hot = (ccv_cnnp_one_hot_context_t*)context; | |||
403 | ccv_nnc_tensor_param_t params = { | |||
404 | .datatype = one_hot->datatype, | |||
405 | .type = CCV_TENSOR_CPU_MEMORY, | |||
406 | .format = one_hot->format, | |||
407 | .dim = { | |||
408 | one_hot->range, | |||
409 | }, | |||
410 | }; | |||
411 | parallel_for(i, batch_size){ int i; for ((i) = 0; (i) < (batch_size); (i)++) { { | |||
412 | int j; | |||
413 | const int label = *(const int*)((const char*)column_data[0][i] + one_hot->structof); | |||
414 | if (!data[i]) | |||
415 | data[i] = ccv_nnc_tensor_new(0, params, 0); | |||
416 | ccv_nnc_tensor_t* const tensor = (ccv_nnc_tensor_t*)data[i]; | |||
417 | assert(label >= 0 && label < one_hot->range)((void) sizeof ((label >= 0 && label < one_hot-> range) ? 1 : 0), __extension__ ({ if (label >= 0 && label < one_hot->range) ; else __assert_fail ("label >= 0 && label < one_hot->range" , "ccv_cnnp_dataframe_addons.c", 417, __extension__ __PRETTY_FUNCTION__ ); })); | |||
418 | if (tensor->info.datatype == CCV_32F) | |||
419 | for (j = 0; j < one_hot->range; j++) | |||
420 | tensor->data.f32[j] = (j == label) ? one_hot->onval : one_hot->offval; | |||
421 | else if (tensor->info.datatype == CCV_16F) | |||
422 | for (j = 0; j < one_hot->range; j++) | |||
423 | ccv_float_to_half_precision((j == label) ? &one_hot->onval : &one_hot->offval, (uint16_t*)(tensor->data.f16 + j), 1); | |||
424 | else | |||
425 | { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail ("0", "ccv_cnnp_dataframe_addons.c", 425, __extension__ __PRETTY_FUNCTION__ ); })); } | |||
426 | } parallel_endfor} } | |||
427 | } | |||
428 | ||||
429 | int ccv_cnnp_dataframe_one_hot(ccv_cnnp_dataframe_t* const dataframe, const int column_idx, const off_t structof, const int range, const float onval, const float offval, const int datatype, const int format, const char* name) | |||
430 | { | |||
431 | assert(datatype == CCV_32F || datatype == CCV_16F)((void) sizeof ((datatype == CCV_32F || datatype == CCV_16F) ? 1 : 0), __extension__ ({ if (datatype == CCV_32F || datatype == CCV_16F) ; else __assert_fail ("datatype == CCV_32F || datatype == CCV_16F" , "ccv_cnnp_dataframe_addons.c", 431, __extension__ __PRETTY_FUNCTION__ ); })); | |||
432 | ccv_cnnp_one_hot_context_t* const one_hot = (ccv_cnnp_one_hot_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_one_hot_context_t)); | |||
433 | one_hot->range = range; | |||
434 | one_hot->datatype = datatype; | |||
435 | one_hot->format = format; | |||
436 | one_hot->onval = onval; | |||
437 | one_hot->offval = offval; | |||
438 | one_hot->structof = structof; | |||
439 | return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_one_hot, 0, _ccv_cnnp_tensor_deinit, COLUMN_ID_LIST(column_idx)(const int []){column_idx}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1), one_hot, (ccv_cnnp_column_data_context_deinit_f)ccfreefree, name); | |||
440 | } | |||
441 | ||||
442 | typedef struct { | |||
443 | int from_dt; | |||
444 | int to_dt; | |||
445 | int format; | |||
446 | off_t structof; | |||
447 | } ccv_cnnp_copy_scalar_context_t; | |||
448 | ||||
449 | static void _ccv_cnnp_copy_scalar(void* const* const* const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context) | |||
450 | { | |||
451 | ccv_cnnp_copy_scalar_context_t* const copy_scalar = (ccv_cnnp_copy_scalar_context_t*)context; | |||
452 | ccv_nnc_tensor_param_t params = { | |||
453 | .datatype = copy_scalar->to_dt, | |||
454 | .type = CCV_TENSOR_CPU_MEMORY, | |||
455 | .format = copy_scalar->format, | |||
456 | .dim = {1}, | |||
457 | }; | |||
458 | parallel_for(i, batch_size){ int i; for ((i) = 0; (i) < (batch_size); (i)++) { { | |||
| ||||
459 | const ccv_numeric_data_t value = { | |||
460 | .u8 = (unsigned char *)((const char*)column_data[0][i] + copy_scalar->structof), | |||
461 | }; | |||
462 | if (!data[i]) | |||
463 | data[i] = ccv_nnc_tensor_new(0, params, 0); | |||
464 | ccv_nnc_tensor_t* const tensor = (ccv_nnc_tensor_t*)data[i]; | |||
465 | if (copy_scalar->from_dt == CCV_32S) | |||
466 | { | |||
467 | if (tensor->info.datatype == CCV_32F) | |||
468 | tensor->data.f32[0] = value.i32[0]; | |||
469 | else if (tensor->info.datatype == CCV_16F) { | |||
470 | float fval = value.i32[0]; | |||
| ||||
471 | ccv_float_to_half_precision(&fval, (uint16_t*)tensor->data.f16, 1); | |||
472 | } | |||
473 | } else if (copy_scalar->from_dt == CCV_32F) { | |||
474 | if (tensor->info.datatype == CCV_32F) | |||
475 | tensor->data.f32[0] = value.f32[0]; | |||
476 | else if (tensor->info.datatype == CCV_16F) | |||
477 | ccv_float_to_half_precision(value.f32, (uint16_t*)tensor->data.f16, 1); | |||
478 | } else if (copy_scalar->from_dt == CCV_16F) { | |||
479 | if (tensor->info.datatype == CCV_32F) | |||
480 | ccv_half_precision_to_float((uint16_t*)value.f16, tensor->data.f32, 1); | |||
481 | else if (tensor->info.datatype == CCV_16F) | |||
482 | tensor->data.f16[0] = value.f16[0]; | |||
483 | } | |||
484 | } parallel_endfor} } | |||
485 | } | |||
486 | ||||
487 | CCV_WARN_UNUSED(int)int __attribute__((warn_unused_result)) ccv_cnnp_dataframe_copy_scalar(ccv_cnnp_dataframe_t* const dataframe, const int column_idx, const off_t structof, const int from_dt, const int to_dt, const int format, const char* name) | |||
488 | { | |||
489 | assert(from_dt == CCV_32S || from_dt == CCV_32F || from_dt == CCV_16F)((void) sizeof ((from_dt == CCV_32S || from_dt == CCV_32F || from_dt == CCV_16F) ? 1 : 0), __extension__ ({ if (from_dt == CCV_32S || from_dt == CCV_32F || from_dt == CCV_16F) ; else __assert_fail ("from_dt == CCV_32S || from_dt == CCV_32F || from_dt == CCV_16F" , "ccv_cnnp_dataframe_addons.c", 489, __extension__ __PRETTY_FUNCTION__ ); })); | |||
490 | assert(to_dt == CCV_32F || to_dt == CCV_16F)((void) sizeof ((to_dt == CCV_32F || to_dt == CCV_16F) ? 1 : 0 ), __extension__ ({ if (to_dt == CCV_32F || to_dt == CCV_16F) ; else __assert_fail ("to_dt == CCV_32F || to_dt == CCV_16F" , "ccv_cnnp_dataframe_addons.c", 490, __extension__ __PRETTY_FUNCTION__ ); })); | |||
491 | ccv_cnnp_copy_scalar_context_t* const copy_scalar = (ccv_cnnp_copy_scalar_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_copy_scalar_context_t)); | |||
492 | copy_scalar->from_dt = from_dt; | |||
493 | copy_scalar->to_dt = to_dt; | |||
494 | copy_scalar->format = format; | |||
495 | copy_scalar->structof = structof; | |||
496 | return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_copy_scalar, 0, _ccv_cnnp_tensor_deinit, COLUMN_ID_LIST(column_idx)(const int []){column_idx}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + 0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1), copy_scalar, (ccv_cnnp_column_data_context_deinit_f)ccfreefree, name); | |||
497 | } | |||
498 | ||||
499 | // MARK - Matrix of Ones | |||
500 | ||||
501 | typedef struct { | |||
502 | ccv_cnnp_dataframe_tuple_t tuple; | |||
503 | int variable_size; | |||
504 | int max_length; | |||
505 | } ccv_cnnp_one_squared_context_t; | |||
506 | ||||
507 | static void _ccv_cnnp_one_squared(void* const* const* const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context) | |||
508 | { | |||
509 | ccv_cnnp_one_squared_context_t* const ones = (ccv_cnnp_one_squared_context_t*)context; | |||
510 | assert(ones->tuple.size == column_size)((void) sizeof ((ones->tuple.size == column_size) ? 1 : 0) , __extension__ ({ if (ones->tuple.size == column_size) ; else __assert_fail ("ones->tuple.size == column_size", "ccv_cnnp_dataframe_addons.c" , 510, __extension__ __PRETTY_FUNCTION__); })); | |||
511 | const int max_length = ones->max_length; | |||
512 | if (ones->variable_size) | |||
513 | { | |||
514 | parallel_for(i, batch_size){ int i; for ((i) = 0; (i) < (batch_size); (i)++) { { | |||
515 | ccv_nnc_tensor_t* const first_seq = (ccv_nnc_tensor_t*)column_data[0][i]; | |||
516 | assert(first_seq->info.datatype == CCV_32S)((void) sizeof ((first_seq->info.datatype == CCV_32S) ? 1 : 0), __extension__ ({ if (first_seq->info.datatype == CCV_32S ) ; else __assert_fail ("first_seq->info.datatype == CCV_32S" , "ccv_cnnp_dataframe_addons.c", 516, __extension__ __PRETTY_FUNCTION__ ); })); | |||
517 | const int first_len = ccv_nnc_tensor_count(first_seq->info); | |||
518 | ccv_nnc_tensor_t** outputs = data[i]; | |||
519 | if (!outputs) | |||
520 | outputs = (ccv_nnc_tensor_t**)(data[i] = cccalloccalloc(column_size, sizeof(ccv_nnc_tensor_t*))); | |||
521 | int k; | |||
522 | for (k = 0; k < column_size; k++) | |||
523 | if (!outputs[k]) | |||
524 | outputs[k] = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, first_len, max_length, max_length)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_ANY) | CCV_TENSOR_CPU_MEMORY ,.format=CCV_TENSOR_FORMAT_NHWC,.datatype=CCV_32S,.dim={first_len , max_length, max_length}}), 0); | |||
525 | int max_len = 0; | |||
526 | for (k = 0; k < column_size; k++) | |||
527 | { | |||
528 | ccv_nnc_tensor_t* const seq = (ccv_nnc_tensor_t*)column_data[k][i]; | |||
529 | assert(seq->info.datatype == CCV_32S)((void) sizeof ((seq->info.datatype == CCV_32S) ? 1 : 0), __extension__ ({ if (seq->info.datatype == CCV_32S) ; else __assert_fail ("seq->info.datatype == CCV_32S", "ccv_cnnp_dataframe_addons.c" , 529, __extension__ __PRETTY_FUNCTION__); })); | |||
530 | const int len = ccv_nnc_tensor_count(seq->info); | |||
531 | assert(len == first_len)((void) sizeof ((len == first_len) ? 1 : 0), __extension__ ({ if (len == first_len) ; else __assert_fail ("len == first_len" , "ccv_cnnp_dataframe_addons.c", 531, __extension__ __PRETTY_FUNCTION__ ); })); | |||
532 | const int* const ia = seq->data.i32; | |||
533 | int l; | |||
534 | for (l = 0; l < len; l++) | |||
535 | max_len = ccv_max(max_len, ia[l])({ typeof (max_len) _a = (max_len); typeof (ia[l]) _b = (ia[l ]); (_a > _b) ? _a : _b; }); | |||
536 | } | |||
537 | assert(max_len <= max_length)((void) sizeof ((max_len <= max_length) ? 1 : 0), __extension__ ({ if (max_len <= max_length) ; else __assert_fail ("max_len <= max_length" , "ccv_cnnp_dataframe_addons.c", 537, __extension__ __PRETTY_FUNCTION__ ); })); | |||
538 | parallel_for(c, column_size){ int c; for ((c) = 0; (c) < (column_size); (c)++) { { | |||
539 | ccv_nnc_tensor_t* const seq = (ccv_nnc_tensor_t*)column_data[c][i]; | |||
540 | assert(seq->info.datatype == CCV_32S)((void) sizeof ((seq->info.datatype == CCV_32S) ? 1 : 0), __extension__ ({ if (seq->info.datatype == CCV_32S) ; else __assert_fail ("seq->info.datatype == CCV_32S", "ccv_cnnp_dataframe_addons.c" , 540, __extension__ __PRETTY_FUNCTION__); })); | |||
541 | const int len = ccv_nnc_tensor_count(seq->info); | |||
542 | assert(len == first_len)((void) sizeof ((len == first_len) ? 1 : 0), __extension__ ({ if (len == first_len) ; else __assert_fail ("len == first_len" , "ccv_cnnp_dataframe_addons.c", 542, __extension__ __PRETTY_FUNCTION__ ); })); | |||
543 | ccv_nnc_tensor_t* tensor = outputs[c]; | |||
544 | tensor = ccv_nnc_tensor_resize(tensor, CPU_TENSOR_NHWC(32S, len, max_len, max_len)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_ANY) | CCV_TENSOR_CPU_MEMORY ,.format=CCV_TENSOR_FORMAT_NHWC,.datatype=CCV_32S,.dim={len, max_len , max_len}})); | |||
545 | assert(outputs[c] == tensor)((void) sizeof ((outputs[c] == tensor) ? 1 : 0), __extension__ ({ if (outputs[c] == tensor) ; else __assert_fail ("outputs[c] == tensor" , "ccv_cnnp_dataframe_addons.c", 545, __extension__ __PRETTY_FUNCTION__ ); })); // Since we allocated with max_length, this cannot be reallocated. | |||
546 | const int* const ia = seq->data.i32; | |||
547 | parallel_for(j, len){ int j; for ((j) = 0; (j) < (len); (j)++) { { | |||
548 | int x, y; | |||
549 | int seq_len = ia[j]; | |||
550 | int* ib = tensor->data.i32 + j * max_len * max_len; | |||
551 | for (y = 0; y < seq_len; y++) | |||
552 | { | |||
553 | for (x = 0; x < seq_len; x++) | |||
554 | ib[x] = 1; | |||
555 | for (x = seq_len; x < max_len; x++) | |||
556 | ib[x] = 0; | |||
557 | ib += max_len; | |||
558 | } | |||
559 | if (seq_len < max_len) | |||
560 | memset(ib, 0, sizeof(int) * max_len * (max_len - seq_len)); | |||
561 | } parallel_endfor} } | |||
562 | } parallel_endfor} } | |||
563 | } parallel_endfor} } | |||
564 | } else { | |||
565 | parallel_for(i, batch_size){ int i; for ((i) = 0; (i) < (batch_size); (i)++) { { | |||
566 | ccv_nnc_tensor_t** outputs = data[i]; | |||
567 | ccv_nnc_tensor_t* const first_seq = (ccv_nnc_tensor_t*)column_data[0][i]; | |||
568 | assert(first_seq->info.datatype == CCV_32S)((void) sizeof ((first_seq->info.datatype == CCV_32S) ? 1 : 0), __extension__ ({ if (first_seq->info.datatype == CCV_32S ) ; else __assert_fail ("first_seq->info.datatype == CCV_32S" , "ccv_cnnp_dataframe_addons.c", 568, __extension__ __PRETTY_FUNCTION__ ); })); | |||
569 | const int first_len = ccv_nnc_tensor_count(first_seq->info); | |||
570 | if (!outputs) | |||
571 | outputs = (ccv_nnc_tensor_t**)(data[i] = cccalloccalloc(column_size, sizeof(ccv_nnc_tensor_t*))); | |||
572 | int k; | |||
573 | for (k = 0; k < column_size; k++) | |||
574 | if (!outputs[k]) | |||
575 | outputs[k] = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, first_len, max_length, max_length)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_ANY) | CCV_TENSOR_CPU_MEMORY ,.format=CCV_TENSOR_FORMAT_NHWC,.datatype=CCV_32S,.dim={first_len , max_length, max_length}}), 0); | |||
576 | parallel_for(c, column_size){ int c; for ((c) = 0; (c) < (column_size); (c)++) { { | |||
577 | ccv_nnc_tensor_t* const tensor = outputs[c]; | |||
578 | ccv_nnc_tensor_t* const seq = (ccv_nnc_tensor_t*)column_data[c][i]; | |||
579 | assert(seq->info.datatype == CCV_32S)((void) sizeof ((seq->info.datatype == CCV_32S) ? 1 : 0), __extension__ ({ if (seq->info.datatype == CCV_32S) ; else __assert_fail ("seq->info.datatype == CCV_32S", "ccv_cnnp_dataframe_addons.c" , 579, __extension__ __PRETTY_FUNCTION__); })); | |||
580 | const int len = ccv_nnc_tensor_count(seq->info); | |||
581 | assert(len == first_len)((void) sizeof ((len == first_len) ? 1 : 0), __extension__ ({ if (len == first_len) ; else __assert_fail ("len == first_len" , "ccv_cnnp_dataframe_addons.c", 581, __extension__ __PRETTY_FUNCTION__ ); })); | |||
582 | const int* const ia = seq->data.i32; | |||
583 | parallel_for(j, len){ int j; for ((j) = 0; (j) < (len); (j)++) { { | |||
584 | int x, y; | |||
585 | int seq_len = ia[j]; | |||
586 | int* ib = tensor->data.i32 + j * max_length * max_length; | |||
587 | for (y = 0; y < seq_len; y++) | |||
588 | { | |||
589 | for (x = 0; x < seq_len; x++) | |||
590 | ib[x] = 1; | |||
591 | for (x = seq_len; x < max_length; x++) | |||
592 | ib[x] = 0; | |||
593 | ib += max_length; | |||
594 | } | |||
595 | if (seq_len < max_length) | |||
596 | memset(ib, 0, sizeof(int) * max_length * (max_length - seq_len)); | |||
597 | } parallel_endfor} } | |||
598 | } parallel_endfor} } | |||
599 | } parallel_endfor} } | |||
600 | } | |||
601 | } | |||
602 | ||||
603 | CCV_WARN_UNUSED(int)int __attribute__((warn_unused_result)) ccv_cnnp_dataframe_one_squared(ccv_cnnp_dataframe_t* const dataframe, const int* const column_idxs, const int column_idx_size, const int variable_size, const int max_length, const char* name) | |||
604 | { | |||
605 | assert(max_length > 0)((void) sizeof ((max_length > 0) ? 1 : 0), __extension__ ( { if (max_length > 0) ; else __assert_fail ("max_length > 0" , "ccv_cnnp_dataframe_addons.c", 605, __extension__ __PRETTY_FUNCTION__ ); })); | |||
606 | assert(variable_size == 0 || variable_size == 1)((void) sizeof ((variable_size == 0 || variable_size == 1) ? 1 : 0), __extension__ ({ if (variable_size == 0 || variable_size == 1) ; else __assert_fail ("variable_size == 0 || variable_size == 1" , "ccv_cnnp_dataframe_addons.c", 606, __extension__ __PRETTY_FUNCTION__ ); })); | |||
607 | ccv_cnnp_one_squared_context_t* const ones = (ccv_cnnp_one_squared_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_one_squared_context_t)); | |||
608 | ones->tuple.size = column_idx_size; | |||
609 | ones->variable_size = variable_size; | |||
610 | ones->max_length = max_length; | |||
611 | return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_one_squared, 0, _ccv_cnnp_tensor_list_deinit, column_idxs, column_idx_size, ones, (ccv_cnnp_column_data_context_deinit_f)ccfreefree, name); | |||
612 | } | |||
613 | ||||
614 | // MARK - Truncate Matrix | |||
615 | ||||
616 | static void _ccv_cnnp_truncate(void* const* const* const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context) | |||
617 | { | |||
618 | assert(column_size >= 2)((void) sizeof ((column_size >= 2) ? 1 : 0), __extension__ ({ if (column_size >= 2) ; else __assert_fail ("column_size >= 2" , "ccv_cnnp_dataframe_addons.c", 618, __extension__ __PRETTY_FUNCTION__ ); })); | |||
619 | assert(column_size % 2 == 0)((void) sizeof ((column_size % 2 == 0) ? 1 : 0), __extension__ ({ if (column_size % 2 == 0) ; else __assert_fail ("column_size % 2 == 0" , "ccv_cnnp_dataframe_addons.c", 619, __extension__ __PRETTY_FUNCTION__ ); })); | |||
620 | const int tuple_size = column_size / 2; | |||
621 | ccv_cnnp_dataframe_tuple_t* const tuple = (ccv_cnnp_dataframe_tuple_t*)context; | |||
622 | assert(tuple->size == tuple_size)((void) sizeof ((tuple->size == tuple_size) ? 1 : 0), __extension__ ({ if (tuple->size == tuple_size) ; else __assert_fail ("tuple->size == tuple_size" , "ccv_cnnp_dataframe_addons.c", 622, __extension__ __PRETTY_FUNCTION__ ); })); | |||
623 | parallel_for(i, batch_size){ int i; for ((i) = 0; (i) < (batch_size); (i)++) { { | |||
624 | int k; | |||
625 | ccv_nnc_tensor_t* const first_seq = (ccv_nnc_tensor_t*)column_data[tuple_size][i]; | |||
626 | assert(first_seq->info.datatype == CCV_32S)((void) sizeof ((first_seq->info.datatype == CCV_32S) ? 1 : 0), __extension__ ({ if (first_seq->info.datatype == CCV_32S ) ; else __assert_fail ("first_seq->info.datatype == CCV_32S" , "ccv_cnnp_dataframe_addons.c", 626, __extension__ __PRETTY_FUNCTION__ ); })); | |||
627 | const int first_len = ccv_nnc_tensor_count(first_seq->info); | |||
628 | int max_len = 0; | |||
629 | for (k = 0; k < tuple_size; k++) | |||
630 | { | |||
631 | ccv_nnc_tensor_t* const seq = (ccv_nnc_tensor_t*)column_data[tuple_size + k][i]; | |||
632 | assert(seq->info.datatype == CCV_32S)((void) sizeof ((seq->info.datatype == CCV_32S) ? 1 : 0), __extension__ ({ if (seq->info.datatype == CCV_32S) ; else __assert_fail ("seq->info.datatype == CCV_32S", "ccv_cnnp_dataframe_addons.c" , 632, __extension__ __PRETTY_FUNCTION__); })); | |||
633 | const int len = ccv_nnc_tensor_count(seq->info); | |||
634 | assert(len == first_len)((void) sizeof ((len == first_len) ? 1 : 0), __extension__ ({ if (len == first_len) ; else __assert_fail ("len == first_len" , "ccv_cnnp_dataframe_addons.c", 634, __extension__ __PRETTY_FUNCTION__ ); })); | |||
635 | const int* const ia = seq->data.i32; | |||
636 | int l; | |||
637 | for (l = 0; l < len; l++) | |||
638 | max_len = ccv_max(max_len, ia[l])({ typeof (max_len) _a = (max_len); typeof (ia[l]) _b = (ia[l ]); (_a > _b) ? _a : _b; }); | |||
639 | } | |||
640 | ccv_nnc_tensor_t* const first_inp = (ccv_nnc_tensor_t*)column_data[0][i]; | |||
641 | ccv_nnc_tensor_param_t first_params = first_inp->info; | |||
642 | assert(first_params.dim[0] == first_len)((void) sizeof ((first_params.dim[0] == first_len) ? 1 : 0), __extension__ ({ if (first_params.dim[0] == first_len) ; else __assert_fail ("first_params.dim[0] == first_len", "ccv_cnnp_dataframe_addons.c" , 642, __extension__ __PRETTY_FUNCTION__); })); | |||
643 | assert(max_len <= first_params.dim[1])((void) sizeof ((max_len <= first_params.dim[1]) ? 1 : 0), __extension__ ({ if (max_len <= first_params.dim[1]) ; else __assert_fail ("max_len <= first_params.dim[1]", "ccv_cnnp_dataframe_addons.c" , 643, __extension__ __PRETTY_FUNCTION__); })); | |||
644 | first_params.dim[1] = max_len; | |||
645 | ccv_nnc_tensor_t** outputs = data[i]; | |||
646 | if (!outputs) | |||
647 | outputs = (ccv_nnc_tensor_t**)(data[i] = cccalloccalloc(tuple_size, sizeof(ccv_nnc_tensor_t*))); | |||
648 | for (k = 0; k < tuple_size; k++) | |||
649 | { | |||
650 | if (!outputs[k]) | |||
651 | outputs[k] = ccv_nnc_tensor_new(0, first_params, 0); | |||
652 | else | |||
653 | outputs[k] = ccv_nnc_tensor_resize(outputs[k], first_params); | |||
654 | } | |||
655 | parallel_for(c, tuple_size){ int c; for ((c) = 0; (c) < (tuple_size); (c)++) { { | |||
656 | ccv_nnc_tensor_t* const seq = (ccv_nnc_tensor_t*)column_data[tuple_size + c][i]; | |||
657 | assert(seq->info.datatype == CCV_32S)((void) sizeof ((seq->info.datatype == CCV_32S) ? 1 : 0), __extension__ ({ if (seq->info.datatype == CCV_32S) ; else __assert_fail ("seq->info.datatype == CCV_32S", "ccv_cnnp_dataframe_addons.c" , 657, __extension__ __PRETTY_FUNCTION__); })); | |||
658 | const int len = ccv_nnc_tensor_count(seq->info); | |||
659 | ccv_nnc_tensor_t* const inp = (ccv_nnc_tensor_t*)column_data[c][i]; | |||
660 | ccv_nnc_tensor_param_t params = inp->info; | |||
661 | assert(params.dim[0] == len)((void) sizeof ((params.dim[0] == len) ? 1 : 0), __extension__ ({ if (params.dim[0] == len) ; else __assert_fail ("params.dim[0] == len" , "ccv_cnnp_dataframe_addons.c", 661, __extension__ __PRETTY_FUNCTION__ ); })); | |||
662 | assert(first_len == len)((void) sizeof ((first_len == len) ? 1 : 0), __extension__ ({ if (first_len == len) ; else __assert_fail ("first_len == len" , "ccv_cnnp_dataframe_addons.c", 662, __extension__ __PRETTY_FUNCTION__ ); })); | |||
663 | assert(max_len <= params.dim[1])((void) sizeof ((max_len <= params.dim[1]) ? 1 : 0), __extension__ ({ if (max_len <= params.dim[1]) ; else __assert_fail ("max_len <= params.dim[1]" , "ccv_cnnp_dataframe_addons.c", 663, __extension__ __PRETTY_FUNCTION__ ); })); | |||
664 | assert(params.dim[2] == 0)((void) sizeof ((params.dim[2] == 0) ? 1 : 0), __extension__ ( { if (params.dim[2] == 0) ; else __assert_fail ("params.dim[2] == 0" , "ccv_cnnp_dataframe_addons.c", 664, __extension__ __PRETTY_FUNCTION__ ); })); | |||
665 | const int ori_len = params.dim[1]; | |||
666 | ccv_nnc_tensor_t* const out = outputs[c]; | |||
667 | uint8_t* const ua = inp->data.u8; | |||
668 | uint8_t* const ub = out->data.u8; | |||
669 | size_t la = CCV_GET_DATA_TYPE_SIZE(params.datatype)_ccv_get_data_type_size[((params.datatype) & 0xFF000) >> 12] * ori_len; | |||
670 | size_t lb = CCV_GET_DATA_TYPE_SIZE(params.datatype)_ccv_get_data_type_size[((params.datatype) & 0xFF000) >> 12] * max_len; | |||
671 | parallel_for(j, len){ int j; for ((j) = 0; (j) < (len); (j)++) { { | |||
672 | memcpy(ub + lb * j, ua + la * j, lb); | |||
673 | } parallel_endfor} } | |||
674 | } parallel_endfor} } | |||
675 | } parallel_endfor} } | |||
676 | } | |||
677 | ||||
678 | int ccv_cnnp_dataframe_truncate(ccv_cnnp_dataframe_t* const dataframe, const int* const vec_idxs, const int vec_idx_size, const int* const len_idxs, const int len_idx_size, const char* name) | |||
679 | { | |||
680 | const int total_idx_size = vec_idx_size + len_idx_size; | |||
681 | assert(total_idx_size > 0)((void) sizeof ((total_idx_size > 0) ? 1 : 0), __extension__ ({ if (total_idx_size > 0) ; else __assert_fail ("total_idx_size > 0" , "ccv_cnnp_dataframe_addons.c", 681, __extension__ __PRETTY_FUNCTION__ ); })); | |||
682 | assert(vec_idx_size == len_idx_size)((void) sizeof ((vec_idx_size == len_idx_size) ? 1 : 0), __extension__ ({ if (vec_idx_size == len_idx_size) ; else __assert_fail ("vec_idx_size == len_idx_size" , "ccv_cnnp_dataframe_addons.c", 682, __extension__ __PRETTY_FUNCTION__ ); })); | |||
683 | int total_idxs[total_idx_size]; | |||
684 | memcpy(total_idxs, vec_idxs, sizeof(int) * vec_idx_size); | |||
685 | memcpy(total_idxs + vec_idx_size, len_idxs, sizeof(int) * len_idx_size); | |||
686 | ccv_cnnp_dataframe_tuple_t* const tuple = (ccv_cnnp_dataframe_tuple_t*)ccmallocmalloc(sizeof(ccv_cnnp_dataframe_tuple_t)); | |||
687 | tuple->size = vec_idx_size; | |||
688 | return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_truncate, 0, _ccv_cnnp_tensor_list_deinit, total_idxs, total_idx_size, tuple, (ccv_cnnp_column_data_context_deinit_f)ccfreefree, name); | |||
689 | } | |||
690 | ||||
691 | // MARK - Batching | |||
692 | ||||
693 | typedef struct { | |||
694 | ccv_cnnp_dataframe_tuple_t tuple; | |||
695 | int format; | |||
696 | int batch_count; | |||
697 | int group_count; | |||
698 | } ccv_cnnp_batch_context_t; | |||
699 | ||||
700 | static void _ccv_cnnp_combine_new(void* const* const input_data, const int input_size, void** const output_data, void* const context, ccv_nnc_stream_context_t* const stream_context) | |||
701 | { | |||
702 | ccv_cnnp_batch_context_t* const batch = (ccv_cnnp_batch_context_t*)context; | |||
703 | const int output_tuple_size = batch->tuple.size; | |||
704 | const int batch_count = batch->batch_count; | |||
705 | const int group_count = batch->group_count; | |||
706 | const int input_tuple_size = output_tuple_size / group_count; | |||
707 | int i, j, k; | |||
708 | assert(input_size > 0)((void) sizeof ((input_size > 0) ? 1 : 0), __extension__ ( { if (input_size > 0) ; else __assert_fail ("input_size > 0" , "ccv_cnnp_dataframe_addons.c", 708, __extension__ __PRETTY_FUNCTION__ ); })); | |||
709 | if (!output_data[0]) | |||
710 | { | |||
711 | ccv_nnc_tensor_t** const inputs = (ccv_nnc_tensor_t**)input_data[0]; | |||
712 | ccv_nnc_tensor_t** const tensors = (ccv_nnc_tensor_t**)(output_data[0] = ccmallocmalloc(sizeof(ccv_nnc_tensor_t*) * output_tuple_size)); | |||
713 | for (i = 0; i < group_count; i++) | |||
714 | for (j = 0; j < input_tuple_size; j++) | |||
715 | { | |||
716 | ccv_nnc_tensor_param_t params = inputs[j]->info; | |||
717 | assert(params.datatype == CCV_32F || params.datatype == CCV_32S || params.datatype == CCV_16F)((void) sizeof ((params.datatype == CCV_32F || params.datatype == CCV_32S || params.datatype == CCV_16F) ? 1 : 0), __extension__ ({ if (params.datatype == CCV_32F || params.datatype == CCV_32S || params.datatype == CCV_16F) ; else __assert_fail ("params.datatype == CCV_32F || params.datatype == CCV_32S || params.datatype == CCV_16F" , "ccv_cnnp_dataframe_addons.c", 717, __extension__ __PRETTY_FUNCTION__ ); })); // Only support 32 bit float yet. | |||
718 | assert(params.format == CCV_TENSOR_FORMAT_NHWC || params.format == CCV_TENSOR_FORMAT_NCHW)((void) sizeof ((params.format == CCV_TENSOR_FORMAT_NHWC || params .format == CCV_TENSOR_FORMAT_NCHW) ? 1 : 0), __extension__ ({ if (params.format == CCV_TENSOR_FORMAT_NHWC || params.format == CCV_TENSOR_FORMAT_NCHW) ; else __assert_fail ("params.format == CCV_TENSOR_FORMAT_NHWC || params.format == CCV_TENSOR_FORMAT_NCHW" , "ccv_cnnp_dataframe_addons.c", 718, __extension__ __PRETTY_FUNCTION__ ); })); | |||
719 | params.format = batch->format; | |||
720 | // Special-case for dim count is 3 and 1, in these two cases, the N is not provided. | |||
721 | if (batch->format == inputs[j]->info.format) | |||
722 | { | |||
723 | const int nd = ccv_nnc_tensor_nd(params.dim); | |||
724 | memset(params.dim, 0, sizeof(int) * CCV_NNC_MAX_DIM_ALLOC(12)); | |||
725 | memcpy(params.dim + 1, inputs[j]->info.dim, sizeof(int) * nd); | |||
726 | } else { | |||
727 | const int nd = ccv_nnc_tensor_nd(params.dim); | |||
728 | if (nd < 3) | |||
729 | { | |||
730 | memset(params.dim, 0, sizeof(int) * CCV_NNC_MAX_DIM_ALLOC(12)); | |||
731 | memcpy(params.dim + 1, inputs[j]->info.dim, sizeof(int) * nd); | |||
732 | } else if (nd >= 3) { | |||
733 | memset(params.dim, 0, sizeof(int) * CCV_NNC_MAX_DIM_ALLOC(12)); | |||
734 | const int hw = ccv_nnc_tensor_hw(inputs[j]->info, nd); | |||
735 | if (batch->format == CCV_TENSOR_FORMAT_NCHW) | |||
736 | { | |||
737 | params.dim[1] = ccv_nnc_tensor_get_c(inputs[j]->info); | |||
738 | for (k = 0; k < CCV_NNC_MAX_DIM(2); k++) | |||
739 | params.dim[k + 2] = inputs[j]->info.dim[k + hw]; | |||
740 | } else { | |||
741 | params.dim[CCV_NNC_MAX_DIM(2) + 1] = ccv_nnc_tensor_get_c(inputs[j]->info); | |||
742 | for (k = 0; k < CCV_NNC_MAX_DIM(2); k++) | |||
743 | params.dim[k + 1] = inputs[j]->info.dim[k + hw]; | |||
744 | } | |||
745 | } | |||
746 | } | |||
747 | params.dim[0] = batch_count; // Set the batch count now. | |||
748 | tensors[i * input_tuple_size + j] = ccv_nnc_tensor_new(0, params, 0); | |||
749 | } | |||
750 | } | |||
751 | for (i = 0; i < group_count; i++) | |||
752 | for (j = 0; j < input_tuple_size; j++) | |||
753 | { | |||
754 | ccv_nnc_tensor_t* const output = ((ccv_nnc_tensor_t**)output_data[0])[i * input_tuple_size + j]; | |||
755 | parallel_for(k, batch_count){ int k; for ((k) = 0; (k) < (batch_count); (k)++) { { | |||
756 | ccv_nnc_tensor_t* const input = ((ccv_nnc_tensor_t**)input_data[(k + i * batch_count) % input_size])[j]; | |||
757 | const size_t tensor_count = ccv_nnc_tensor_count(input->info); | |||
758 | if (input->info.datatype == CCV_32F) | |||
759 | { | |||
760 | float* const ap = input->data.f32; | |||
761 | float* const bp = output->data.f32 + k * tensor_count; | |||
762 | if (input->info.format == output->info.format) | |||
763 | memcpy(bp, ap, sizeof(float) * tensor_count); | |||
764 | else { | |||
765 | // Do a simple format conversion. | |||
766 | const int c = ccv_nnc_tensor_get_c(input->info); | |||
767 | assert(c > 0)((void) sizeof ((c > 0) ? 1 : 0), __extension__ ({ if (c > 0) ; else __assert_fail ("c > 0", "ccv_cnnp_dataframe_addons.c" , 767, __extension__ __PRETTY_FUNCTION__); })); | |||
768 | const size_t hw_count = tensor_count / c; | |||
769 | size_t x; | |||
770 | int y; | |||
771 | if (input->info.format == CCV_TENSOR_FORMAT_NHWC && output->info.format == CCV_TENSOR_FORMAT_NCHW) | |||
772 | for (x = 0; x < hw_count; x++) | |||
773 | for (y = 0; y < c; y++) | |||
774 | bp[y * hw_count + x] = ap[x * c + y]; | |||
775 | else if (input->info.format == CCV_TENSOR_FORMAT_NCHW && output->info.format == CCV_TENSOR_FORMAT_NHWC) | |||
776 | for (x = 0; x < hw_count; x++) | |||
777 | for (y = 0; y < c; y++) | |||
778 | bp[x * c + y] = ap[y * hw_count + x]; | |||
779 | } | |||
780 | } else if (input->info.datatype == CCV_32S) { | |||
781 | int* const ap = input->data.i32; | |||
782 | int* const bp = output->data.i32 + k * tensor_count; | |||
783 | if (input->info.format == output->info.format) | |||
784 | memcpy(bp, ap, sizeof(int) * tensor_count); | |||
785 | else { | |||
786 | // Do a simple format conversion. | |||
787 | const int c = ccv_nnc_tensor_get_c(input->info); | |||
788 | assert(c > 0)((void) sizeof ((c > 0) ? 1 : 0), __extension__ ({ if (c > 0) ; else __assert_fail ("c > 0", "ccv_cnnp_dataframe_addons.c" , 788, __extension__ __PRETTY_FUNCTION__); })); | |||
789 | const size_t hw_count = tensor_count / c; | |||
790 | size_t x; | |||
791 | int y; | |||
792 | if (input->info.format == CCV_TENSOR_FORMAT_NHWC && output->info.format == CCV_TENSOR_FORMAT_NCHW) | |||
793 | for (x = 0; x < hw_count; x++) | |||
794 | for (y = 0; y < c; y++) | |||
795 | bp[y * hw_count + x] = ap[x * c + y]; | |||
796 | else if (input->info.format == CCV_TENSOR_FORMAT_NCHW && output->info.format == CCV_TENSOR_FORMAT_NHWC) | |||
797 | for (x = 0; x < hw_count; x++) | |||
798 | for (y = 0; y < c; y++) | |||
799 | bp[x * c + y] = ap[y * hw_count + x]; | |||
800 | } | |||
801 | } else if (input->info.datatype == CCV_16F) { | |||
802 | ccv_float16_t* const ap = input->data.f16; | |||
803 | ccv_float16_t* const bp = output->data.f16 + k * tensor_count; | |||
804 | if (input->info.format == output->info.format) | |||
805 | memcpy(bp, ap, sizeof(ccv_float16_t) * tensor_count); | |||
806 | else { | |||
807 | // Do a simple format conversion. | |||
808 | const int c = ccv_nnc_tensor_get_c(input->info); | |||
809 | assert(c > 0)((void) sizeof ((c > 0) ? 1 : 0), __extension__ ({ if (c > 0) ; else __assert_fail ("c > 0", "ccv_cnnp_dataframe_addons.c" , 809, __extension__ __PRETTY_FUNCTION__); })); | |||
810 | const size_t hw_count = tensor_count / c; | |||
811 | size_t x; | |||
812 | int y; | |||
813 | if (input->info.format == CCV_TENSOR_FORMAT_NHWC && output->info.format == CCV_TENSOR_FORMAT_NCHW) | |||
814 | for (x = 0; x < hw_count; x++) | |||
815 | for (y = 0; y < c; y++) | |||
816 | bp[y * hw_count + x] = ap[x * c + y]; | |||
817 | else if (input->info.format == CCV_TENSOR_FORMAT_NCHW && output->info.format == CCV_TENSOR_FORMAT_NHWC) | |||
818 | for (x = 0; x < hw_count; x++) | |||
819 | for (y = 0; y < c; y++) | |||
820 | bp[x * c + y] = ap[y * hw_count + x]; | |||
821 | } | |||
822 | } else { | |||
823 | assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail ("0", "ccv_cnnp_dataframe_addons.c", 823, __extension__ __PRETTY_FUNCTION__ ); })); | |||
824 | } | |||
825 | } parallel_endfor} } | |||
826 | } | |||
827 | } | |||
828 | ||||
829 | static void _ccv_cnnp_combine_deinit(void* const self, void* const context) | |||
830 | { | |||
831 | ccv_cnnp_batch_context_t* const batch = (ccv_cnnp_batch_context_t*)context; | |||
832 | ccv_nnc_tensor_t** const tensors = (ccv_nnc_tensor_t**)self; | |||
833 | const int size = batch->tuple.size; | |||
834 | int i; | |||
835 | for (i = 0; i < size; i++) | |||
836 | ccv_nnc_tensor_free(tensors[i]); | |||
837 | ccfreefree(tensors); | |||
838 | } | |||
839 | ||||
840 | ccv_cnnp_dataframe_t* ccv_cnnp_dataframe_combine_new(ccv_cnnp_dataframe_t* const dataframe, const int* const column_idxs, const int column_idx_size, const int batch_count, const int group_count, const int format) | |||
841 | { | |||
842 | assert(format == CCV_TENSOR_FORMAT_NCHW || format == CCV_TENSOR_FORMAT_NHWC)((void) sizeof ((format == CCV_TENSOR_FORMAT_NCHW || format == CCV_TENSOR_FORMAT_NHWC) ? 1 : 0), __extension__ ({ if (format == CCV_TENSOR_FORMAT_NCHW || format == CCV_TENSOR_FORMAT_NHWC ) ; else __assert_fail ("format == CCV_TENSOR_FORMAT_NCHW || format == CCV_TENSOR_FORMAT_NHWC" , "ccv_cnnp_dataframe_addons.c", 842, __extension__ __PRETTY_FUNCTION__ ); })); | |||
843 | assert(column_idx_size >= 1)((void) sizeof ((column_idx_size >= 1) ? 1 : 0), __extension__ ({ if (column_idx_size >= 1) ; else __assert_fail ("column_idx_size >= 1" , "ccv_cnnp_dataframe_addons.c", 843, __extension__ __PRETTY_FUNCTION__ ); })); | |||
844 | assert(batch_count > 0)((void) sizeof ((batch_count > 0) ? 1 : 0), __extension__ ( { if (batch_count > 0) ; else __assert_fail ("batch_count > 0" , "ccv_cnnp_dataframe_addons.c", 844, __extension__ __PRETTY_FUNCTION__ ); })); | |||
845 | assert(group_count > 0)((void) sizeof ((group_count > 0) ? 1 : 0), __extension__ ( { if (group_count > 0) ; else __assert_fail ("group_count > 0" , "ccv_cnnp_dataframe_addons.c", 845, __extension__ __PRETTY_FUNCTION__ ); })); | |||
846 | const int derived = ccv_cnnp_dataframe_make_tuple(dataframe, column_idxs, column_idx_size, 0); | |||
847 | ccv_cnnp_batch_context_t* const batch = (ccv_cnnp_batch_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_batch_context_t)); | |||
848 | batch->tuple.size = column_idx_size * group_count; | |||
849 | batch->format = format; | |||
850 | batch->batch_count = batch_count; | |||
851 | batch->group_count = group_count; | |||
852 | return ccv_cnnp_dataframe_sample_new(dataframe, _ccv_cnnp_combine_new, _ccv_cnnp_combine_deinit, derived, batch_count * group_count, batch, (ccv_cnnp_column_data_context_deinit_f)ccfreefree); | |||
853 | } |