## Coverage Report

#### Created: 2026-05-04 15:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/liu/actions-runner/_work/ccv/ccv/lib/nnc/_ccv_nnc_dynamic_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_dynamic_graph_internal_h
    11
    #define GUARD_ccv_nnc_dynamic_graph_internal_h
    12
    13
    #include "ccv_nnc.h"
    14
    #include "ccv_nnc_internal.h"
    15
    #include "_ccv_nnc_stream.h"
    16
    #include "_ccv_nnc_xpu_alloc.h"
    17
    #include "3rdparty/khash/khash.h"
    18
    19
    39.2k
    #define CCV_NNC_IS_EXTERN_TENSOR_VIEW(tv) ((uintptr_t)(tv) & 1)
    20
    69.9k
    #define CCV_NNC_TENSOR_VIEW(tv) ((ccv_nnc_tensor_view_t*)((uintptr_t)(tv) & ~(uintptr_t)1))
    21
    22
    enum {
    23
      CCV_NNC_TENSOR_VARIABLE,
    24
      CCV_NNC_TENSOR_CONSTANT,
    25
    };
    26
    27
    struct ccv_nnc_tensor_variable_s {
    28
      int type;
    29
      int index;
    30
      int alias_index_ref; // The index back into the original tensor variable. 0 means no alias.
    31
      off_t alias_off; // If it is an alias, what's the off on the tensor before ofs applied.
    32
      struct {
    33
        ccv_nnc_tensor_variable_destructor_f func;
    34
        void* context;
    35
      } destructor_hook;
    36
      ccv_nnc_tensor_param_t info;
    37
      ccv_nnc_tensor_symbol_t symbol;
    38
      ccv_nnc_tensor_view_t* tensor_view;
    39
      int ofs[CCV_NNC_MAX_DIM_ALLOC];
    40
      int stride[CCV_NNC_MAX_DIM_ALLOC];
    41
    };
    42
    43
    enum {
    44
      CCV_NNC_TENSOR_NO_VARIABLE = -1,
    45
      CCV_NNC_TENSOR_NO_VARIABLE_BUT_USED = -2,
    46
    };
    47
    48
    typedef struct {
    49
      ccv_nnc_cmd_vtab_t super;
    50
      void(*apply_gradients)(const ccv_nnc_cmd_t cmd, ccv_nnc_stream_context_t* const stream_context);
    51
    } ccv_nnc_stateful_cmd_vtab_t;
    52
    53
    typedef struct { // Extra information kept per tensor symbol along with symbolic graph.
    54
      int type;
    55
      int index; // The index back into the tensor variable. -1 meant no associated tensor vairable.
    56
      int alias_ref; // If this is an alias tensor view to a tensor. 0 means no alias, otherwise the index + 1 of the original symbol on the tape.
    57
      struct {
    58
        ccv_nnc_tensor_variable_destructor_f func;
    59
        void* context;
    60
      } destructor_hook;
    61
      ccv_array_t* sources; // array of graph_exec_symbol, use this tensor symbol as output.
    62
      ccv_array_t* destinations; // array of graph_exec_symbol, use this tensor symbol as input.
    63
      ccv_nnc_tensor_view_t* tensor_view; // Transfer ownership of the tensor view to here.
    64
    } ccv_nnc_tensor_variable_graph_bind_t;
    65
    66
    typedef struct {
    67
      ccv_nnc_xpu_alloc_t* xpu_alloc;
    68
      ccv_nnc_stream_context_t* stream;
    69
    } ccv_nnc_dy_xpu_alloc_t;
    70
    71
    typedef struct {
    72
      int8_t requires_grad;
    73
      int8_t is_test;
    74
      int8_t did_backward_but_not_apply_gradients;
    75
      int8_t should_free;
    76
      int index;
    77
      uint64_t disable_outgrad;
    78
      ccv_nnc_tensor_tape_t* tensor_tape;
    79
      void* data;
    80
      ccv_nnc_cmd_t cmd;
    81
    } ccv_nnc_stateful_exec_t;
    82
    83
    KHASH_MAP_INIT_INT(stateful_exec, ccv_nnc_stateful_exec_t*)
    84
    85
    struct ccv_nnc_dynamic_graph_s {
    86
      int no_grad; // 1 if gradient computation is disabled.
    87
      int max_stream_count;
    88
      int reuse_var; // -1 if no var can be reused. Otherwise first locate the reuse var without increase array size.
    89
      int reuse_stateful_exec; // -1 if no stateful exec can be reused. Otherwise first locate the reuse without increase array size.
    90
      ccv_nnc_xpu_alloc_t xpu_alloc; // Allocate memory dynamically.
    91
      ccv_array_t* vars; // Array keeps track of all allocated tensor variable.
    92
      ccv_array_t* binds; // Array keeps track of extra information for a tensor symbol.
    93
      ccv_array_t* stateful_execs; // Array keeps track of the stateful execs. The stateful execs type can have additional apply_gradients calls to update its internal states.
    94
      ccv_nnc_symbolic_graph_t* tape; // Symbolic graph to keep track of computation.
    95
      khash_t(stream_map)* stream_map; // Keeps track of streams on both GPU / CPU and devices so it can be used properly during execution.
    96
      ccv_array_t* ws; // array of integers as workspace
    97
    };
    98
    99
    ccv_nnc_tensor_variable_t ccv_nnc_tensor_variable_exchange_new(ccv_nnc_dynamic_graph_t* const graph, ccv_nnc_tensor_variable_t tensor_variable);
    100
    101
    static inline void ccv_nnc_insert_if_prior_to_any(const ccv_nnc_symbolic_graph_t* const graph, const int d, ccv_array_t* const sources, uint32_t* const visited, int* const buf0, int* const buf1)
    102
    4.48k
    {
    103
    4.48k
      if (visited[(d >> 5)] & (1u << (d & 31)))
    104
    7
        return;
    105
    4.48k
      visited[(d >> 5)] |= (1u << (d & 31));
    106
    4.48k
      buf0[0] = d;
    107
    4.48k
      int* buf[2] = {
    108
    4.48k
        buf0, buf1
    109
    4.48k
      };
    110
    4.48k
      int buf_size[2] = {
    111
    4.48k
        1, 0
    112
    4.48k
      };
    113
    4.48k
      int p = 0, q = 1;
    114
    4.48k
      int i, j, k;
    115
    4.48k
      int flag = 0;
    116
    19.7k
      while (buf_size[p] > 0)
    117
    15.3k
      {
    118
    15.3k
        buf_size[q] = 0;
    119
    30.6k
        for (i = 0; i < buf_size[p]; i++15.3k)
    120
    15.3k
        {
    121
    15.3k
          const int* outgoings; int outgoing_size;
    122
    15.3k
          ccv_nnc_graph_exec_symbol_to(graph, (ccv_nnc_graph_exec_symbol_t){
    123
    15.3k
            .d = buf[p][i],
    124
    15.3k
            .graph = graph
    125
    15.3k
          }, &outgoings, &outgoing_size);
    126
    26.1k
          for (j = 0; j < outgoing_size; j++10.8k)
    127
    10.8k
          {
    128
    10.8k
            const int outgoing_idx = outgoings[j];
    129
    10.9k
            for (k = 0; k < sources->rnum; k++85)
    130
    85
            {
    131
    85
              ccv_nnc_graph_exec_symbol_t* const source_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, k);
    132
              // If this outgoing idx is one of the source, replace it with d, or delete it.
    133
    85
              if (source_symbol->d == outgoing_idx)
    134
    0
              {
    135
    0
                if (!flag)
    136
    0
                {
    137
    0
                  source_symbol->d = d;
    138
    0
                  flag = 1;
    139
    0
                } else {
    140
                  // Delete this from the list.
    141
    0
                  if (k < sources->rnum - 1)
    142
    0
                    source_symbol->d = ((ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, sources->rnum - 1))->d;
    143
    0
                  --sources->rnum;
    144
    0
                }
    145
    0
                break;
    146
    0
              }
    147
    85
            }
    148
    10.8k
            if (visited[(outgoing_idx >> 5)] & (1u << (outgoing_idx & 31)))
    149
    19
              continue;
    150
    10.8k
            visited[(outgoing_idx >> 5)] |= (1u << (outgoing_idx & 31));
    151
    10.8k
            buf[q][buf_size[q]] = outgoing_idx;
    152
    10.8k
            ++buf_size[q];
    153
    10.8k
          }
    154
    15.3k
        }
    155
    15.3k
        CCV_SWAP(p, q, i);
    156
    15.3k
      }
    157
      // If this node is not visited, and we cannot find anything in the sources to replace, this is a new top node.
    158
    4.48k
      if (!flag)
    159
    4.48k
      {
    160
    4.48k
        const ccv_nnc_graph_exec_symbol_t source_symbol = {
    161
    4.48k
          .d = d,
    162
    4.48k
          .graph = graph
    163
    4.48k
        };
    164
    4.48k
        ccv_array_push(sources, &source_symbol);
    165
    4.48k
      }
    166
    4.48k
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph.c:ccv_nnc_insert_if_prior_to_any
    Unexecuted instantiation: ccv_nnc_dynamic_graph_alloc.c:ccv_nnc_insert_if_prior_to_any

    ccv_nnc_dynamic_graph_backward.c:ccv_nnc_insert_if_prior_to_any

    Line
    Count
    Source
    102
    3.48k
    {
    103
    3.48k
      if (visited[(d >> 5)] & (1u << (d & 31)))
    104
    7
        return;
    105
    3.47k
      visited[(d >> 5)] |= (1u << (d & 31));
    106
    3.47k
      buf0[0] = d;
    107
    3.47k
      int* buf[2] = {
    108
    3.47k
        buf0, buf1
    109
    3.47k
      };
    110
    3.47k
      int buf_size[2] = {
    111
    3.47k
        1, 0
    112
    3.47k
      };
    113
    3.47k
      int p = 0, q = 1;
    114
    3.47k
      int i, j, k;
    115
    3.47k
      int flag = 0;
    116
    15.7k
      while (buf_size[p] > 0)
    117
    12.3k
      {
    118
    12.3k
        buf_size[q] = 0;
    119
    24.6k
        for (i = 0; i < buf_size[p]; i++12.3k)
    120
    12.3k
        {
    121
    12.3k
          const int* outgoings; int outgoing_size;
    122
    12.3k
          ccv_nnc_graph_exec_symbol_to(graph, (ccv_nnc_graph_exec_symbol_t){
    123
    12.3k
            .d = buf[p][i],
    124
    12.3k
            .graph = graph
    125
    12.3k
          }, &outgoings, &outgoing_size);
    126
    21.1k
          for (j = 0; j < outgoing_size; j++8.85k)
    127
    8.85k
          {
    128
    8.85k
            const int outgoing_idx = outgoings[j];
    129
    8.93k
            for (k = 0; k < sources->rnum; k++85)
    130
    85
            {
    131
    85
              ccv_nnc_graph_exec_symbol_t* const source_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, k);
    132
              // If this outgoing idx is one of the source, replace it with d, or delete it.
    133
    85
              if (source_symbol->d == outgoing_idx)
    134
    0
              {
    135
    0
                if (!flag)
    136
    0
                {
    137
    0
                  source_symbol->d = d;
    138
    0
                  flag = 1;
    139
    0
                } else {
    140
                  // Delete this from the list.
    141
    0
                  if (k < sources->rnum - 1)
    142
    0
                    source_symbol->d = ((ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, sources->rnum - 1))->d;
    143
    0
                  --sources->rnum;
    144
    0
                }
    145
    0
                break;
    146
    0
              }
    147
    85
            }
    148
    8.85k
            if (visited[(outgoing_idx >> 5)] & (1u << (outgoing_idx & 31)))
    149
    19
              continue;
    150
    8.83k
            visited[(outgoing_idx >> 5)] |= (1u << (outgoing_idx & 31));
    151
    8.83k
            buf[q][buf_size[q]] = outgoing_idx;
    152
    8.83k
            ++buf_size[q];
    153
    8.83k
          }
    154
    12.3k
        }
    155
    12.3k
        CCV_SWAP(p, q, i);
    156
    12.3k
      }
    157
      // If this node is not visited, and we cannot find anything in the sources to replace, this is a new top node.
    158
    3.47k
      if (!flag)
    159
    3.47k
      {
    160
    3.47k
        const ccv_nnc_graph_exec_symbol_t source_symbol = {
    161
    3.47k
          .d = d,
    162
    3.47k
          .graph = graph
    163
    3.47k
        };
    164
    3.47k
        ccv_array_push(sources, &source_symbol);
    165
    3.47k
      }
    166
    3.47k
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph_apply_gradients.c:ccv_nnc_insert_if_prior_to_any

    ccv_nnc_dynamic_graph_minimize.c:ccv_nnc_insert_if_prior_to_any

    Line
    Count
    Source
    102
    1.00k
    {
    103
    1.00k
      if (visited[(d >> 5)] & (1u << (d & 31)))
    104
    0
        return;
    105
    1.00k
      visited[(d >> 5)] |= (1u << (d & 31));
    106
    1.00k
      buf0[0] = d;
    107
    1.00k
      int* buf[2] = {
    108
    1.00k
        buf0, buf1
    109
    1.00k
      };
    110
    1.00k
      int buf_size[2] = {
    111
    1.00k
        1, 0
    112
    1.00k
      };
    113
    1.00k
      int p = 0, q = 1;
    114
    1.00k
      int i, j, k;
    115
    1.00k
      int flag = 0;
    116
    4.00k
      while (buf_size[p] > 0)
    117
    3.00k
      {
    118
    3.00k
        buf_size[q] = 0;
    119
    6.00k
        for (i = 0; i < buf_size[p]; i++3.00k)
    120
    3.00k
        {
    121
    3.00k
          const int* outgoings; int outgoing_size;
    122
    3.00k
          ccv_nnc_graph_exec_symbol_to(graph, (ccv_nnc_graph_exec_symbol_t){
    123
    3.00k
            .d = buf[p][i],
    124
    3.00k
            .graph = graph
    125
    3.00k
          }, &outgoings, &outgoing_size);
    126
    5.00k
          for (j = 0; j < outgoing_size; j++2.00k)
    127
    2.00k
          {
    128
    2.00k
            const int outgoing_idx = outgoings[j];
    129
    2.00k
            for (k = 0; k < sources->rnum; k++0)
    130
    0
            {
    131
    0
              ccv_nnc_graph_exec_symbol_t* const source_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, k);
    132
              // If this outgoing idx is one of the source, replace it with d, or delete it.
    133
    0
              if (source_symbol->d == outgoing_idx)
    134
    0
              {
    135
    0
                if (!flag)
    136
    0
                {
    137
    0
                  source_symbol->d = d;
    138
    0
                  flag = 1;
    139
    0
                } else {
    140
                  // Delete this from the list.
    141
    0
                  if (k < sources->rnum - 1)
    142
    0
                    source_symbol->d = ((ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, sources->rnum - 1))->d;
    143
    0
                  --sources->rnum;
    144
    0
                }
    145
    0
                break;
    146
    0
              }
    147
    0
            }
    148
    2.00k
            if (visited[(outgoing_idx >> 5)] & (1u << (outgoing_idx & 31)))
    149
    0
              continue;
    150
    2.00k
            visited[(outgoing_idx >> 5)] |= (1u << (outgoing_idx & 31));
    151
    2.00k
            buf[q][buf_size[q]] = outgoing_idx;
    152
    2.00k
            ++buf_size[q];
    153
    2.00k
          }
    154
    3.00k
        }
    155
    3.00k
        CCV_SWAP(p, q, i);
    156
    3.00k
      }
    157
      // If this node is not visited, and we cannot find anything in the sources to replace, this is a new top node.
    158
    1.00k
      if (!flag)
    159
    1.00k
      {
    160
    1.00k
        const ccv_nnc_graph_exec_symbol_t source_symbol = {
    161
    1.00k
          .d = d,
    162
    1.00k
          .graph = graph
    163
    1.00k
        };
    164
    1.00k
        ccv_array_push(sources, &source_symbol);
    165
    1.00k
      }
    166
    1.00k
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_nnc_insert_if_prior_to_any
    167
    168
    static inline void ccv_nnc_remove_if_prior_to_any(const ccv_nnc_symbolic_graph_t* const graph, const int d, ccv_array_t* const destinations, uint32_t* const visited, int* const buf0, int* const buf1)
    169
    22
    {
    170
    22
      int i, j, k;
    171
      // If it is already visited, this is the later one, we are good.
    172
    22
      if (visited[(d >> 5)] & (1u << (d & 31)))
    173
    0
        return;
    174
    22
      visited[(d >> 5)] |= (1u << (d & 31));
    175
    22
      buf0[0] = d;
    176
    22
      int* buf[2] = {
    177
    22
        buf0, buf1
    178
    22
      };
    179
    22
      int buf_size[2] = {
    180
    22
        1, 0
    181
    22
      };
    182
    22
      int p = 0, q = 1;
    183
    22
      int flag = 0;
    184
    44
      while (!flag && buf_size[p] > 042)
    185
    22
      {
    186
    22
        buf_size[q] = 0;
    187
    44
        for (i = 0; !flag && i < buf_size[p]42; i++22)
    188
    22
        {
    189
    22
          const int* outgoings; int outgoing_size;
    190
    22
          ccv_nnc_graph_exec_symbol_to(graph, (ccv_nnc_graph_exec_symbol_t){
    191
    22
            .d = buf[p][i],
    192
    22
            .graph = graph
    193
    22
          }, &outgoings, &outgoing_size);
    194
    25
          for (j = 0; j < outgoing_size; j++3)
    195
    3
          {
    196
    3
            const int outgoing_idx = outgoings[j];
    197
            // If this node happens to be visited, do nothing.
    198
    3
            if (visited[(outgoing_idx >> 5)] & (1u << (outgoing_idx & 31)))
    199
    0
              continue;
    200
    6
            for (k = 0; 3!flag && k < destinations->rnum3; k++3)
    201
    3
            {
    202
    3
              ccv_nnc_graph_exec_symbol_t* const destination_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, k);
    203
              // If this outgoing idx is one of the destination, delete current node.
    204
    3
              flag = (destination_symbol->d == outgoing_idx);
    205
    3
            }
    206
    3
            visited[(outgoing_idx >> 5)] |= (1u << (outgoing_idx & 31));
    207
    3
            buf[q][buf_size[q]] = outgoing_idx;
    208
    3
            ++buf_size[q];
    209
    3
          }
    210
    22
        }
    211
    22
        CCV_SWAP(p, q, i);
    212
    22
      }
    213
    22
      if (flag)
    214
    3
        for (i = 0; 2i < destinations->rnum; i++1)
    215
    3
        {
    216
    3
          ccv_nnc_graph_exec_symbol_t* const destination_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, i);
    217
          // If this outgoing idx is one of the destination, delete current node.
    218
    3
          if (destination_symbol->d == d)
    219
    2
          {
    220
            // Delete this from the list.
    221
    2
            if (i < destinations->rnum - 1)
    222
    1
              destination_symbol->d = ((ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, destinations->rnum - 1))->d;
    223
    2
            --destinations->rnum;
    224
    2
            break;
    225
    2
          }
    226
    3
        }
    227
    22
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph.c:ccv_nnc_remove_if_prior_to_any
    Unexecuted instantiation: ccv_nnc_dynamic_graph_alloc.c:ccv_nnc_remove_if_prior_to_any

    ccv_nnc_dynamic_graph_backward.c:ccv_nnc_remove_if_prior_to_any

    Line
    Count
    Source
    169
    18
    {
    170
    18
      int i, j, k;
    171
      // If it is already visited, this is the later one, we are good.
    172
    18
      if (visited[(d >> 5)] & (1u << (d & 31)))
    173
    0
        return;
    174
    18
      visited[(d >> 5)] |= (1u << (d & 31));
    175
    18
      buf0[0] = d;
    176
    18
      int* buf[2] = {
    177
    18
        buf0, buf1
    178
    18
      };
    179
    18
      int buf_size[2] = {
    180
    18
        1, 0
    181
    18
      };
    182
    18
      int p = 0, q = 1;
    183
    18
      int flag = 0;
    184
    36
      while (!flag && buf_size[p] > 034)
    185
    18
      {
    186
    18
        buf_size[q] = 0;
    187
    36
        for (i = 0; !flag && i < buf_size[p]34; i++18)
    188
    18
        {
    189
    18
          const int* outgoings; int outgoing_size;
    190
    18
          ccv_nnc_graph_exec_symbol_to(graph, (ccv_nnc_graph_exec_symbol_t){
    191
    18
            .d = buf[p][i],
    192
    18
            .graph = graph
    193
    18
          }, &outgoings, &outgoing_size);
    194
    21
          for (j = 0; j < outgoing_size; j++3)
    195
    3
          {
    196
    3
            const int outgoing_idx = outgoings[j];
    197
            // If this node happens to be visited, do nothing.
    198
    3
            if (visited[(outgoing_idx >> 5)] & (1u << (outgoing_idx & 31)))
    199
    0
              continue;
    200
    6
            for (k = 0; 3!flag && k < destinations->rnum3; k++3)
    201
    3
            {
    202
    3
              ccv_nnc_graph_exec_symbol_t* const destination_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, k);
    203
              // If this outgoing idx is one of the destination, delete current node.
    204
    3
              flag = (destination_symbol->d == outgoing_idx);
    205
    3
            }
    206
    3
            visited[(outgoing_idx >> 5)] |= (1u << (outgoing_idx & 31));
    207
    3
            buf[q][buf_size[q]] = outgoing_idx;
    208
    3
            ++buf_size[q];
    209
    3
          }
    210
    18
        }
    211
    18
        CCV_SWAP(p, q, i);
    212
    18
      }
    213
    18
      if (flag)
    214
    3
        for (i = 0; 2i < destinations->rnum; i++1)
    215
    3
        {
    216
    3
          ccv_nnc_graph_exec_symbol_t* const destination_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, i);
    217
          // If this outgoing idx is one of the destination, delete current node.
    218
    3
          if (destination_symbol->d == d)
    219
    2
          {
    220
            // Delete this from the list.
    221
    2
            if (i < destinations->rnum - 1)
    222
    1
              destination_symbol->d = ((ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, destinations->rnum - 1))->d;
    223
    2
            --destinations->rnum;
    224
    2
            break;
    225
    2
          }
    226
    3
        }
    227
    18
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph_apply_gradients.c:ccv_nnc_remove_if_prior_to_any

    ccv_nnc_dynamic_graph_minimize.c:ccv_nnc_remove_if_prior_to_any

    Line
    Count
    Source
    169
    4
    {
    170
    4
      int i, j, k;
    171
      // If it is already visited, this is the later one, we are good.
    172
    4
      if (visited[(d >> 5)] & (1u << (d & 31)))
    173
    0
        return;
    174
    4
      visited[(d >> 5)] |= (1u << (d & 31));
    175
    4
      buf0[0] = d;
    176
    4
      int* buf[2] = {
    177
    4
        buf0, buf1
    178
    4
      };
    179
    4
      int buf_size[2] = {
    180
    4
        1, 0
    181
    4
      };
    182
    4
      int p = 0, q = 1;
    183
    4
      int flag = 0;
    184
    8
      while (!flag && buf_size[p] > 0)
    185
    4
      {
    186
    4
        buf_size[q] = 0;
    187
    8
        for (i = 0; !flag && i < buf_size[p]; i++4)
    188
    4
        {
    189
    4
          const int* outgoings; int outgoing_size;
    190
    4
          ccv_nnc_graph_exec_symbol_to(graph, (ccv_nnc_graph_exec_symbol_t){
    191
    4
            .d = buf[p][i],
    192
    4
            .graph = graph
    193
    4
          }, &outgoings, &outgoing_size);
    194
    4
          for (j = 0; j < outgoing_size; j++0)
    195
    0
          {
    196
    0
            const int outgoing_idx = outgoings[j];
    197
            // If this node happens to be visited, do nothing.
    198
    0
            if (visited[(outgoing_idx >> 5)] & (1u << (outgoing_idx & 31)))
    199
    0
              continue;
    200
    0
            for (k = 0; !flag && k < destinations->rnum; k++)
    201
    0
            {
    202
    0
              ccv_nnc_graph_exec_symbol_t* const destination_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, k);
    203
              // If this outgoing idx is one of the destination, delete current node.
    204
    0
              flag = (destination_symbol->d == outgoing_idx);
    205
    0
            }
    206
    0
            visited[(outgoing_idx >> 5)] |= (1u << (outgoing_idx & 31));
    207
    0
            buf[q][buf_size[q]] = outgoing_idx;
    208
    0
            ++buf_size[q];
    209
    0
          }
    210
    4
        }
    211
    4
        CCV_SWAP(p, q, i);
    212
    4
      }
    213
    4
      if (flag)
    214
    0
        for (i = 0; i < destinations->rnum; i++)
    215
    0
        {
    216
    0
          ccv_nnc_graph_exec_symbol_t* const destination_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, i);
    217
          // If this outgoing idx is one of the destination, delete current node.
    218
    0
          if (destination_symbol->d == d)
    219
    0
          {
    220
            // Delete this from the list.
    221
    0
            if (i < destinations->rnum - 1)
    222
    0
              destination_symbol->d = ((ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, destinations->rnum - 1))->d;
    223
    0
            --destinations->rnum;
    224
    0
            break;
    225
    0
          }
    226
    0
        }
    227
    4
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_nnc_remove_if_prior_to_any
    228
    229
    typedef struct {
    230
      int type;
    231
      int d;
    232
    } ccv_nnc_tape_symbol_t;
    233
    234
    static inline void ccv_nnc_dynamic_graph_push_backward_tensor_symbol(void* context, const ccv_nnc_tensor_symbol_t symbol, const ccv_nnc_tensor_param_t info, const char* const name)
    235
    40.9k
    {
    236
    40.9k
      ccv_array_t* const stack = (ccv_array_t*)context;
    237
    40.9k
      ccv_nnc_tape_symbol_t tape_symbol = {
    238
    40.9k
        .d = symbol.d,
    239
    40.9k
        .type = CCV_NNC_SYMBOL_TENSOR,
    240
    40.9k
      };
    241
    40.9k
      ccv_array_push(stack, &tape_symbol);
    242
    40.9k
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol
    Unexecuted instantiation: ccv_nnc_dynamic_graph_alloc.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol

    ccv_nnc_dynamic_graph_backward.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol

    Line
    Count
    Source
    235
    26.1k
    {
    236
    26.1k
      ccv_array_t* const stack = (ccv_array_t*)context;
    237
    26.1k
      ccv_nnc_tape_symbol_t tape_symbol = {
    238
    26.1k
        .d = symbol.d,
    239
    26.1k
        .type = CCV_NNC_SYMBOL_TENSOR,
    240
    26.1k
      };
    241
    26.1k
      ccv_array_push(stack, &tape_symbol);
    242
    26.1k
    }

    ccv_nnc_dynamic_graph_apply_gradients.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol

    Line
    Count
    Source
    235
    5.73k
    {
    236
    5.73k
      ccv_array_t* const stack = (ccv_array_t*)context;
    237
    5.73k
      ccv_nnc_tape_symbol_t tape_symbol = {
    238
    5.73k
        .d = symbol.d,
    239
    5.73k
        .type = CCV_NNC_SYMBOL_TENSOR,
    240
    5.73k
      };
    241
    5.73k
      ccv_array_push(stack, &tape_symbol);
    242
    5.73k
    }

    ccv_nnc_dynamic_graph_minimize.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol

    Line
    Count
    Source
    235
    9.01k
    {
    236
    9.01k
      ccv_array_t* const stack = (ccv_array_t*)context;
    237
    9.01k
      ccv_nnc_tape_symbol_t tape_symbol = {
    238
    9.01k
        .d = symbol.d,
    239
    9.01k
        .type = CCV_NNC_SYMBOL_TENSOR,
    240
    9.01k
      };
    241
    9.01k
      ccv_array_push(stack, &tape_symbol);
    242
    9.01k
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol
    243
    244
    static inline void ccv_nnc_dynamic_graph_push_backward_tensor_symbol_alias(void* context, const ccv_nnc_tensor_symbol_t symbol, const ccv_nnc_tensor_symbol_t from_symbol, const int ofs[CCV_NNC_MAX_DIM_ALLOC], const int stride[CCV_NNC_MAX_DIM_ALLOC], const ccv_nnc_tensor_param_t info, const char* const name)
    245
    1.01k
    {
    246
    1.01k
      ccv_array_t* const stack = (ccv_array_t*)context;
    247
    1.01k
      ccv_nnc_tape_symbol_t tape_symbol = {
    248
    1.01k
        .d = symbol.d,
    249
    1.01k
        .type = CCV_NNC_SYMBOL_TENSOR_ALIAS,
    250
    1.01k
      };
    251
    1.01k
      ccv_array_push(stack, &tape_symbol);
    252
    1.01k
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol_alias
    Unexecuted instantiation: ccv_nnc_dynamic_graph_alloc.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol_alias

    ccv_nnc_dynamic_graph_backward.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol_alias

    Line
    Count
    Source
    245
    1.01k
    {
    246
    1.01k
      ccv_array_t* const stack = (ccv_array_t*)context;
    247
    1.01k
      ccv_nnc_tape_symbol_t tape_symbol = {
    248
    1.01k
        .d = symbol.d,
    249
    1.01k
        .type = CCV_NNC_SYMBOL_TENSOR_ALIAS,
    250
    1.01k
      };
    251
    1.01k
      ccv_array_push(stack, &tape_symbol);
    252
    1.01k
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph_apply_gradients.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol_alias
    Unexecuted instantiation: ccv_nnc_dynamic_graph_minimize.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol_alias
    Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol_alias
    253
    254
    static inline void ccv_nnc_dynamic_graph_push_backward_graph_exec_symbol(void* context, const ccv_nnc_graph_exec_symbol_t symbol, const ccv_nnc_cmd_t cmd, const ccv_nnc_tensor_symbol_t* const inputs, const int input_size, const ccv_nnc_tensor_symbol_t* const outputs, const int output_size, const char* const name)
    255
    23.9k
    {
    256
    23.9k
      ccv_array_t* const stack = (ccv_array_t*)context;
    257
    23.9k
      ccv_nnc_tape_symbol_t tape_symbol = {
    258
    23.9k
        .d = symbol.d,
    259
    23.9k
        .type = CCV_NNC_SYMBOL_GRAPH_EXEC,
    260
    23.9k
      };
    261
    23.9k
      ccv_array_push(stack, &tape_symbol);
    262
    23.9k
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph.c:ccv_nnc_dynamic_graph_push_backward_graph_exec_symbol
    Unexecuted instantiation: ccv_nnc_dynamic_graph_alloc.c:ccv_nnc_dynamic_graph_push_backward_graph_exec_symbol

    ccv_nnc_dynamic_graph_backward.c:ccv_nnc_dynamic_graph_push_backward_graph_exec_symbol

    Line
    Count
    Source
    255
    17.4k
    {
    256
    17.4k
      ccv_array_t* const stack = (ccv_array_t*)context;
    257
    17.4k
      ccv_nnc_tape_symbol_t tape_symbol = {
    258
    17.4k
        .d = symbol.d,
    259
    17.4k
        .type = CCV_NNC_SYMBOL_GRAPH_EXEC,
    260
    17.4k
      };
    261
    17.4k
      ccv_array_push(stack, &tape_symbol);
    262
    17.4k
    }

    ccv_nnc_dynamic_graph_apply_gradients.c:ccv_nnc_dynamic_graph_push_backward_graph_exec_symbol

    Line
    Count
    Source
    255
    1.44k
    {
    256
    1.44k
      ccv_array_t* const stack = (ccv_array_t*)context;
    257
    1.44k
      ccv_nnc_tape_symbol_t tape_symbol = {
    258
    1.44k
        .d = symbol.d,
    259
    1.44k
        .type = CCV_NNC_SYMBOL_GRAPH_EXEC,
    260
    1.44k
      };
    261
    1.44k
      ccv_array_push(stack, &tape_symbol);
    262
    1.44k
    }

    ccv_nnc_dynamic_graph_minimize.c:ccv_nnc_dynamic_graph_push_backward_graph_exec_symbol

    Line
    Count
    Source
    255
    5.01k
    {
    256
    5.01k
      ccv_array_t* const stack = (ccv_array_t*)context;
    257
    5.01k
      ccv_nnc_tape_symbol_t tape_symbol = {
    258
    5.01k
        .d = symbol.d,
    259
    5.01k
        .type = CCV_NNC_SYMBOL_GRAPH_EXEC,
    260
    5.01k
      };
    261
    5.01k
      ccv_array_push(stack, &tape_symbol);
    262
    5.01k
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_nnc_dynamic_graph_push_backward_graph_exec_symbol
    263
    264
    static inline int ccv_nnc_tensor_variable_contains_value(ccv_nnc_tensor_variable_t const tensor_variable)
    265
    4.68k
    {
    266
      // A tensor variable contains value only if it has a tensor view, and these tensor view is not external bind without a symbol (thus, freshly external bind).
    267
    4.68k
      return tensor_variable->tensor_view && (3.40k!3.40kCCV_NNC_IS_EXTERN_TENSOR_VIEW3.40k(tensor_variable->tensor_view) || tensor_variable->symbol.d >= 01);
    268
    4.68k
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph.c:ccv_nnc_tensor_variable_contains_value
    Unexecuted instantiation: ccv_nnc_dynamic_graph_alloc.c:ccv_nnc_tensor_variable_contains_value

    ccv_nnc_dynamic_graph_backward.c:ccv_nnc_tensor_variable_contains_value

    Line
    Count
    Source
    265
    3.25k
    {
    266
      // A tensor variable contains value only if it has a tensor view, and these tensor view is not external bind without a symbol (thus, freshly external bind).
    267
    3.25k
      return tensor_variable->tensor_view && (2.00k!2.00kCCV_NNC_IS_EXTERN_TENSOR_VIEW2.00k(tensor_variable->tensor_view) || tensor_variable->symbol.d >= 01);
    268
    3.25k
    }

    ccv_nnc_dynamic_graph_apply_gradients.c:ccv_nnc_tensor_variable_contains_value

    Line
    Count
    Source
    265
    1.43k
    {
    266
      // A tensor variable contains value only if it has a tensor view, and these tensor view is not external bind without a symbol (thus, freshly external bind).
    267
    1.43k
      return tensor_variable->tensor_view && (1.40k!1.40kCCV_NNC_IS_EXTERN_TENSOR_VIEW1.40k(tensor_variable->tensor_view) || tensor_variable->symbol.d >= 00);
    268
    1.43k
    }
    Unexecuted instantiation: ccv_nnc_dynamic_graph_minimize.c:ccv_nnc_tensor_variable_contains_value
    Unexecuted instantiation: ccv_nnc_dynamic_graph_evaluate.c:ccv_nnc_tensor_variable_contains_value
    269
    270
    void ccv_nnc_dynamic_graph_exec_ret(ccv_nnc_dynamic_graph_t* const graph, const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, const ccv_nnc_tensor_variable_t* const inputs, const int input_size, ccv_nnc_tensor_variable_t* const outputs, const int output_size, const int parallel, ccv_nnc_stream_context_t* const stream_context, ccv_nnc_graph_exec_symbol_t* const graph_execs);
    271
    272
    extern const ccv_nnc_symbolic_graph_compile_allocator_vtab_t ccv_nnc_dy_allocator_isa;
    273
    274
    typedef struct {
    275
      ccv_nnc_graph_t* graph;
    276
      ccv_nnc_tensor_arena_t* tensor_arena;
    277
      ccv_nnc_graph_exec_arena_t* exec_arena;
    278
    } ccv_nnc_compilation_artifact_t;
    279
    280
    ccv_nnc_compilation_artifact_t* ccv_nnc_compilation_artifact_new(ccv_nnc_graph_t* const graph, ccv_nnc_tensor_arena_t* const tensor_arena, ccv_nnc_graph_exec_arena_t* const exec_arena);
    281
    void ccv_nnc_compilation_artifact_free(ccv_nnc_compilation_artifact_t* const artifact);
    282
    283
    #endif