Coverage Report

Created: 2025-02-24 17:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/_ccv_nnc_symbolic_graph.h
Line
Count
Source
1
/**********************************************************
2
 * C-based/Cached/Core Computer Vision Library
3
 * Liu Liu, 2010-02-01
4
 **********************************************************/
5
6
/**********************************************************
7
 * CCV - Neural Network Collection
8
 **********************************************************/
9
10
#ifndef GUARD_ccv_nnc_symbolic_graph_internal_h
11
#define GUARD_ccv_nnc_symbolic_graph_internal_h
12
13
#include "ccv_nnc.h"
14
#include "ccv_nnc_internal.h"
15
16
typedef struct {
17
  // Start for while loop handling
18
  int assign_ref; // Reference to the tensor that the value will be copied from (for parameter passing). Starts at 1.
19
  int r_assign_ref; // It is a reverse of the assign_ref. Starts at 1.
20
  int bypass_ref; // Some exec may not generate output for this tensor. In that case, use the content from tensor bypass (typical case for case..of). Starts at 1.
21
  int r_bypass_ref; // It is a reverse of the bypass_ref. Starts at 1.
22
  int p_ref; // Reference to the tensor number in its parent graph. Starts at 1.
23
  // End of while loop handling.
24
  int alias_ref; // Reference to the tensor. Starts at 1.
25
  int pair_ref; // Reference to its pair. Starts at 1.
26
  int flags;
27
  int ofs[CCV_NNC_MAX_DIM_ALLOC];
28
  int stride[CCV_NNC_MAX_DIM_ALLOC];
29
  ccv_array_t* s_ref; // Reference to the tensor number in its sub graphs, Starts at 1.
30
  char* name;
31
  ccv_nnc_tensor_param_t info;
32
} ccv_nnc_tensor_symbol_info_t;
33
34
enum {
35
  CCV_NNC_GRAPH_EXEC_CASE_OF_NO_BYPASS = 0x01, // If this flag is set, this case..of won't have any bypass.
36
};
37
38
typedef struct {
39
  int input_size;
40
  int output_size;
41
  int graph_ref_size;
42
  int flags; // Mark this node as dead. Lower 16 bits is for internal use, such as mark as dead. Higher 16-bit can be set.
43
  int pair_ref; // Reference to its pair. Starts at 1.
44
  int* inputs;
45
  int* outputs;
46
  ccv_array_t* outgoings; // Outgoing nodes
47
  char* name;
48
  ccv_nnc_cmd_t cmd;
49
  ccv_nnc_hint_t hint;
50
  // Below are only relevant to sub-graph nodes (case_of, while).
51
  int _inline_graph_ref[2]; // Reference to the sub-graph. Starts at 1.
52
  int* _heap_graph_ref;
53
  union {
54
    struct {
55
      ccv_nnc_graph_case_of_f expr;
56
      const void* data;
57
      int flags;
58
      struct {
59
        int offset;
60
        int size;
61
      } argument; // range for which data as inputs from input section.
62
    } case_of;
63
    struct {
64
      ccv_nnc_graph_while_f expr;
65
      const void* data;
66
      int* inputs;
67
      int input_size;
68
    } p_while;
69
  };
70
} ccv_nnc_graph_exec_symbol_info_t;
71
72
struct ccv_nnc_symbolic_graph_s {
73
  ccv_array_t* tensor_symbol_info; // A lit of info for tensor symbols.
74
  ccv_array_t* exec_symbol_info; // A list of info for exec symbols.
75
  // I think that I can be more explicit about which are sources and which are destinations.
76
  ccv_array_t* sources;
77
  ccv_array_t* destinations;
78
  // Some extra information piggy-back on symbolic graph struct.
79
  // Start for while loop handling
80
  ccv_array_t* sub_graphs; // A list of its sub-graphs (for while loop).
81
  struct ccv_nnc_symbolic_graph_s* pair; // The pair graph (only useful for backward prop graph).
82
  struct ccv_nnc_symbolic_graph_s* p; // The parent graph (if current one is a sub-graph).
83
  int p_idx; // Reference to the index in its parent graph's sub-graph array, Starts at 1.
84
  int exec_idx; // Reference to the index in its parent graph's exec (the graph exec), Starts at 1.
85
  // Why some of these I choose to be flat int* array, some of these I choose to be ccv_array_t?
86
  // for flat int* array, these are not going to be modified until next time call ccv_nnc_symbolic_graph_backward
87
  // for ccv_array_t, we can continue to modify what's inside.
88
  int breakpoint_size;
89
  ccv_nnc_graph_exec_symbol_t* breakpoints;
90
  // End of while loop handling.
91
  struct {
92
    int tensor;
93
    int exec;
94
  } reuse; // The reuse slot for tensor or graph exec symbols.
95
  // Start for backward (automatic differentiation) handling
96
  struct {
97
    int tensor_symbol_size;
98
    int* tensor_symbol_idx;
99
    int exec_symbol_size;
100
    int* exec_symbol_idx;
101
  } backward;
102
  // End of backward (automatic differentiation) handling.
103
  // For parallel, get duplicated tensors.
104
  struct {
105
    int count;
106
    int tensor_symbol_size;
107
    int* tensor_symbol_idx;
108
    int exec_symbol_size;
109
    int* exec_symbol_idx;
110
  } data_parallel;
111
  // Hooks
112
  struct {
113
    struct {
114
      ccv_nnc_tensor_symbol_new_hook_f func;
115
      void* context;
116
    } tensor_symbol_new;
117
    struct {
118
      ccv_nnc_tensor_symbol_alias_new_hook_f func;
119
      void* context;
120
    } tensor_symbol_alias_new;
121
    struct {
122
      ccv_nnc_graph_exec_symbol_new_hook_f func;
123
      void* context;
124
    } graph_exec_symbol_new;
125
  } hooks;
126
};
127
128
typedef void(*ccv_nnc_arena_dispose_f)(void* ptr, void* userdata);
129
typedef struct {
130
  void* ptr;
131
  void* userdata;
132
  ccv_nnc_arena_dispose_f dispose;
133
} ccv_nnc_arena_disposer_t;
134
135
struct ccv_nnc_tensor_arena_s {
136
  intptr_t graph_ref; // A value contains the pointer name of the graph.
137
  int sub_arena_size;
138
  struct ccv_nnc_tensor_arena_s** sub_arenas; // Corresponding to sub graphs.
139
  // This is a table of tensor references to real allocated tensors.
140
  int vt_tensor_size;
141
  ccv_nnc_tensor_t** vt_tensors;
142
  int* vt_alias_refs; // reference to which it is alias to.
143
  int* vt_alias_r_refs_p; // pointer to record which tensor this is aliased to.
144
  int* vt_alias_r_refs; // array to record which tensor this is aliased to. This is first created when bind a symbol.
145
  size_t* vt_sizes; // The size of each tensor.
146
  ccv_numeric_data_t* pb_vt_tensors; // pre-bindings for this vt_tensors, this is optional.
147
  struct {
148
    const ccv_nnc_symbolic_graph_compile_allocator_vtab_t* isa;
149
    struct {
150
      void* free;
151
    } context;
152
  } allocator;
153
  // This is the allocated non-continuous buffers.
154
  int buffer_size;
155
  struct {
156
    int type; // The type from tensor blocks.
157
    int pin_mem; // Whether this memory is pinned.
158
    uint64_t size;
159
    uint8_t* ptr;
160
  }* buffers;
161
  // Real allocated tensor header metadata (this is a mixed pool of ccv_tensor_t, ccv_tensor_view_t,
162
  // ccv_tensor_multiview_t, thus, it is aligned to a 16-byte boundary).
163
  ccv_array_t* tensor_metadata;
164
  ccv_array_t* m_tensor_idx; // The index into multi-view tensors in tensor_metadata.
165
  ccv_array_t* disposers; // Generic dispose structure that shares life-cycle with the arena.
166
};
167
168
struct ccv_nnc_graph_exec_arena_s {
169
  intptr_t graph_ref; // A value contains the pointer name of the graph.
170
  int sub_arena_size;
171
  struct ccv_nnc_graph_exec_arena_s** sub_arenas; // Corresponding to sub graphs.
172
  ccv_nnc_graph_exec_t source;
173
  ccv_nnc_graph_exec_t destination;
174
  int graph_exec_size;
175
  ccv_nnc_graph_exec_t graph_execs[1];
176
};
177
178
1
#define CCV_NNC_ENCODE_WHILE_COUNT_SYMBOL(d) ((int)((~(uint32_t)d) << 4 | 0xe))
179
40
#define CCV_NNC_DECODE_WHILE_COUNT_SYMBOL(symbol) ((~(uint32_t)(symbol)) >> 4)
180
181
inline static void ccv_array_replace_unique_int(ccv_array_t* ints, const int idx, const int outgoing)
182
8.59k
{
183
8.59k
  int i;
184
8.59k
  int flag = 0;
185
17.2k
  for (i = 0; i < ints->rnum;)
186
8.60k
  {
187
8.60k
    if (*(int*)ccv_array_get(ints, i) == idx)
188
4.28k
    {
189
4.28k
      if (flag)
190
4
      {
191
4
        if (i < ints->rnum - 1)
192
4
          *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1);
193
4
        --ints->rnum;
194
4
        continue;
195
4
      }
196
4.28k
      *(int*)ccv_array_get(ints, i) = outgoing;
197
4.28k
      flag = 1;
198
4.31k
    } else if (*(int*)ccv_array_get(ints, i) == outgoing) {
199
      // Remove this from the list.
200
4.24k
      if (flag)
201
0
      {
202
0
        if (i < ints->rnum - 1)
203
0
          *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1);
204
0
        --ints->rnum;
205
0
        continue;
206
0
      }
207
4.24k
      flag = 1;
208
4.24k
    }
