Coverage Report

Created: 2021-04-12 03:25

/home/liu/buildslave/linux-x64-runtests/build/lib/nnc/ccv_nnc_tensor_io.c
Line
Count
Source (jump to first uncovered line)
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
#ifdef HAVE_CUDA
8
#include "gpu/ccv_nnc_compat.h"
9
#endif
10
11
#ifdef NDEBUG
12
#define SQLITE_ENFORCE(stmt) (void)(stmt)
13
#else
14
22
#define SQLITE_ENFORCE assert
15
#endif
16
17
// MARK - Level-1 API
18
19
int ccv_nnc_tensor_write(const ccv_nnc_tensor_t* const tensor, void* const handle, const char* const name)
20
11
{
21
11
  assert(!CCV_IS_TENSOR_VIEW(tensor));
22
11
  assert(name);
23
11
  sqlite3* conn = (sqlite3*)handle;
24
11
  if (!conn)
25
0
    return CCV_IO_ERROR;
26
11
  const char tensor_create_table_qs[] = "CREATE TABLE IF NOT EXISTS tensors "
27
11
    "(name TEXT, type INTEGER, format INTEGER, datatype INTEGER, "
28
11
    "dim BLOB, data BLOB, PRIMARY KEY (name))";
29
11
  SQLITE_ENFORCE(SQLITE_OK == sqlite3_exec(conn, tensor_create_table_qs, 0, 0, 0));
30
11
  const char tensor_insert_qs[] =
31
11
    "REPLACE INTO tensors "
32
11
    "(name, type, format, datatype, dim, data) VALUES ("
33
11
    "$name, $type, $format, $datatype, $dim, $data)";
34
11
  sqlite3_stmt* tensor_insert_stmt = 0;
35
11
  SQLITE_ENFORCE(SQLITE_OK == sqlite3_prepare_v2(conn, tensor_insert_qs, sizeof(tensor_insert_qs), &tensor_insert_stmt, 0));
36
11
  sqlite3_bind_text(tensor_insert_stmt, 1, name, -1, 0);
37
11
  sqlite3_bind_int(tensor_insert_stmt, 2, tensor->info.type);
38
11
  sqlite3_bind_int(tensor_insert_stmt, 3, tensor->info.format);
39
11
  sqlite3_bind_int(tensor_insert_stmt, 4, tensor->info.datatype);
40
11
  sqlite3_bind_blob(tensor_insert_stmt, 5, tensor->info.dim, sizeof(tensor->info.dim), 0);
41
11
  const size_t data_size = ccv_nnc_tensor_data_size(tensor->info);
42
11
  void* workspace = 0;
43
11
#ifdef HAVE_CUDA
44
11
  if (CCV_TENSOR_GET_MEMORY(tensor->info.type) == CCV_TENSOR_GPU_MEMORY)
45
0
  {
46
0
    workspace = ccmalloc(data_size);
47
0
    cumemcpy(workspace, CCV_TENSOR_CPU_MEMORY, tensor->data.u8, tensor->info.type, data_size);
48
0
    sqlite3_bind_blob(tensor_insert_stmt, 6, workspace, data_size, 0);
49
0
  } else
50
11
    sqlite3_bind_blob(tensor_insert_stmt, 6, tensor->data.u8, data_size, 0);
51
#else
52
  sqlite3_bind_blob(tensor_insert_stmt, 6, tensor->data.u8, data_size, 0);
53
#endif
54
11
  sqlite3_step(tensor_insert_stmt);
55
11
  sqlite3_reset(tensor_insert_stmt);
56
11
  sqlite3_clear_bindings(tensor_insert_stmt);
57
11
  sqlite3_finalize(tensor_insert_stmt);
58
11
  if (workspace)
59
0
    free(workspace);
60
11
  return CCV_IO_FINAL;
61
11
}
62
63
int ccv_nnc_tensor_read(void* const handle, const char* const name, ccv_nnc_tensor_t** const tensor_out)
64
12
{
65
12
  assert(name);
66
12
  sqlite3* conn = (sqlite3*)handle;
67
12
  if (!conn)
68
0
    return CCV_IO_ERROR;
69
12
  const char tensor_select_qs[] =
70
12
    "SELECT data, type, format, datatype, dim FROM tensors WHERE name=$name";
71
12
  sqlite3_stmt* tensor_select_stmt = 0;
72
12
  if (SQLITE_OK != sqlite3_prepare_v2(conn, tensor_select_qs, sizeof(tensor_select_qs), &tensor_select_stmt, 0))
73
0
    return CCV_IO_ERROR;
74
12
  sqlite3_bind_text(tensor_select_stmt, 1, name, -1, 0);
75
12
  if (SQLITE_ROW != sqlite3_step(tensor_select_stmt))
76
0
    return CCV_IO_ERROR;
77
12
  ccv_nnc_tensor_t* tensor = *tensor_out;
78
12
  int datatype = 0;
79
12
  if (!tensor) // If the tensor is not provided, we need to create one.
80
1
  {
81
1
    ccv_nnc_tensor_param_t info;
82
1
    info.type = sqlite3_column_int(tensor_select_stmt, 1);
83
1
    info.format = sqlite3_column_int(tensor_select_stmt, 2);
84
1
    datatype = info.datatype = sqlite3_column_int(tensor_select_stmt, 3);
85
1
    const void* const dim = sqlite3_column_blob(tensor_select_stmt, 4);
86
1
    memcpy(info.dim, dim, ccv_min(sizeof(info.dim), sqlite3_column_bytes(tensor_select_stmt, 4)));
87
1
    *tensor_out = tensor = ccv_nnc_tensor_new(0, info, 0);
88
1
  } else
89
11
    datatype = sqlite3_column_int(tensor_select_stmt, 3);
90
12
  const void* const data = sqlite3_column_blob(tensor_select_stmt, 0);
91
12
  if (datatype != tensor->info.datatype)
92
0
  {
93
0
    // Only ever works for 16F to 32F or 32F to 16F transparently.
94
0
    assert((datatype == CCV_16F && tensor->info.datatype == CCV_32F) || (datatype == CCV_32F && tensor->info.datatype == CCV_16F));
95
0
    const size_t tensor_count = ccv_nnc_tensor_count(tensor->info);
96
0
#ifdef HAVE_CUDA
97
0
    if (CCV_TENSOR_GET_MEMORY(tensor->info.type) == CCV_TENSOR_GPU_MEMORY)
98
0
    {
99
0
      size_t data_size = ccv_nnc_tensor_data_size(tensor->info);
100
0
      void* const workspace = ccmalloc(data_size);
101
0
      if (datatype == CCV_16F && tensor->info.datatype == CCV_32F)
102
0
        ccv_half_precision_to_float((uint16_t*)data, (float*)workspace, ccv_min(tensor_count, sqlite3_column_bytes(tensor_select_stmt, 0) / sizeof(uint16_t)));
103
0
      else
104
0
        ccv_float_to_half_precision((float*)data, (uint16_t*)workspace, ccv_min(tensor_count, sqlite3_column_bytes(tensor_select_stmt, 0) / sizeof(float)));
105
0
      if (CCV_TENSOR_GET_MEMORY(tensor->info.type) == CCV_TENSOR_GPU_MEMORY)
106
0
        cumemcpy(tensor->data.u8, tensor->info.type, workspace, CCV_TENSOR_CPU_MEMORY, data_size);
107
0
      ccfree(workspace);
108
0
    } else {
109
0
      if (datatype == CCV_16F && tensor->info.datatype == CCV_32F)
110
0
        ccv_half_precision_to_float((uint16_t*)data, tensor->data.f32, ccv_min(tensor_count, sqlite3_column_bytes(tensor_select_stmt, 0) / sizeof(uint16_t)));
111
0
      else
112
0
        ccv_float_to_half_precision((float*)data, (uint16_t*)tensor->data.f16, ccv_min(tensor_count, sqlite3_column_bytes(tensor_select_stmt, 0) / sizeof(float)));
113
0
    }
114
#else
115
    if (datatype == CCV_16F && tensor->info.datatype == CCV_32F)
116
      ccv_half_precision_to_float((uint16_t*)data, tensor->data.f32, ccv_min(tensor_count, sqlite3_column_bytes(tensor_select_stmt, 0) / sizeof(uint16_t)));
117
    else
118
      ccv_float_to_half_precision((float*)data, (uint16_t*)tensor->data.f16, ccv_min(tensor_count, sqlite3_column_bytes(tensor_select_stmt, 0) / sizeof(float)));
119
#endif
120
12
  } else {
121
12
    size_t data_size = ccv_nnc_tensor_data_size(tensor->info);
122
12
#ifdef HAVE_CUDA
123
12
    if (CCV_TENSOR_GET_MEMORY(tensor->info.type) == CCV_TENSOR_GPU_MEMORY)
124
0
      cumemcpy(tensor->data.u8, tensor->info.type, data, CCV_TENSOR_CPU_MEMORY, ccv_min(data_size, sqlite3_column_bytes(tensor_select_stmt, 0)));
125
12
    else
126
12
      memcpy(tensor->data.u8, data, ccv_min(data_size, sqlite3_column_bytes(tensor_select_stmt, 0)));
127
#else
128
    memcpy(tensor->data.u8, data, ccv_min(data_size, sqlite3_column_bytes(tensor_select_stmt, 0)));
129
#endif
130
12
  }
131
12
  tensor->type &= ~CCV_GARBAGE; // If it is marked as garbage, remove that mark now.
132
12
  sqlite3_reset(tensor_select_stmt);
133
12
  sqlite3_clear_bindings(tensor_select_stmt);
134
12
  sqlite3_finalize(tensor_select_stmt);
135
12
  return CCV_IO_FINAL;
136
12
}