Coverage Report

Created: 2024-08-19 11:27

/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/ccv_cnnp_model_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_cnnp_model.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
2
#define SQLITE_ENFORCE assert
15
#endif
16
17
static inline int _model_tensor_write(const ccv_cnnp_model_t* const self, const ccv_nnc_tensor_t* const tensor, const char* const sql, void* const handle, const char* const name, const ccv_nnc_tensor_io_option_t* const options)
18
12
{
19
12
  if (self->rw.writer)
20
0
    return self->rw.writer(tensor, sql, handle, name, options);
21
12
  if (sql)
22
2
  {
23
2
    sqlite3* conn = (sqlite3*)handle;
24
2
    SQLITE_ENFORCE(SQLITE_OK == sqlite3_exec(conn, sql, 0, 0, 0));
25
2
    return CCV_IO_FINAL;
26
2
  } else
27
10
    return ccv_nnc_tensor_write(tensor, handle, name, options);
28
12
}
29
30
int ccv_cnnp_model_write(const ccv_cnnp_model_t* const model, void* const handle, const char* const name, const ccv_nnc_tensor_io_option_t* const options)
31
1
{
32
1
  ccv_cnnp_compiled_data_t* const compiled_data = model->compiled_data;
33
1
  assert(compiled_data); // The model has to be compiled.
34
1
  _model_tensor_write(model, 0, "BEGIN", handle, 0, options);
35
1
  int i, j;
36
1
  const int parallel_count = ccv_max(model->parallel_count, 1);
37
1
  const int parameter_size = compiled_data->parameters->rnum;
38
1
  const int internal_size = compiled_data->internals->rnum;
39
1
  char internal_name[2048 + 16];
40
11
  for (i = 0; i < parameter_size; 
i++10
)
41
10
  {
42
10
    const char* const id = *(char**)ccv_array_get(compiled_data->ids.parameters, i);
43
10
    if (name)
44
0
      snprintf(internal_name, 2048 + 16, "__%s__[%s]", name, id);
45
10
    else
46
10
      snprintf(internal_name, 2048 + 16, "%s", id);
47
10
    _model_tensor_write(model, CCV_NNC_TENSOR(compiled_data->tensors.parameters[i]), 0, handle, internal_name, options);
48
10
  }
49
2
  for (i = 0; i < parallel_count; 
i++1
)
50
1
    for (j = 0; j < internal_size; 
j++0
)
51
0
    {
52
0
      const char* const id = *(char**)ccv_array_get(compiled_data->ids.internals, j);
53
0
      if (name)
54
0
        snprintf(internal_name, 2048 + 16, "__%s__[%s(%d)]", name, id, i);
55
0
      else
56
0
        snprintf(internal_name, 2048 + 16, "%s(%d)", id, i);
57
0
      _model_tensor_write(model, compiled_data->tensors.internals[i * internal_size + j], 0, handle, internal_name, options);
58
0
    }
59
1
  _model_tensor_write(model, 0, "COMMIT", handle, 0, options);
60
1
  return CCV_IO_FINAL;
61
1
}
62
63
static inline int _model_tensor_read(const ccv_cnnp_model_t* const self, void* const handle, const char* const name, const ccv_nnc_tensor_io_option_t* const options, const ccv_nnc_tensor_param_t info, ccv_nnc_tensor_t** const tensor_out)
64
10
{
65
10
  if (self->rw.reader)
66
0
    return self->rw.reader(handle, name, options, info, tensor_out);
67
10
  return ccv_nnc_tensor_read(handle, name, options, 0, &info, tensor_out);
68
10
}
69
70
int ccv_cnnp_model_read(void* const handle, const char* const name, const ccv_nnc_tensor_io_option_t* const options, const ccv_cnnp_model_t* const model_out)
71
1
{
72
1
  sqlite3* conn = (sqlite3*)handle;
73
1
  assert(conn);
74
1
  ccv_cnnp_compiled_data_t* const compiled_data = model_out->compiled_data;
75
1
  assert(compiled_data); // The model has to be compiled.
76
1
  const int tensors_init = !!compiled_data->tensors_init.v;
77
1
  if (!tensors_init)
78
1
    ccv_cnnp_model_tensors_init_0(model_out, compiled_data);
79
1
  int i, j;
80
1
  const int parallel_count = ccv_max(model_out->parallel_count, 1);
81
1
  const int parameter_size = compiled_data->parameters->rnum;
82
1
  const int internal_size = compiled_data->internals->rnum;
83
1
  char internal_name[2048 + 16];
84
1
  uint32_t* const init_v = CCV_NNC_INIT_V(compiled_data->tensors_init.v);
85
11
  for (i = 0; i < parameter_size; 
i++10
)
86
10
  {
87
10
    const char* const id = *(char**)ccv_array_get(compiled_data->ids.parameters, i);
88
10
    if (name)
89
0
      snprintf(internal_name, 2048 + 16, "__%s__[%s]", name, id);
90
10
    else
91
10
      snprintf(internal_name, 2048 + 16, "%s", id);
92
10
    const ccv_nnc_tensor_symbol_t parameter = *(ccv_nnc_tensor_symbol_t*)ccv_array_get(compiled_data->parameters, i);
93
10
    const int d = parameter.d;
94
10
    ccv_nnc_tensor_param_t info = ccv_nnc_tensor_symbol_params(parameter.graph, parameter);
95
10
    if (CCV_TENSOR_GET_DEVICE(info.type) == CCV_COMPUTE_DEVICE_ANY)
96
10
      CCV_TENSOR_SET_DEVICE_ID(info.type, 0);
97
10
    const int device_id = CCV_TENSOR_GET_DEVICE_ID(info.type);
98
10
    if (compiled_data->tensors.parameters[i]) // Cannot be a shared parameter to read.
99
0
      { assert(!((uintptr_t)compiled_data->tensors.parameters[i] & (uintptr_t)1)); }
100
10
    if (_model_tensor_read(model_out, conn, internal_name, options, info, compiled_data->tensors.parameters + i) == CCV_IO_FINAL)
101
10
    {
102
10
      init_v[d >> 5] |= (1u << (d & 0x1f));
103
      // Create this tensor for other data parallel allocations.
104
10
      info = compiled_data->tensors.parameters[i]->info; // In case we loaded a different info.
105
10
      for (j = 1; j < parallel_count; 
j++0
)
106
0
        if (!compiled_data->tensors.parameters[i + j * parameter_size])
107
0
        {
108
0
          if (j != device_id)
109
0
            CCV_TENSOR_SET_DEVICE_ID(info.type, j);
110
0
          else
111
0
            CCV_TENSOR_SET_DEVICE_ID(info.type, 0);
112
0
          compiled_data->tensors.parameters[i + j * parameter_size] = ccv_nnc_tensor_new(0, info, 0);
113
0
        }
114
        // No need to copy over, this is done in ccv_cnnp_model.c's copy_tensors method.
115
10
    }
116
10
  }
117
2
  
for (i = 0; 1
i < parallel_count;
i++1
)
118
1
    for (j = 0; j < internal_size; 
j++0
)
119
0
    {
120
0
      const char* const id = *(char**)ccv_array_get(compiled_data->ids.internals, j);
121
0
      if (name)
122
0
        snprintf(internal_name, 2048 + 16, "__%s__[%s(%d)]", name, id, i);
123
0
      else
124
0
        snprintf(internal_name, 2048 + 16, "%s(%d)", id, i);
125
0
      const ccv_nnc_tensor_symbol_t retained = *(ccv_nnc_tensor_symbol_t*)ccv_array_get(compiled_data->internals, j);
126
0
      const int d = retained.d;
127
0
      ccv_nnc_tensor_param_t info = ccv_nnc_tensor_symbol_params(retained.graph, retained);
128
0
      if (CCV_TENSOR_GET_DEVICE(info.type) == CCV_COMPUTE_DEVICE_ANY)
129
0
        CCV_TENSOR_SET_DEVICE_ID(info.type, 0);
130
0
      if (i > 0)
131
0
      {
132
0
        const int device_id = CCV_TENSOR_GET_DEVICE_ID(info.type);
133
0
        if (i != device_id)
134
0
          CCV_TENSOR_SET_DEVICE_ID(info.type, i);
135
0
        else
136
0
          CCV_TENSOR_SET_DEVICE_ID(info.type, 0);
137
0
      }
138
0
      if (_model_tensor_read(model_out, conn, internal_name, options, info, compiled_data->tensors.internals + i * internal_size + j) == CCV_IO_FINAL)
139
0
        init_v[d >> 5] |= (1u << (d & 0x1f));
140
0
    }
141
  // Mark it as to have some other tensors to allocate.
142
1
  if (ccv_cnnp_model_tensors_any_to_alloc(model_out, compiled_data))
143
0
    compiled_data->tensors_init.v = (uint32_t*)((uintptr_t)compiled_data->tensors_init.v | (uintptr_t)1);
144
1
  else // Remove the flag.
145
1
    compiled_data->tensors_init.v = CCV_NNC_INIT_V(compiled_data->tensors_init.v);
146
1
  return CCV_IO_FINAL;
147
1
}
148
149
void ccv_cnnp_model_write_to_file(ccv_cnnp_model_t* const model, const char* const fn, const ccv_nnc_tensor_io_option_t* const options)
150
1
{
151
1
  ccv_cnnp_compiled_data_t* const compiled_data = model->compiled_data;
152
1
  assert(compiled_data); // The model has to be compiled.
153
1
  sqlite3* conn = 0;
154
1
  if (SQLITE_OK != sqlite3_open(fn, &conn))
155
0
    return;
156
1
  ccv_cnnp_model_write(model, conn, 0, options);
157
1
  sqlite3_close(conn);
158
1
}
159
160
void ccv_cnnp_model_read_from_file(const char* const fn, const ccv_nnc_tensor_io_option_t* const options, const ccv_cnnp_model_t* const model)
161
1
{
162
1
  ccv_cnnp_compiled_data_t* const compiled_data = model->compiled_data;
163
1
  assert(compiled_data); // The model has to be compiled.
164
1
  sqlite3* conn = 0;
165
1
  if (SQLITE_OK != sqlite3_open(fn, &conn))
166
0
    return;
167
1
  ccv_cnnp_model_read(conn, 0, options, model);
168
1
  sqlite3_close(conn);
169
1
}
170
171
void ccv_cnnp_model_set_io(ccv_cnnp_model_t* const model, ccv_cnnp_model_io_reader_f reader, ccv_cnnp_model_io_writer_f writer)
172
0
{
173
0
  model->rw.reader = reader;
174
0
  model->rw.writer = writer;
175
0
}