209
8.60k
    ++i;
210
8.60k
  }
211
8.59k
  if (!flag)
212
70
    ccv_array_push(ints, &outgoing);
213
8.59k
}
Unexecuted instantiation: ccv_nnc_tensor_io.c:ccv_array_replace_unique_int
Unexecuted instantiation: ccv_nnc_symbolic_graph.c:ccv_array_replace_unique_int
Unexecuted instantiation: ccv_nnc_symbolic_graph_io.c:ccv_array_replace_unique_int
Unexecuted instantiation: ccv_nnc_symbolic_graph_compile.c:ccv_array_replace_unique_int
ccv_nnc_symbolic_graph_backward.c:ccv_array_replace_unique_int
Line
Count
Source
182
8.58k
{
183
8.58k
  int i;
184
8.58k
  int flag = 0;
185
17.1k
  for (i = 0; i < ints->rnum;)
186
8.56k
  {
187
8.56k
    if (*(int*)ccv_array_get(ints, i) == idx)
188
4.28k
    {
189
4.28k
      if (flag)
190
0
      {
191
0
        if (i < ints->rnum - 1)
192
0
          *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1);
193
0
        --ints->rnum;
194
0
        continue;
195
0
      }
196
4.28k
      *(int*)ccv_array_get(ints, i) = outgoing;
197
4.28k
      flag = 1;
198
4.28k
    } else if (*(int*)ccv_array_get(ints, i) == outgoing) {
199
      // Remove this from the list.
200
4.23k
      if (flag)
201
0
      {
202
0
        if (i < ints->rnum - 1)
203
0
          *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1);
204
0
        --ints->rnum;
205
0
        continue;
206
0
      }
207
4.23k
      flag = 1;
208
4.23k
    }
