Bug Summary

File:nnc/ccv_nnc_tensor_io.c
Warning:line 482, column 22
Although the value stored to 'tensor' is used in the enclosing expression, the value is never actually read from 'tensor'

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_nnc_tensor_io.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/2026-04-30-181353-1393048-1 -x c ccv_nnc_tensor_io.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_nnc_symbolic_graph.h"
6#include "3rdparty/sqlite3/sqlite3.h"
7#include <limits.h>
8#include <stdint.h>
9#ifdef HAVE_CUDA1
10#include "gpu/ccv_nnc_compat.h"
11#elif HAVE_MPS
12#include "mps/ccv_nnc_mps.h"
13#endif
14
15#ifdef NDEBUG
16#define SQLITE_ENFORCE(stmt)((void) sizeof ((stmt) ? 1 : 0), __extension__ ({ if (stmt) ;
else __assert_fail ("stmt", "ccv_nnc_tensor_io.c", 16, __extension__
__PRETTY_FUNCTION__); }))
(void)(stmt)
17#else
18#define SQLITE_ENFORCEassert assert
19#endif
20
21// SQLite INTEGER is 64-bit. Tensor IO already packs side metadata into the
22// high 32 bits of type / datatype. Tensor formats are low 32-bit int enum
23// values (NCHW/NHWC/CHWN), so bit 32 can mark that tensors.data is the head
24// chunk. Always mask this out before assigning to ccv_nnc_tensor_param_t.format.
25#define CCV_NNC_TENSOR_IO_SPLIT_FORMAT(((sqlite_int64)1) << 32) (((sqlite_int64)1) << 32)
26#define CCV_NNC_TENSOR_IO_FORMAT_MASK0xffffffffll 0xffffffffll
27#define CCV_NNC_TENSOR_IO_SPLIT_HEADROOM1024 1024
28
29static int _ccv_nnc_tensor_io_blob_chunk_size(sqlite3* const conn)
30{
31 const int limit = sqlite3_limit(conn, SQLITE_LIMIT_LENGTH0, -1);
32 if (limit <= 0)
33 return INT_MAX2147483647;
34 if (limit > CCV_NNC_TENSOR_IO_SPLIT_HEADROOM1024 * 2)
35 return limit - CCV_NNC_TENSOR_IO_SPLIT_HEADROOM1024;
36 return limit > 1 ? limit / 2 : 1;
37}
38
39static int _ccv_nnc_tensor_io_delete_splits(sqlite3* const conn, const char* const name)
40{
41 const char tensor_split_delete_qs[] = "DELETE FROM tensor_splits WHERE name=$name";
42 sqlite3_stmt* tensor_split_delete_stmt = 0;
43 int rc = sqlite3_prepare_v2(conn, tensor_split_delete_qs, sizeof(tensor_split_delete_qs), &tensor_split_delete_stmt, 0);
44 if (rc != SQLITE_OK0)
45 return rc;
46 sqlite3_bind_text(tensor_split_delete_stmt, 1, name, -1, SQLITE_STATIC((sqlite3_destructor_type)0));
47 rc = sqlite3_step(tensor_split_delete_stmt);
48 sqlite3_finalize(tensor_split_delete_stmt);
49 return rc == SQLITE_DONE101 ? SQLITE_OK0 : rc;
50}
51
52static int _ccv_nnc_tensor_io_write_splits(sqlite3* const conn, const char* const name, const unsigned char* const data, const size_t data_size, const size_t offset, const int chunk_size)
53{
54 const char tensor_split_insert_qs[] =
55 "REPLACE INTO tensor_splits "
56 "(name, part, data) VALUES ($name, $part, $data)";
57 sqlite3_stmt* tensor_split_insert_stmt = 0;
58 int rc = sqlite3_prepare_v2(conn, tensor_split_insert_qs, sizeof(tensor_split_insert_qs), &tensor_split_insert_stmt, 0);
59 if (rc != SQLITE_OK0)
60 return rc;
61 size_t pos = offset;
62 int part = 0;
63 while (pos < data_size)
64 {
65 const size_t tail_size = data_size - pos;
66 const int write_size = (int)ccv_min(tail_size, (size_t)chunk_size)({ typeof (tail_size) _a = (tail_size); typeof ((size_t)chunk_size
) _b = ((size_t)chunk_size); (_a < _b) ? _a : _b; })
;
67 sqlite3_bind_text(tensor_split_insert_stmt, 1, name, -1, SQLITE_STATIC((sqlite3_destructor_type)0));
68 sqlite3_bind_int(tensor_split_insert_stmt, 2, part++);
69 rc = sqlite3_bind_blob(tensor_split_insert_stmt, 3, data + pos, write_size, SQLITE_STATIC((sqlite3_destructor_type)0));
70 if (rc != SQLITE_OK0)
71 break;
72 rc = sqlite3_step(tensor_split_insert_stmt);
73 if (rc != SQLITE_DONE101)
74 break;
75 sqlite3_reset(tensor_split_insert_stmt);
76 sqlite3_clear_bindings(tensor_split_insert_stmt);
77 pos += write_size;
78 }
79 sqlite3_finalize(tensor_split_insert_stmt);
80 return rc == SQLITE_DONE101 ? SQLITE_OK0 : rc;
81}
82
83static int _ccv_nnc_tensor_io_read_split_data(sqlite3* const conn, const char* const name, const void* const first_data, const size_t first_size, const void** const data_out, size_t* const data_size_out, unsigned char** const workspace_out)
84{
85 const char tensor_split_size_qs[] = "SELECT COUNT(*), SUM(length(data)) FROM tensor_splits WHERE name=$name";
86 sqlite3_stmt* tensor_split_size_stmt = 0;
87 int rc = sqlite3_prepare_v2(conn, tensor_split_size_qs, sizeof(tensor_split_size_qs), &tensor_split_size_stmt, 0);
88 if (rc != SQLITE_OK0)
89 return rc;
90 sqlite3_bind_text(tensor_split_size_stmt, 1, name, -1, SQLITE_STATIC((sqlite3_destructor_type)0));
91 rc = sqlite3_step(tensor_split_size_stmt);
92 if (rc != SQLITE_ROW100)
93 {
94 sqlite3_finalize(tensor_split_size_stmt);
95 return rc;
96 }
97 const sqlite_int64 split_count = sqlite3_column_int64(tensor_split_size_stmt, 0);
98 const sqlite_int64 tail_size = sqlite3_column_int64(tensor_split_size_stmt, 1);
99 sqlite3_finalize(tensor_split_size_stmt);
100 if (split_count <= 0 || tail_size < 0 || (size_t)tail_size > SIZE_MAX(18446744073709551615UL) - first_size)
101 return SQLITE_CORRUPT11;
102 const size_t total_size = first_size + (size_t)tail_size;
103 unsigned char* const workspace = (unsigned char*)ccmallocmalloc(total_size);
104 if (first_size > 0)
105 memcpy(workspace, first_data, first_size);
106 const char tensor_split_select_qs[] = "SELECT part, data FROM tensor_splits WHERE name=$name ORDER BY part";
107 sqlite3_stmt* tensor_split_select_stmt = 0;
108 rc = sqlite3_prepare_v2(conn, tensor_split_select_qs, sizeof(tensor_split_select_qs), &tensor_split_select_stmt, 0);
109 if (rc != SQLITE_OK0)
110 {
111 ccfreefree(workspace);
112 return rc;
113 }
114 sqlite3_bind_text(tensor_split_select_stmt, 1, name, -1, SQLITE_STATIC((sqlite3_destructor_type)0));
115 size_t offset = first_size;
116 int expected_part = 0;
117 while ((rc = sqlite3_step(tensor_split_select_stmt)) == SQLITE_ROW100)
118 {
119 if (sqlite3_column_int(tensor_split_select_stmt, 0) != expected_part++)
120 {
121 sqlite3_finalize(tensor_split_select_stmt);
122 ccfreefree(workspace);
123 return SQLITE_CORRUPT11;
124 }
125 const int split_size = sqlite3_column_bytes(tensor_split_select_stmt, 1);
126 if (split_size < 0 || (size_t)split_size > total_size - offset)
127 {
128 sqlite3_finalize(tensor_split_select_stmt);
129 ccfreefree(workspace);
130 return SQLITE_CORRUPT11;
131 }
132 const void* const split_data = sqlite3_column_blob(tensor_split_select_stmt, 1);
133 if (split_size > 0)
134 memcpy(workspace + offset, split_data, split_size);
135 offset += split_size;
136 }
137 sqlite3_finalize(tensor_split_select_stmt);
138 if (rc != SQLITE_DONE101 || offset != total_size)
139 {
140 ccfreefree(workspace);
141 return rc == SQLITE_DONE101 ? SQLITE_CORRUPT11 : rc;
142 }
143 *data_out = workspace;
144 *data_size_out = total_size;
145 *workspace_out = workspace;
146 return SQLITE_OK0;
147}
148
149// MARK - Level-1 API
150
151int ccv_nnc_tensor_write(const ccv_nnc_tensor_t* const tensor, void* const handle, const char* const name, const ccv_nnc_tensor_io_option_t* const options)
152{
153 assert(CCV_IS_TENSOR_CONTIGUOUS(tensor))((void) sizeof (((!((*(int*)(tensor)) & CCV_TENSOR_VIEW) ||
(((ccv_nnc_tensor_view_t*)tensor)->contiguous == 1))) ? 1
: 0), __extension__ ({ if ((!((*(int*)(tensor)) & CCV_TENSOR_VIEW
) || (((ccv_nnc_tensor_view_t*)tensor)->contiguous == 1)))
; else __assert_fail ("CCV_IS_TENSOR_CONTIGUOUS(tensor)", "ccv_nnc_tensor_io.c"
, 153, __extension__ __PRETTY_FUNCTION__); }))
;
154 assert(name)((void) sizeof ((name) ? 1 : 0), __extension__ ({ if (name) ;
else __assert_fail ("name", "ccv_nnc_tensor_io.c", 154, __extension__
__PRETTY_FUNCTION__); }))
;
155 sqlite3* conn = (sqlite3*)handle;
156 if (!conn)
157 return CCV_IO_ERROR;
158 const char tensor_create_table_qs[] = "CREATE TABLE IF NOT EXISTS tensors "
159 "(name TEXT, type INTEGER, format INTEGER, datatype INTEGER, "
160 "dim BLOB, data BLOB, PRIMARY KEY (name))";
161 SQLITE_ENFORCE(SQLITE_OK == sqlite3_exec(conn, tensor_create_table_qs, 0, 0, 0))((void) sizeof ((0 == sqlite3_exec(conn, tensor_create_table_qs
, 0, 0, 0)) ? 1 : 0), __extension__ ({ if (0 == sqlite3_exec(
conn, tensor_create_table_qs, 0, 0, 0)) ; else __assert_fail (
"SQLITE_OK == sqlite3_exec(conn, tensor_create_table_qs, 0, 0, 0)"
, "ccv_nnc_tensor_io.c", 161, __extension__ __PRETTY_FUNCTION__
); }))
;
162 const char tensor_insert_qs[] =
163 "REPLACE INTO tensors "
164 "(name, type, format, datatype, dim, data) VALUES ("
165 "$name, $type, $format, $datatype, $dim, $data)";
166 sqlite3_stmt* tensor_insert_stmt = 0;
167 SQLITE_ENFORCE(SQLITE_OK == sqlite3_prepare_v2(conn, tensor_insert_qs, sizeof(tensor_insert_qs), &tensor_insert_stmt, 0))((void) sizeof ((0 == sqlite3_prepare_v2(conn, tensor_insert_qs
, sizeof(tensor_insert_qs), &tensor_insert_stmt, 0)) ? 1 :
0), __extension__ ({ if (0 == sqlite3_prepare_v2(conn, tensor_insert_qs
, sizeof(tensor_insert_qs), &tensor_insert_stmt, 0)) ; else
__assert_fail ("SQLITE_OK == sqlite3_prepare_v2(conn, tensor_insert_qs, sizeof(tensor_insert_qs), &tensor_insert_stmt, 0)"
, "ccv_nnc_tensor_io.c", 167, __extension__ __PRETTY_FUNCTION__
); }))
;
168 sqlite3_bind_text(tensor_insert_stmt, 1, name, -1, 0);
169 ccv_nnc_tensor_param_t params = tensor->info;
170 const size_t data_size = ccv_nnc_tensor_data_size_without_padding(tensor->info);
171 unsigned char* workspace = 0;
172 const void* payload = tensor->data.u8;
173 size_t payload_size = data_size;
174 unsigned int identifier = 0;
175#ifdef HAVE_CUDA1
176 if (CCV_TENSOR_GET_MEMORY(tensor->info.type)((tensor->info.type) & 0x3) == CCV_TENSOR_GPU_MEMORY)
177 {
178 if (!options || !options->encode)
179 {
180 workspace = ccmallocmalloc(data_size);
181 cumemcpy(workspace, CCV_TENSOR_CPU_MEMORY, tensor->data.u8, tensor->info.type, data_size);
182 payload = workspace;
183 } else {
184 workspace = ccmallocmalloc(data_size * 2 + 4);
185 cumemcpy(workspace, CCV_TENSOR_CPU_MEMORY, tensor->data.u8, tensor->info.type, data_size);
186 size_t encoded_size = data_size + 4;
187 if (options->encode(workspace, data_size, tensor->info.datatype, tensor->info.dim, ccv_nnc_tensor_nd(tensor->info.dim), options->context, workspace + data_size, &encoded_size, &params, &identifier))
188 {
189 payload = workspace + data_size;
190 payload_size = encoded_size;
191 }
192 else
193 payload = workspace;
194 }
195 } else {
196 if (!options || !options->encode)
197 payload = tensor->data.u8;
198 else {
199 workspace = ccmallocmalloc(data_size + 4);
200 size_t encoded_size = data_size + 4;
201 if (options->encode(tensor->data.u8, data_size, tensor->info.datatype, tensor->info.dim, ccv_nnc_tensor_nd(tensor->info.dim), options->context, workspace, &encoded_size, &params, &identifier))
202 {
203 payload = workspace;
204 payload_size = encoded_size;
205 }
206 else
207 payload = tensor->data.u8;
208 }
209 }
210#elif defined(HAVE_MPS)
211 if (CCV_TENSOR_GET_MEMORY(tensor->info.type)((tensor->info.type) & 0x3) == CCV_TENSOR_GPU_MEMORY)
212 {
213 if (!options || !options->encode)
214 {
215 workspace = ccmallocmalloc(data_size);
216 mpmemcpy(workspace, 0, CCV_TENSOR_CPU_MEMORY, tensor->data.u8, tensor->dataof, tensor->info.type, data_size);
217 payload = workspace;
218 } else {
219 workspace = ccmallocmalloc(data_size * 2 + 4);
220 mpmemcpy(workspace, 0, CCV_TENSOR_CPU_MEMORY, tensor->data.u8, tensor->dataof, tensor->info.type, data_size);
221 size_t encoded_size = data_size + 4;
222 if (options->encode(workspace, data_size, tensor->info.datatype, tensor->info.dim, ccv_nnc_tensor_nd(tensor->info.dim), options->context, workspace + data_size, &encoded_size, &params, &identifier))
223 {
224 payload = workspace + data_size;
225 payload_size = encoded_size;
226 }
227 else
228 payload = workspace;
229 }
230 } else {
231 if (!options || !options->encode)
232 payload = tensor->data.u8;
233 else {
234 workspace = ccmallocmalloc(data_size + 4); // Allocate extra 4 bytes in case we need to copy the QX tensor out.
235 size_t encoded_size = data_size + 4;
236 if (options->encode(tensor->data.u8, data_size, tensor->info.datatype, tensor->info.dim, ccv_nnc_tensor_nd(tensor->info.dim), options->context, workspace, &encoded_size, &params, &identifier))
237 {
238 payload = workspace;
239 payload_size = encoded_size;
240 }
241 else
242 payload = tensor->data.u8;
243 }
244 }
245#else
246 if (!options || !options->encode)
247 payload = tensor->data.u8;
248 else {
249 workspace = ccmallocmalloc(data_size + 4);
250 size_t encoded_size = data_size + 4;
251 if (options->encode(tensor->data.u8, data_size, tensor->info.datatype, tensor->info.dim, ccv_nnc_tensor_nd(tensor->info.dim), options->context, workspace, &encoded_size, &params, &identifier))
252 {
253 payload = workspace;
254 payload_size = encoded_size;
255 }
256 else
257 payload = tensor->data.u8;
258 }
259#endif
260 int result = SQLITE_TOOBIG18;
261 int bind_result = payload_size <= INT_MAX2147483647 ? sqlite3_bind_blob(tensor_insert_stmt, 6, payload, (int)payload_size, 0) : SQLITE_TOOBIG18;
262 if (bind_result == SQLITE_OK0)
263 {
264 sqlite3_bind_int64(tensor_insert_stmt, 2, ((sqlite_int64)identifier << 32) | params.type);
265 sqlite3_bind_int(tensor_insert_stmt, 3, params.format);
266 sqlite3_bind_int64(tensor_insert_stmt, 4, ((sqlite_int64)params.reserved << 32) | params.datatype);
267 sqlite3_bind_blob(tensor_insert_stmt, 5, params.dim, sizeof(params.dim), 0);
268 result = sqlite3_step(tensor_insert_stmt);
269 if (result == SQLITE_DONE101)
270 {
271 sqlite3_reset(tensor_insert_stmt);
272 sqlite3_clear_bindings(tensor_insert_stmt);
273 sqlite3_finalize(tensor_insert_stmt);
274 if (workspace)
275 free(workspace);
276 return CCV_IO_FINAL;
277 }
278 sqlite3_reset(tensor_insert_stmt);
279 sqlite3_clear_bindings(tensor_insert_stmt);
280 if (result != SQLITE_TOOBIG18)
281 {
282 sqlite3_finalize(tensor_insert_stmt);
283 if (workspace)
284 free(workspace);
285 return CCV_IO_ERROR;
286 }
287 } else {
288 sqlite3_reset(tensor_insert_stmt);
289 sqlite3_clear_bindings(tensor_insert_stmt);
290 if (bind_result != SQLITE_TOOBIG18)
291 {
292 sqlite3_finalize(tensor_insert_stmt);
293 if (workspace)
294 free(workspace);
295 return CCV_IO_ERROR;
296 }
297 }
298 if (sqlite3_exec(conn, "SAVEPOINT ccv_nnc_tensor_write", 0, 0, 0) != SQLITE_OK0)
299 {
300 sqlite3_finalize(tensor_insert_stmt);
301 if (workspace)
302 free(workspace);
303 return CCV_IO_ERROR;
304 }
305 const char tensor_split_create_table_qs[] = "CREATE TABLE IF NOT EXISTS tensor_splits "
306 "(name TEXT, part INTEGER, data BLOB, PRIMARY KEY (name, part))";
307 if (sqlite3_exec(conn, tensor_split_create_table_qs, 0, 0, 0) != SQLITE_OK0)
308 {
309 sqlite3_finalize(tensor_insert_stmt);
310 sqlite3_exec(conn, "ROLLBACK TO ccv_nnc_tensor_write", 0, 0, 0);
311 sqlite3_exec(conn, "RELEASE ccv_nnc_tensor_write", 0, 0, 0);
312 if (workspace)
313 free(workspace);
314 return CCV_IO_ERROR;
315 }
316 sqlite3_bind_text(tensor_insert_stmt, 1, name, -1, 0);
317 const int chunk_size = _ccv_nnc_tensor_io_blob_chunk_size(conn);
318 assert(chunk_size > 0)((void) sizeof ((chunk_size > 0) ? 1 : 0), __extension__ (
{ if (chunk_size > 0) ; else __assert_fail ("chunk_size > 0"
, "ccv_nnc_tensor_io.c", 318, __extension__ __PRETTY_FUNCTION__
); }))
;
319 const size_t first_size = ccv_min(payload_size, (size_t)chunk_size)({ typeof (payload_size) _a = (payload_size); typeof ((size_t
)chunk_size) _b = ((size_t)chunk_size); (_a < _b) ? _a : _b
; })
;
320 bind_result = first_size < payload_size ? sqlite3_bind_blob(tensor_insert_stmt, 6, payload, (int)first_size, SQLITE_STATIC((sqlite3_destructor_type)0)) : SQLITE_TOOBIG18;
321 if (bind_result == SQLITE_OK0)
322 bind_result = _ccv_nnc_tensor_io_delete_splits(conn, name);
323 if (bind_result == SQLITE_OK0)
324 bind_result = _ccv_nnc_tensor_io_write_splits(conn, name, (const unsigned char*)payload, payload_size, first_size, chunk_size);
325 if (bind_result != SQLITE_OK0)
326 {
327 sqlite3_finalize(tensor_insert_stmt);
328 sqlite3_exec(conn, "ROLLBACK TO ccv_nnc_tensor_write", 0, 0, 0);
329 sqlite3_exec(conn, "RELEASE ccv_nnc_tensor_write", 0, 0, 0);
330 if (workspace)
331 free(workspace);
332 return CCV_IO_ERROR;
333 }
334 sqlite3_bind_int64(tensor_insert_stmt, 2, ((sqlite_int64)identifier << 32) | params.type);
335 sqlite3_bind_int64(tensor_insert_stmt, 3, ((sqlite_int64)params.format & CCV_NNC_TENSOR_IO_FORMAT_MASK0xffffffffll) | CCV_NNC_TENSOR_IO_SPLIT_FORMAT(((sqlite_int64)1) << 32));
336 sqlite3_bind_int64(tensor_insert_stmt, 4, ((sqlite_int64)params.reserved << 32) | params.datatype);
337 sqlite3_bind_blob(tensor_insert_stmt, 5, params.dim, sizeof(params.dim), 0);
338 result = sqlite3_step(tensor_insert_stmt);
339 sqlite3_reset(tensor_insert_stmt);
340 sqlite3_clear_bindings(tensor_insert_stmt);
341 sqlite3_finalize(tensor_insert_stmt);
342 if (result == SQLITE_DONE101)
343 {
344 if (sqlite3_exec(conn, "RELEASE ccv_nnc_tensor_write", 0, 0, 0) != SQLITE_OK0)
345 {
346 if (workspace)
347 free(workspace);
348 return CCV_IO_ERROR;
349 }
350 } else {
351 sqlite3_exec(conn, "ROLLBACK TO ccv_nnc_tensor_write", 0, 0, 0);
352 sqlite3_exec(conn, "RELEASE ccv_nnc_tensor_write", 0, 0, 0);
353 }
354 if (workspace)
355 free(workspace);
356 return result == SQLITE_DONE101 ? CCV_IO_FINAL : CCV_IO_ERROR;
357}
358
359int ccv_nnc_tensor_read(void* const handle, const char* const name, const ccv_nnc_tensor_io_option_t* const options, const int flags, const ccv_nnc_tensor_param_t* const tensor_params_optional, ccv_nnc_tensor_t** const tensor_out)
360{
361 assert(name)((void) sizeof ((name) ? 1 : 0), __extension__ ({ if (name) ;
else __assert_fail ("name", "ccv_nnc_tensor_io.c", 361, __extension__
__PRETTY_FUNCTION__); }))
;
362 sqlite3* conn = (sqlite3*)handle;
363 if (!conn)
364 return CCV_IO_ERROR;
365 const char tensor_select_qs[] =
366 "SELECT data, type, format, datatype, dim FROM tensors WHERE name=$name";
367 sqlite3_stmt* tensor_select_stmt = 0;
368 if (SQLITE_OK0 != sqlite3_prepare_v2(conn, tensor_select_qs, sizeof(tensor_select_qs), &tensor_select_stmt, 0))
369 return CCV_IO_ERROR;
370 sqlite3_bind_text(tensor_select_stmt, 1, name, -1, 0);
371 if (SQLITE_ROW100 != sqlite3_step(tensor_select_stmt))
372 {
373 sqlite3_finalize(tensor_select_stmt);
374 return CCV_IO_ERROR;
375 }
376 ccv_nnc_tensor_t* tensor = *tensor_out;
377 ccv_nnc_tensor_param_t tensor_params;
378 int datatype = 0;
379 unsigned int identifier = 0;
380 const sqlite_int64 format_mix = sqlite3_column_int64(tensor_select_stmt, 2);
381 const int has_splits = !!(format_mix & CCV_NNC_TENSOR_IO_SPLIT_FORMAT(((sqlite_int64)1) << 32));
382 if (!tensor) // If the tensor is not provided, we need to create one.
383 {
384 if (tensor_params_optional)
385 {
386 identifier = (sqlite3_column_int64(tensor_select_stmt, 1) >> 32) & 0xffffffff;
387 datatype = sqlite3_column_int64(tensor_select_stmt, 3) & 0xffffffff;
388 tensor_params = *tensor_params_optional;
389 assert(!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY))((void) sizeof ((!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY
)) ? 1 : 0), __extension__ ({ if (!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY
)) ; else __assert_fail ("!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY)"
, "ccv_nnc_tensor_io.c", 389, __extension__ __PRETTY_FUNCTION__
); }))
;
390 } else {
391 const sqlite_int64 type = sqlite3_column_int64(tensor_select_stmt, 1);
392 identifier = (type >> 32) & 0xffffffff;
393 tensor_params.type = (type & 0xffffffff);
394 tensor_params.format = (int)(format_mix & CCV_NNC_TENSOR_IO_FORMAT_MASK0xffffffffll);
395 const sqlite_int64 datatype_mix = sqlite3_column_int64(tensor_select_stmt, 3);
396 datatype = tensor_params.datatype = (datatype_mix & 0xffffffff);
397 tensor_params.reserved = (datatype_mix >> 32) & 0xffffffff;
398 const void* const dim = sqlite3_column_blob(tensor_select_stmt, 4);
399 memcpy(tensor_params.dim, dim, ccv_min(sizeof(tensor_params.dim), sqlite3_column_bytes(tensor_select_stmt, 4))({ typeof (sizeof(tensor_params.dim)) _a = (sizeof(tensor_params
.dim)); typeof (sqlite3_column_bytes(tensor_select_stmt, 4)) _b
= (sqlite3_column_bytes(tensor_select_stmt, 4)); (_a < _b
) ? _a : _b; })
);
400 }
401 if (flags & CCV_NNC_TENSOR_READ_CPU_MEMORY) // Reset type to CPU memory.
402 tensor_params.type = (tensor_params.type & 0xfff00000) | CCV_TENSOR_CPU_MEMORY;
403 if (!options || !options->decode)
404 {
405 if (flags & CCV_NNC_TENSOR_READ_METADATA_ONLY)
406 {
407 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, CCV_NO_DATA_ALLOC); // Set the data point to 1 so it is allocated without data.
408 assert(tensor->data.u8 == 0)((void) sizeof ((tensor->data.u8 == 0) ? 1 : 0), __extension__
({ if (tensor->data.u8 == 0) ; else __assert_fail ("tensor->data.u8 == 0"
, "ccv_nnc_tensor_io.c", 408, __extension__ __PRETTY_FUNCTION__
); }))
; // Set it back to 0.
409 // Already done loading metadata, return.
410 sqlite3_reset(tensor_select_stmt);
411 sqlite3_clear_bindings(tensor_select_stmt);
412 sqlite3_finalize(tensor_select_stmt);
413 return CCV_IO_FINAL;
414 } else
415 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
416 } else {
417 assert(!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY))((void) sizeof ((!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY
)) ? 1 : 0), __extension__ ({ if (!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY
)) ; else __assert_fail ("!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY)"
, "ccv_nnc_tensor_io.c", 417, __extension__ __PRETTY_FUNCTION__
); }))
;
418 }
419 } else {
420 identifier = (sqlite3_column_int64(tensor_select_stmt, 1) >> 32) & 0xffffffff;
421 datatype = sqlite3_column_int64(tensor_select_stmt, 3) & 0xffffffff;
422 tensor_params = tensor->info;
423 assert(!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY))((void) sizeof ((!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY
)) ? 1 : 0), __extension__ ({ if (!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY
)) ; else __assert_fail ("!(flags & CCV_NNC_TENSOR_READ_METADATA_ONLY)"
, "ccv_nnc_tensor_io.c", 423, __extension__ __PRETTY_FUNCTION__
); }))
;
424 }
425 const void* data = sqlite3_column_blob(tensor_select_stmt, 0);
426 size_t data_bytes = sqlite3_column_bytes(tensor_select_stmt, 0);
427 unsigned char* split_workspace = 0;
428 if (has_splits)
429 {
430 const int split_result = _ccv_nnc_tensor_io_read_split_data(conn, name, data, data_bytes, &data, &data_bytes, &split_workspace);
431 if (split_result != SQLITE_OK0)
432 {
433 sqlite3_reset(tensor_select_stmt);
434 sqlite3_clear_bindings(tensor_select_stmt);
435 sqlite3_finalize(tensor_select_stmt);
436 return CCV_IO_ERROR;
437 }
438 }
439 int dim[CCV_NNC_MAX_DIM_ALLOC(12)];
440 memcpy(dim, sqlite3_column_blob(tensor_select_stmt, 4), ccv_min(sizeof(dim), sqlite3_column_bytes(tensor_select_stmt, 4))({ typeof (sizeof(dim)) _a = (sizeof(dim)); typeof (sqlite3_column_bytes
(tensor_select_stmt, 4)) _b = (sqlite3_column_bytes(tensor_select_stmt
, 4)); (_a < _b) ? _a : _b; })
);
441 const int nd = ccv_nnc_tensor_nd(dim);
442 if (datatype != tensor_params.datatype && CCV_GET_DATA_TYPE(tensor_params.datatype)((tensor_params.datatype) & 0xFF000) != CCV_QX)
443 {
444 // Only ever works for 16F to 32F or 32F to 16F transparently.
445 assert((datatype == CCV_16F && tensor_params.datatype == CCV_32F) || (datatype == CCV_32F && tensor_params.datatype == CCV_16F))((void) sizeof (((datatype == CCV_16F && tensor_params
.datatype == CCV_32F) || (datatype == CCV_32F && tensor_params
.datatype == CCV_16F)) ? 1 : 0), __extension__ ({ if ((datatype
== CCV_16F && tensor_params.datatype == CCV_32F) || (
datatype == CCV_32F && tensor_params.datatype == CCV_16F
)) ; else __assert_fail ("(datatype == CCV_16F && tensor_params.datatype == CCV_32F) || (datatype == CCV_32F && tensor_params.datatype == CCV_16F)"
, "ccv_nnc_tensor_io.c", 445, __extension__ __PRETTY_FUNCTION__
); }))
;
446 const size_t tensor_count = ccv_nnc_tensor_count(tensor_params);
447 ccv_nnc_tensor_param_t params = tensor_params;
448 params.datatype = datatype;
449 const size_t source_data_size = ccv_nnc_tensor_data_size(params);
450#ifdef HAVE_CUDA1
451 if (CCV_TENSOR_GET_MEMORY(tensor_params.type)((tensor_params.type) & 0x3) == CCV_TENSOR_GPU_MEMORY)
452 {
453 const size_t data_size = ccv_nnc_tensor_data_size(tensor_params);
454 unsigned char* workspace;
455 unsigned char* copying;
456 size_t decoded_size = data_size;
457 if (!options || !options->decode)
458 {
459 copying = workspace = ccmallocmalloc(data_size);
460 if (datatype == CCV_16F && tensor_params.datatype == CCV_32F)
461 ccv_half_precision_to_float((uint16_t*)data, (float*)workspace, ccv_min(tensor_count, data_bytes / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(uint16_t)) _b = (data_bytes / sizeof(uint16_t)); (_a
< _b) ? _a : _b; })
);
462 else if (datatype == CCV_32F && tensor_params.datatype == CCV_16F)
463 ccv_float_to_half_precision((float*)data, (uint16_t*)workspace, ccv_min(tensor_count, data_bytes / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(float)) _b = (data_bytes / sizeof(float)); (_a <
_b) ? _a : _b; })
);
464 else
465 { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_tensor_io.c", 465, __extension__ __PRETTY_FUNCTION__
); }))
; }
466 } else {
467 copying = workspace = ccmallocmalloc(data_size + source_data_size);
468 if (datatype == CCV_16F && tensor_params.datatype == CCV_32F)
469 {
470 decoded_size = source_data_size;
471 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace + data_size, &decoded_size))
472 {
473 // If we loaded quantized tensor, don't do the conversion.
474 if (CCV_GET_DATA_TYPE(tensor_out[0]->info.datatype)((tensor_out[0]->info.datatype) & 0xFF000) == CCV_QX)
475 copying = workspace + data_size;
476 else {
477 ccv_half_precision_to_float((uint16_t*)(workspace + data_size), (float*)workspace, ccv_min(tensor_count, ccv_min(source_data_size, decoded_size) / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (({ typeof
(source_data_size) _a = (source_data_size); typeof (decoded_size
) _b = (decoded_size); (_a < _b) ? _a : _b; }) / sizeof(uint16_t
)) _b = (({ typeof (source_data_size) _a = (source_data_size)
; typeof (decoded_size) _b = (decoded_size); (_a < _b) ? _a
: _b; }) / sizeof(uint16_t)); (_a < _b) ? _a : _b; })
);
478 decoded_size = data_size;
479 }
480 } else {
481 if (!tensor)
482 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
Although the value stored to 'tensor' is used in the enclosing expression, the value is never actually read from 'tensor'
483 ccv_half_precision_to_float((uint16_t*)data, (float*)workspace, ccv_min(tensor_count, data_bytes / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(uint16_t)) _b = (data_bytes / sizeof(uint16_t)); (_a
< _b) ? _a : _b; })
);
484 decoded_size = data_size;
485 }
486 } else if (datatype == CCV_32F && tensor_params.datatype == CCV_16F) {
487 decoded_size = source_data_size;
488 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace + data_size, &decoded_size))
489 {
490 if (CCV_GET_DATA_TYPE(tensor_out[0]->info.datatype)((tensor_out[0]->info.datatype) & 0xFF000) == CCV_QX)
491 copying = workspace + data_size;
492 else {
493 ccv_float_to_half_precision((float*)(workspace + data_size), (uint16_t*)workspace, ccv_min(tensor_count, ccv_min(source_data_size, decoded_size) / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (({ typeof
(source_data_size) _a = (source_data_size); typeof (decoded_size
) _b = (decoded_size); (_a < _b) ? _a : _b; }) / sizeof(float
)) _b = (({ typeof (source_data_size) _a = (source_data_size)
; typeof (decoded_size) _b = (decoded_size); (_a < _b) ? _a
: _b; }) / sizeof(float)); (_a < _b) ? _a : _b; })
);
494 decoded_size = data_size;
495 }
496 } else {
497 if (!tensor)
498 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
499 ccv_float_to_half_precision((float*)data, (uint16_t*)workspace, ccv_min(tensor_count, data_bytes / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(float)) _b = (data_bytes / sizeof(float)); (_a <
_b) ? _a : _b; })
);
500 decoded_size = data_size;
501 }
502 } else
503 { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_tensor_io.c", 503, __extension__ __PRETTY_FUNCTION__
); }))
; }
504 }
505 cumemcpy(tensor_out[0]->data.u8, tensor_out[0]->info.type, copying, CCV_TENSOR_CPU_MEMORY, decoded_size);
506 ccfreefree(workspace);
507 } else {
508 if (!options || !options->decode)
509 {
510 if (datatype == CCV_16F && tensor_params.datatype == CCV_32F)
511 ccv_half_precision_to_float((uint16_t*)data, tensor->data.f32, ccv_min(tensor_count, data_bytes / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(uint16_t)) _b = (data_bytes / sizeof(uint16_t)); (_a
< _b) ? _a : _b; })
);
512 else if (datatype == CCV_32F && tensor_params.datatype == CCV_16F)
513 ccv_float_to_half_precision((float*)data, (uint16_t*)tensor->data.f16, ccv_min(tensor_count, data_bytes / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(float)) _b = (data_bytes / sizeof(float)); (_a <
_b) ? _a : _b; })
);
514 else
515 { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_tensor_io.c", 515, __extension__ __PRETTY_FUNCTION__
); }))
; }
516 } else {
517 void* const workspace = ccmallocmalloc(source_data_size);
518 if (datatype == CCV_16F && tensor_params.datatype == CCV_32F)
519 {
520 size_t decoded_size = source_data_size;
521 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace, &decoded_size))
522 {
523 if (CCV_GET_DATA_TYPE(tensor_out[0]->info.datatype)((tensor_out[0]->info.datatype) & 0xFF000) == CCV_QX)
524 {
525 if (decoded_size > 0)
526 memcpy(tensor_out[0]->data.f32, workspace, ccv_min(source_data_size, decoded_size)({ typeof (source_data_size) _a = (source_data_size); typeof (
decoded_size) _b = (decoded_size); (_a < _b) ? _a : _b; })
);
527 } else
528 ccv_half_precision_to_float((uint16_t*)workspace, tensor_out[0]->data.f32, ccv_min(tensor_count, ccv_min(source_data_size, decoded_size) / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (({ typeof
(source_data_size) _a = (source_data_size); typeof (decoded_size
) _b = (decoded_size); (_a < _b) ? _a : _b; }) / sizeof(uint16_t
)) _b = (({ typeof (source_data_size) _a = (source_data_size)
; typeof (decoded_size) _b = (decoded_size); (_a < _b) ? _a
: _b; }) / sizeof(uint16_t)); (_a < _b) ? _a : _b; })
);
529 } else {
530 if (!tensor)
531 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
532 ccv_half_precision_to_float((uint16_t*)data, tensor->data.f32, ccv_min(tensor_count, data_bytes / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(uint16_t)) _b = (data_bytes / sizeof(uint16_t)); (_a
< _b) ? _a : _b; })
);
533 }
534 } else if (datatype == CCV_32F && tensor_params.datatype == CCV_16F) {
535 size_t decoded_size = source_data_size;
536 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace, &decoded_size))
537 {
538 if (CCV_GET_DATA_TYPE(tensor_out[0]->info.datatype)((tensor_out[0]->info.datatype) & 0xFF000) == CCV_QX)
539 {
540 if (decoded_size > 0)
541 memcpy(tensor_out[0]->data.f16, workspace, ccv_min(source_data_size, decoded_size)({ typeof (source_data_size) _a = (source_data_size); typeof (
decoded_size) _b = (decoded_size); (_a < _b) ? _a : _b; })
);
542 } else
543 ccv_float_to_half_precision((float*)workspace, (uint16_t*)tensor_out[0]->data.f16, ccv_min(tensor_count, ccv_min(source_data_size, decoded_size) / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (({ typeof
(source_data_size) _a = (source_data_size); typeof (decoded_size
) _b = (decoded_size); (_a < _b) ? _a : _b; }) / sizeof(float
)) _b = (({ typeof (source_data_size) _a = (source_data_size)
; typeof (decoded_size) _b = (decoded_size); (_a < _b) ? _a
: _b; }) / sizeof(float)); (_a < _b) ? _a : _b; })
);
544 } else {
545 if (!tensor)
546 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
547 ccv_float_to_half_precision((float*)data, (uint16_t*)tensor->data.f16, ccv_min(tensor_count, data_bytes / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(float)) _b = (data_bytes / sizeof(float)); (_a <
_b) ? _a : _b; })
);
548 }
549 } else
550 { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_tensor_io.c", 550, __extension__ __PRETTY_FUNCTION__
); }))
; }
551 ccfreefree(workspace);
552 }
553 }
554#elif defined(HAVE_MPS)
555 if (CCV_TENSOR_GET_MEMORY(tensor_params.type)((tensor_params.type) & 0x3) == CCV_TENSOR_GPU_MEMORY)
556 {
557 const size_t data_size = ccv_nnc_tensor_data_size(tensor_params);
558 unsigned char* workspace;
559 unsigned char* copying;
560 size_t decoded_size = data_size;
561 if (!options || !options->decode)
562 {
563 copying = workspace = ccmallocmalloc(data_size);
564 if (datatype == CCV_16F && tensor_params.datatype == CCV_32F)
565 ccv_half_precision_to_float((uint16_t*)data, (float*)workspace, ccv_min(tensor_count, data_bytes / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(uint16_t)) _b = (data_bytes / sizeof(uint16_t)); (_a
< _b) ? _a : _b; })
);
566 else if (datatype == CCV_32F && tensor_params.datatype == CCV_16F)
567 ccv_float_to_half_precision((float*)data, (uint16_t*)workspace, ccv_min(tensor_count, data_bytes / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(float)) _b = (data_bytes / sizeof(float)); (_a <
_b) ? _a : _b; })
);
568 else
569 { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_tensor_io.c", 569, __extension__ __PRETTY_FUNCTION__
); }))
; }
570 } else {
571 copying = workspace = ccmallocmalloc(data_size + source_data_size);
572 if (datatype == CCV_16F && tensor_params.datatype == CCV_32F)
573 {
574 decoded_size = source_data_size;
575 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace + data_size, &decoded_size))
576 {
577 if (CCV_GET_DATA_TYPE(tensor_out[0]->info.datatype)((tensor_out[0]->info.datatype) & 0xFF000) == CCV_QX)
578 copying = workspace + data_size;
579 else {
580 ccv_half_precision_to_float((uint16_t*)(workspace + data_size), (float*)workspace, ccv_min(tensor_count, ccv_min(source_data_size, decoded_size) / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (({ typeof
(source_data_size) _a = (source_data_size); typeof (decoded_size
) _b = (decoded_size); (_a < _b) ? _a : _b; }) / sizeof(uint16_t
)) _b = (({ typeof (source_data_size) _a = (source_data_size)
; typeof (decoded_size) _b = (decoded_size); (_a < _b) ? _a
: _b; }) / sizeof(uint16_t)); (_a < _b) ? _a : _b; })
);
581 decoded_size = data_size;
582 }
583 } else {
584 if (!tensor)
585 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
586 ccv_half_precision_to_float((uint16_t*)data, (float*)workspace, ccv_min(tensor_count, data_bytes / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(uint16_t)) _b = (data_bytes / sizeof(uint16_t)); (_a
< _b) ? _a : _b; })
);
587 decoded_size = data_size;
588 }
589 } else if (datatype == CCV_32F && tensor_params.datatype == CCV_16F) {
590 decoded_size = source_data_size;
591 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace + data_size, &decoded_size))
592 {
593 if (CCV_GET_DATA_TYPE(tensor_out[0]->info.datatype)((tensor_out[0]->info.datatype) & 0xFF000) == CCV_QX)
594 copying = workspace + data_size;
595 else {
596 ccv_float_to_half_precision((float*)(workspace + data_size), (uint16_t*)workspace, ccv_min(tensor_count, ccv_min(source_data_size, decoded_size) / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (({ typeof
(source_data_size) _a = (source_data_size); typeof (decoded_size
) _b = (decoded_size); (_a < _b) ? _a : _b; }) / sizeof(float
)) _b = (({ typeof (source_data_size) _a = (source_data_size)
; typeof (decoded_size) _b = (decoded_size); (_a < _b) ? _a
: _b; }) / sizeof(float)); (_a < _b) ? _a : _b; })
);
597 decoded_size = data_size;
598 }
599 } else {
600 if (!tensor)
601 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
602 ccv_float_to_half_precision((float*)data, (uint16_t*)workspace, ccv_min(tensor_count, data_bytes / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(float)) _b = (data_bytes / sizeof(float)); (_a <
_b) ? _a : _b; })
);
603 decoded_size = data_size;
604 }
605 } else
606 { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_tensor_io.c", 606, __extension__ __PRETTY_FUNCTION__
); }))
; }
607 }
608 assert(tensor_out[0]->dataof == 0)((void) sizeof ((tensor_out[0]->dataof == 0) ? 1 : 0), __extension__
({ if (tensor_out[0]->dataof == 0) ; else __assert_fail (
"tensor_out[0]->dataof == 0", "ccv_nnc_tensor_io.c", 608, __extension__
__PRETTY_FUNCTION__); }))
;
609 mpmemcpy(tensor_out[0]->data.u8, tensor_out[0]->dataof, tensor_out[0]->info.type, copying, 0, CCV_TENSOR_CPU_MEMORY, decoded_size);
610 ccfreefree(workspace);
611 } else {
612 if (!options || !options->decode)
613 {
614 if (datatype == CCV_16F && tensor_params.datatype == CCV_32F)
615 ccv_half_precision_to_float((uint16_t*)data, tensor->data.f32, ccv_min(tensor_count, data_bytes / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(uint16_t)) _b = (data_bytes / sizeof(uint16_t)); (_a
< _b) ? _a : _b; })
);
616 else if (datatype == CCV_32F && tensor_params.datatype == CCV_16F)
617 ccv_float_to_half_precision((float*)data, (uint16_t*)tensor->data.f16, ccv_min(tensor_count, data_bytes / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(float)) _b = (data_bytes / sizeof(float)); (_a <
_b) ? _a : _b; })
);
618 else
619 { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_tensor_io.c", 619, __extension__ __PRETTY_FUNCTION__
); }))
; }
620 } else {
621 void* const workspace = ccmallocmalloc(source_data_size);
622 if (datatype == CCV_16F && tensor_params.datatype == CCV_32F)
623 {
624 size_t decoded_size = source_data_size;
625 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace, &decoded_size))
626 {
627 if (CCV_GET_DATA_TYPE(tensor_out[0]->info.datatype)((tensor_out[0]->info.datatype) & 0xFF000) == CCV_QX)
628 {
629 if (decoded_size > 0)
630 memcpy(tensor_out[0]->data.f32, workspace, ccv_min(source_data_size, decoded_size)({ typeof (source_data_size) _a = (source_data_size); typeof (
decoded_size) _b = (decoded_size); (_a < _b) ? _a : _b; })
);
631 } else
632 ccv_half_precision_to_float((uint16_t*)workspace, tensor_out[0]->data.f32, ccv_min(tensor_count, ccv_min(source_data_size, decoded_size) / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (({ typeof
(source_data_size) _a = (source_data_size); typeof (decoded_size
) _b = (decoded_size); (_a < _b) ? _a : _b; }) / sizeof(uint16_t
)) _b = (({ typeof (source_data_size) _a = (source_data_size)
; typeof (decoded_size) _b = (decoded_size); (_a < _b) ? _a
: _b; }) / sizeof(uint16_t)); (_a < _b) ? _a : _b; })
);
633 } else {
634 if (!tensor)
635 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
636 ccv_half_precision_to_float((uint16_t*)data, tensor->data.f32, ccv_min(tensor_count, data_bytes / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(uint16_t)) _b = (data_bytes / sizeof(uint16_t)); (_a
< _b) ? _a : _b; })
);
637 }
638 } else if (datatype == CCV_32F && tensor_params.datatype == CCV_16F) {
639 size_t decoded_size = source_data_size;
640 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace, &decoded_size))
641 {
642 if (CCV_GET_DATA_TYPE(tensor_out[0]->info.datatype)((tensor_out[0]->info.datatype) & 0xFF000) == CCV_QX)
643 {
644 if (decoded_size > 0)
645 memcpy(tensor_out[0]->data.f16, workspace, ccv_min(source_data_size, decoded_size)({ typeof (source_data_size) _a = (source_data_size); typeof (
decoded_size) _b = (decoded_size); (_a < _b) ? _a : _b; })
);
646 } else
647 ccv_float_to_half_precision((float*)workspace, (uint16_t*)tensor_out[0]->data.f16, ccv_min(tensor_count, ccv_min(source_data_size, decoded_size) / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (({ typeof
(source_data_size) _a = (source_data_size); typeof (decoded_size
) _b = (decoded_size); (_a < _b) ? _a : _b; }) / sizeof(float
)) _b = (({ typeof (source_data_size) _a = (source_data_size)
; typeof (decoded_size) _b = (decoded_size); (_a < _b) ? _a
: _b; }) / sizeof(float)); (_a < _b) ? _a : _b; })
);
648 } else {
649 if (!tensor)
650 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
651 ccv_float_to_half_precision((float*)data, (uint16_t*)tensor->data.f16, ccv_min(tensor_count, data_bytes / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(float)) _b = (data_bytes / sizeof(float)); (_a <
_b) ? _a : _b; })
);
652 }
653 } else
654 { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_tensor_io.c", 654, __extension__ __PRETTY_FUNCTION__
); }))
; }
655 ccfreefree(workspace);
656 }
657 }
658#else
659 if (!options || !options->decode)
660 {
661 if (datatype == CCV_16F && tensor_params.datatype == CCV_32F)
662 ccv_half_precision_to_float((uint16_t*)data, tensor->data.f32, ccv_min(tensor_count, data_bytes / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(uint16_t)) _b = (data_bytes / sizeof(uint16_t)); (_a
< _b) ? _a : _b; })
);
663 else if (datatype == CCV_32F && tensor_params.datatype == CCV_16F)
664 ccv_float_to_half_precision((float*)data, (uint16_t*)tensor->data.f16, ccv_min(tensor_count, data_bytes / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(float)) _b = (data_bytes / sizeof(float)); (_a <
_b) ? _a : _b; })
);
665 else
666 { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_tensor_io.c", 666, __extension__ __PRETTY_FUNCTION__
); }))
; }
667 } else {
668 void* const workspace = ccmallocmalloc(source_data_size);
669 if (datatype == CCV_16F && tensor_params.datatype == CCV_32F)
670 {
671 size_t decoded_size = source_data_size;
672 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace, &decoded_size))
673 {
674 if (CCV_GET_DATA_TYPE(tensor_out[0]->info.datatype)((tensor_out[0]->info.datatype) & 0xFF000) == CCV_QX)
675 {
676 if (decoded_size > 0)
677 memcpy(tensor_out[0]->data.f32, workspace, ccv_min(source_data_size, decoded_size)({ typeof (source_data_size) _a = (source_data_size); typeof (
decoded_size) _b = (decoded_size); (_a < _b) ? _a : _b; })
);
678 } else
679 ccv_half_precision_to_float((uint16_t*)workspace, tensor_out[0]->data.f32, ccv_min(tensor_count, ccv_min(source_data_size, decoded_size) / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (({ typeof
(source_data_size) _a = (source_data_size); typeof (decoded_size
) _b = (decoded_size); (_a < _b) ? _a : _b; }) / sizeof(uint16_t
)) _b = (({ typeof (source_data_size) _a = (source_data_size)
; typeof (decoded_size) _b = (decoded_size); (_a < _b) ? _a
: _b; }) / sizeof(uint16_t)); (_a < _b) ? _a : _b; })
);
680 } else {
681 if (!tensor)
682 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
683 ccv_half_precision_to_float((uint16_t*)data, tensor->data.f32, ccv_min(tensor_count, data_bytes / sizeof(uint16_t))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(uint16_t)) _b = (data_bytes / sizeof(uint16_t)); (_a
< _b) ? _a : _b; })
);
684 }
685 } else if (datatype == CCV_32F && tensor_params.datatype == CCV_16F) {
686 size_t decoded_size = source_data_size;
687 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace, &decoded_size))
688 {
689 if (CCV_GET_DATA_TYPE(tensor_out[0]->info.datatype)((tensor_out[0]->info.datatype) & 0xFF000) == CCV_QX)
690 {
691 if (decoded_size > 0)
692 memcpy(tensor_out[0]->data.f16, workspace, ccv_min(source_data_size, decoded_size)({ typeof (source_data_size) _a = (source_data_size); typeof (
decoded_size) _b = (decoded_size); (_a < _b) ? _a : _b; })
);
693 } else
694 ccv_float_to_half_precision((float*)workspace, (uint16_t*)tensor_out[0]->data.f16, ccv_min(tensor_count, ccv_min(source_data_size, decoded_size) / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (({ typeof
(source_data_size) _a = (source_data_size); typeof (decoded_size
) _b = (decoded_size); (_a < _b) ? _a : _b; }) / sizeof(float
)) _b = (({ typeof (source_data_size) _a = (source_data_size)
; typeof (decoded_size) _b = (decoded_size); (_a < _b) ? _a
: _b; }) / sizeof(float)); (_a < _b) ? _a : _b; })
);
695 } else {
696 if (!tensor)
697 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
698 ccv_float_to_half_precision((float*)data, (uint16_t*)tensor->data.f16, ccv_min(tensor_count, data_bytes / sizeof(float))({ typeof (tensor_count) _a = (tensor_count); typeof (data_bytes
/ sizeof(float)) _b = (data_bytes / sizeof(float)); (_a <
_b) ? _a : _b; })
);
699 }
700 } else
701 { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_tensor_io.c", 701, __extension__ __PRETTY_FUNCTION__
); }))
; }
702 ccfreefree(workspace);
703 }
704#endif
705 } else {
706 // If it is QX, we need to have a custom decoder to decode properly.
707 if (datatype != tensor_params.datatype)
708 { assert(options && options->decode)((void) sizeof ((options && options->decode) ? 1 :
0), __extension__ ({ if (options && options->decode
) ; else __assert_fail ("options && options->decode"
, "ccv_nnc_tensor_io.c", 708, __extension__ __PRETTY_FUNCTION__
); }))
; }
709 size_t data_size = ccv_nnc_tensor_data_size(tensor_params);
710#ifdef HAVE_CUDA1
711 if (!options || !options->decode)
712 {
713 if (CCV_TENSOR_GET_MEMORY(tensor_params.type)((tensor_params.type) & 0x3) == CCV_TENSOR_GPU_MEMORY)
714 cumemcpy(tensor->data.u8, tensor->info.type, data, CCV_TENSOR_CPU_MEMORY, ccv_min(data_size, data_bytes)({ typeof (data_size) _a = (data_size); typeof (data_bytes) _b
= (data_bytes); (_a < _b) ? _a : _b; })
);
715 else
716 memcpy(tensor->data.u8, data, ccv_min(data_size, data_bytes)({ typeof (data_size) _a = (data_size); typeof (data_bytes) _b
= (data_bytes); (_a < _b) ? _a : _b; })
);
717 } else {
718 if (CCV_TENSOR_GET_MEMORY(tensor_params.type)((tensor_params.type) & 0x3) == CCV_TENSOR_GPU_MEMORY)
719 {
720 void* const workspace = ccmallocmalloc(data_size);
721 size_t decoded_size = data_size;
722 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace, &decoded_size))
723 cumemcpy(tensor_out[0]->data.u8, tensor_out[0]->info.type, workspace, CCV_TENSOR_CPU_MEMORY, ccv_min(data_size, decoded_size)({ typeof (data_size) _a = (data_size); typeof (decoded_size)
_b = (decoded_size); (_a < _b) ? _a : _b; })
);
724 else {
725 if (!tensor)
726 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
727 cumemcpy(tensor->data.u8, tensor->info.type, data, CCV_TENSOR_CPU_MEMORY, ccv_min(data_size, data_bytes)({ typeof (data_size) _a = (data_size); typeof (data_bytes) _b
= (data_bytes); (_a < _b) ? _a : _b; })
);
728 }
729 ccfreefree(workspace);
730 } else {
731 size_t decoded_size = data_size;
732 if (!options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, tensor ? tensor->data.u8 : 0, &decoded_size))
733 {
734 if (!tensor)
735 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
736 memcpy(tensor->data.u8, data, ccv_min(data_size, data_bytes)({ typeof (data_size) _a = (data_size); typeof (data_bytes) _b
= (data_bytes); (_a < _b) ? _a : _b; })
);
737 }
738 }
739 }
740#elif defined(HAVE_MPS)
741 if (!options || !options->decode)
742 {
743 if (CCV_TENSOR_GET_MEMORY(tensor_params.type)((tensor_params.type) & 0x3) == CCV_TENSOR_GPU_MEMORY)
744 {
745 assert(tensor->dataof == 0)((void) sizeof ((tensor->dataof == 0) ? 1 : 0), __extension__
({ if (tensor->dataof == 0) ; else __assert_fail ("tensor->dataof == 0"
, "ccv_nnc_tensor_io.c", 745, __extension__ __PRETTY_FUNCTION__
); }))
;
746 mpmemcpy(tensor->data.u8, tensor->dataof, tensor->info.type, data, 0, CCV_TENSOR_CPU_MEMORY, ccv_min(data_size, data_bytes)({ typeof (data_size) _a = (data_size); typeof (data_bytes) _b
= (data_bytes); (_a < _b) ? _a : _b; })
);
747 } else
748 memcpy(tensor->data.u8, data, ccv_min(data_size, data_bytes)({ typeof (data_size) _a = (data_size); typeof (data_bytes) _b
= (data_bytes); (_a < _b) ? _a : _b; })
);
749 } else {
750 if (CCV_TENSOR_GET_MEMORY(tensor_params.type)((tensor_params.type) & 0x3) == CCV_TENSOR_GPU_MEMORY)
751 {
752 if (tensor)
753 { assert(tensor->dataof == 0)((void) sizeof ((tensor->dataof == 0) ? 1 : 0), __extension__
({ if (tensor->dataof == 0) ; else __assert_fail ("tensor->dataof == 0"
, "ccv_nnc_tensor_io.c", 753, __extension__ __PRETTY_FUNCTION__
); }))
; }
754 void* const workspace = ccmallocmalloc(data_size);
755 size_t decoded_size = data_size;
756 if (options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, workspace, &decoded_size)) {
757 mpmemcpy(tensor_out[0]->data.u8, tensor_out[0]->dataof, tensor_out[0]->info.type, workspace, 0, CCV_TENSOR_CPU_MEMORY, ccv_min(data_size, decoded_size)({ typeof (data_size) _a = (data_size); typeof (decoded_size)
_b = (decoded_size); (_a < _b) ? _a : _b; })
);
758 } else {
759 if (!tensor)
760 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
761 mpmemcpy(tensor->data.u8, tensor->dataof, tensor->info.type, data, 0, CCV_TENSOR_CPU_MEMORY, ccv_min(data_size, data_bytes)({ typeof (data_size) _a = (data_size); typeof (data_bytes) _b
= (data_bytes); (_a < _b) ? _a : _b; })
);
762 }
763 ccfreefree(workspace);
764 } else {
765 size_t decoded_size = data_size;
766 if (!options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, tensor ? tensor->data.u8 : 0, &decoded_size))
767 {
768 if (!tensor)
769 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
770 memcpy(tensor->data.u8, data, ccv_min(data_size, data_bytes)({ typeof (data_size) _a = (data_size); typeof (data_bytes) _b
= (data_bytes); (_a < _b) ? _a : _b; })
);
771 }
772 }
773 }
774#else
775 if (!options || !options->decode)
776 memcpy(tensor->data.u8, data, ccv_min(data_size, data_bytes)({ typeof (data_size) _a = (data_size); typeof (data_bytes) _b
= (data_bytes); (_a < _b) ? _a : _b; })
);
777 else {
778 size_t decoded_size = data_size;
779 if (!options->decode(data, data_bytes, datatype, dim, nd, identifier, options->context, tensor_params, tensor_out, tensor ? tensor->data.u8 : 0, &decoded_size))
780 {
781 if (!tensor)
782 *tensor_out = tensor = ccv_nnc_tensor_new(0, tensor_params, 0);
783 memcpy(tensor->data.u8, data, ccv_min(data_size, data_bytes)({ typeof (data_size) _a = (data_size); typeof (data_bytes) _b
= (data_bytes); (_a < _b) ? _a : _b; })
);
784 }
785 }
786#endif
787 }
788 tensor_out[0]->type &= ~CCV_GARBAGE; // If it is marked as garbage, remove that mark now.
789 sqlite3_reset(tensor_select_stmt);
790 sqlite3_clear_bindings(tensor_select_stmt);
791 sqlite3_finalize(tensor_select_stmt);
792 if (split_workspace)
793 ccfreefree(split_workspace);
794 return CCV_IO_FINAL;
795}