209
8.56k
    ++i;
210
8.56k
  }
211
8.58k
  if (!flag)
212
66
    ccv_array_push(ints, &outgoing);
213
8.58k
}
Unexecuted instantiation: ccv_nnc_symbolic_graph_while.c:ccv_array_replace_unique_int
Unexecuted instantiation: ccv_nnc_symbolic_graph_case_of.c:ccv_array_replace_unique_int
Unexecuted instantiation: ccv_nnc_symbolic_graph_minimize.c:ccv_array_replace_unique_int
ccv_nnc_symbolic_graph_parallel.c:ccv_array_replace_unique_int
Line
Count
Source
182
16
{
183
16
  int i;
184
16
  int flag = 0;
185
60
  for (i = 0; i < ints->rnum;)
186
44
  {
187
44
    if (*(int*)ccv_array_get(ints, i) == idx)
188
8
    {
189
8
      if (flag)
190
4
      {
191
4
        if (i < ints->rnum - 1)
192
4
          *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1);
193
4
        --ints->rnum;
194
4
        continue;
195
4
      }
196
4
      *(int*)ccv_array_get(ints, i) = outgoing;
197
4
      flag = 1;
198
36
    } else if (*(int*)ccv_array_get(ints, i) == outgoing) {
199
      // Remove this from the list.
200
8
      if (flag)
201
0
      {
202
0
        if (i < ints->rnum - 1)
203
0
          *(int*)ccv_array_get(ints, i) = *(int*)ccv_array_get(ints, ints->rnum - 1);
204
0
        --ints->rnum;
205
0
        continue;
206
0
      }
207
8
      flag = 1;
208
8
    }
209
40
    ++i;
210
40
  }
211
16
  if (!flag)
212
4
    ccv_array_push(ints, &outgoing);
213
16
}
Unexecuted instantiation: ccv_nnc_symbolic_graph_simplify.c:ccv_array_replace_unique_int
Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_compression.c:ccv_array_replace_unique_int
Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_reduction.c:ccv_array_replace_unique_int
Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_array_replace_unique_int
Unexecuted instantiation: ccv_nnc_symbolic_graph_chain_decomposition.c:ccv_array_replace_unique_int
214
215
void ccv_nnc_symbolic_graph_symbol_infer(const ccv_nnc_symbolic_graph_t* const symbolic_graph, const ccv_nnc_graph_visit_t* const visit, const ccv_nnc_graph_exec_symbol_t* const sources, const int source_size, const ccv_nnc_graph_exec_symbol_t* const destinations, const int destination_size, const ccv_nnc_tensor_symbol_info_t* const p_tensor_symbol_info, const int p_tensor_symbol_info_size, ccv_nnc_tensor_symbol_info_t* const tensor_symbol_info, ccv_nnc_graph_exec_symbol_info_t* const exec_symbol_info);
216
217
int ccv_nnc_over_tensor_symbol_aliases(const ccv_nnc_tensor_symbol_info_t* const tensor_a, const ccv_nnc_tensor_symbol_info_t* const tensor_b);
218
int ccv_nnc_tensor_symbol_map_raw(ccv_nnc_symbolic_graph_t* const graph, const ccv_nnc_tensor_symbol_t symbol);
219
220
typedef struct {
221
  int flags;
222
  int* chain_ids;
223
  int* chain_pos;
224
  ccv_sparse_matrix_t* deps;
225
} ccv_nnc_exec_dep_t;
226
227
ccv_nnc_exec_dep_t ccv_nnc_exec_dep_new(const ccv_nnc_symbolic_graph_t* const graph, const ccv_nnc_graph_visit_t* const visit);
228
void ccv_nnc_exec_dep_free(const ccv_nnc_exec_dep_t exec_dep);
229
230
inline static int ccv_nnc_exec_dep_hop(const ccv_nnc_exec_dep_t exec_dep, const int d, ccv_sparse_matrix_vector_t* const vector, const int dd)
231
0
{
232
  // Check if dd is d's ancestor.
233
0
  const int dd_chain_id = exec_dep.chain_ids[dd];
234
0
  const int dd_chain_pos = exec_dep.chain_pos[dd];
235
0
  if (exec_dep.chain_ids[d] == dd_chain_id)
236
0
    return exec_dep.chain_pos[d] - dd_chain_pos;
237
0
  const ccv_numeric_data_t cell = vector ? ccv_get_sparse_matrix_cell_from_vector(exec_dep.deps, vector, dd_chain_id) : ccv_get_sparse_matrix_cell(exec_dep.deps, d, dd_chain_id);
238
  // Check if the chain pos is greater than or equal to dd_chain_pos. If it is, it is an ancestor.
239
0
  if (cell.i32 && cell.i32[0] > 0 && cell.i32[0] >= dd_chain_pos)
240
0
    return cell.i32[0] - dd_chain_pos + cell.i32[1];
241
0
  return -1;
242
0
}
Unexecuted instantiation: ccv_nnc_tensor_io.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph_io.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph_compile.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph_backward.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph_while.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph_case_of.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph_minimize.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph_parallel.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph_simplify.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_compression.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_reduction.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_cnnp_model_gradient_checkpointing.c:ccv_nnc_exec_dep_hop
Unexecuted instantiation: ccv_nnc_symbolic_graph_chain_decomposition.c:ccv_nnc_exec_dep_hop
243
244
inline static int ccv_nnc_exec_dep_check(const ccv_nnc_exec_dep_t exec_dep, const int d, ccv_sparse_matrix_vector_t* const vector, const int dd)
245
81
{
246
  // Check if dd is d's ancestor.
247
81
  const int dd_chain_id = exec_dep.chain_ids[dd];
248
81
  const int dd_chain_pos = exec_dep.chain_pos[dd];
249
81
  if (exec_dep.chain_ids[d] == dd_chain_id)
250
38
    return exec_dep.chain_pos[d] > dd_chain_pos;
251
43
  if (vector == (ccv_sparse_matrix_vector_t*)1) // Special sentinel value to say that we don't have vector found.
252
22
    return 0;
253
21
  const ccv_numeric_data_t cell = vector ? ccv_get_sparse_matrix_cell_from_vector(exec_dep.deps, vector, dd_chain_id) : 
ccv_get_sparse_matrix_cell(exec_dep.deps, d, dd_chain_id)0
;
254
  // Check if the chain pos is greater than or equal to dd_chain_pos. If it is, it is an ancestor.
255
21
  if (cell.i32 && 
cell.i32[0] > 010
)
256
10
    return cell.i32[0] >= dd_chain_pos;
257
11
  return 0;
258
21
}
Unexecuted instantiation: ccv_nnc_tensor_io.c:ccv_nnc_exec_dep_check
Unexecuted instantiation: ccv_nnc_symbolic_graph.c:ccv_nnc_exec_dep_check
Unexecuted instantiation: ccv_nnc_symbolic_graph_io.c:ccv_nnc_exec_dep_check
Unexecuted instantiation: ccv_nnc_symbolic_graph_compile.c:ccv_nnc_exec_dep_check
Unexecuted instantiation: ccv_nnc_symbolic_graph_backward.c:ccv_nnc_exec_dep_check
Unexecuted instantiation: ccv_nnc_symbolic_graph_while.c:ccv_nnc_exec_dep_check
Unexecuted instantiation: ccv_nnc_symbolic_graph_case_of.c:ccv_nnc_exec_dep_check
Unexecuted instantiation: ccv_nnc_symbolic_graph_minimize.c:ccv_nnc_exec_dep_check
Unexecuted instantiation: ccv_nnc_symbolic_graph_parallel.c:ccv_nnc_exec_dep_check
Unexecuted instantiation: ccv_nnc_symbolic_graph_simplify.c:ccv_nnc_exec_dep_check
Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_compression.c:ccv_nnc_exec_dep_check
Unexecuted instantiation: ccv_nnc_symbolic_graph_memory_reduction.c:ccv_nnc_exec_dep_check
ccv_cnnp_model_gradient_checkpointing.c:ccv_nnc_exec_dep_check
Line
Count
Source
245
81
{
246
  // Check if dd is d's ancestor.
247
81
  const int dd_chain_id = exec_dep.chain_ids[dd];
248
81
  const int dd_chain_pos = exec_dep.chain_pos[dd];
249
81
  if (exec_dep.chain_ids[d] == dd_chain_id)
250
38
    return exec_dep.chain_pos[d] > dd_chain_pos;
251
43
  if (vector == (ccv_sparse_matrix_vector_t*)1) // Special sentinel value to say that we don't have vector found.
252
22
    return 0;
253
21
  const ccv_numeric_data_t cell = vector ? ccv_get_sparse_matrix_cell_from_vector(exec_dep.deps, vector, dd_chain_id) : 
ccv_get_sparse_matrix_cell(exec_dep.deps, d, dd_chain_id)0
;
254
  // Check if the chain pos is greater than or equal to dd_chain_pos. If it is, it is an ancestor.
255
21
  if (cell.i32 && 
cell.i32[0] > 010
)
256
10
    return cell.i32[0] >= dd_chain_pos;
257
11
  return 0;
258
21
}
Unexecuted instantiation: ccv_nnc_symbolic_graph_chain_decomposition.c:ccv_nnc_exec_dep_check
259
260
#endif
261