## Coverage Report

#### Created: 2026-04-17 07:37

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

    /home/liu/actions-runner/_work/ccv/ccv/lib/nnc/_ccv_nnc_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_graph_internal_h
    11
    #define GUARD_ccv_nnc_graph_internal_h
    12
    13
    #include "ccv_nnc.h"
    14
    15
    #include "_ccv_nnc_stream.h"
    16
    #include "3rdparty/khash/khash.h"
    17
    18
    typedef struct {
    19
      int update_required;
    20
      int count;
    21
      int index;
    22
      ccv_nnc_tensor_t* tensors[1];
    23
    } ccv_nnc_graph_tensor_wrap_t;
    24
    25
    typedef struct {
    26
      int size;
    27
      ccv_nnc_graph_tensor_wrap_t* tensor_wraps[1];
    28
    } ccv_nnc_graph_tensor_wrap_array_t;
    29
    30
    typedef struct {
    31
      int stream_size; // This controls the size of both _heap_signals and _heap_streams. When this is <= 1, we don't have _heap variant.
    32
      union {
    33
        int _inline_signals[1];
    34
        int* _heap_signals;
    35
      };
    36
      union {
    37
        int _inline_streams[1]; // The assigned stream for this to be executed.
    38
        int* _heap_streams;
    39
      };
    40
      int wait_size;
    41
      int* waits;
    42
    } ccv_nnc_graph_exec_schedule_t;
    43
    44
    struct ccv_nnc_graph_static_schedule_s {
    45
      int exec_info_size;
    46
      int psort_size;
    47
      int wait_size;
    48
      int stream_0;
    49
      int stream_1_size;
    50
      int* stream_1s; // The default stream will begin these signals on start.
    51
      int* waits; // The default stream will wait on these signals to be done.
    52
      int* psort; // If the graph is not topsorted, I will re-index it. Only applicable for partial scheduling.
    53
      ccv_nnc_stream_signal_t* begin; // This signal is created so that internal stream_1s can sync with stream_0.
    54
      ccv_nnc_stream_signal_t* end; // This signal is created so that outside provided stream can be synced with the stream_0.
    55
      ccv_nnc_graph_exec_schedule_t exec_info[1];
    56
    };
    57
    58
    typedef struct {
    59
      int input_size;
    60
      int output_size;
    61
      int flags;
    62
      int pair_ref; // Reference to its pair. Starts at 1.
    63
      int graph_ref_size;
    64
      int update_size;
    65
      int tensor_wraps_ref; // Reference to the tensor_wraps in the graph. Starts at 1.
    66
      ccv_nnc_tensor_t** inputs;
    67
      int* input_flags;
    68
      ccv_nnc_tensor_t** outputs;
    69
      int* output_flags;
    70
      ccv_array_t* outgoings; // outgoing nodes
    71
      intptr_t alias_ref; // Link to some reference data.
    72
      ccv_nnc_cmd_t cmd;
    73
      ccv_nnc_hint_t hint;
    74
      // These correlates to tensors that need to be unwrapped, but not in either inputs / outputs (thus, only relevant if this graph exec symbol points to a sub-graph.)
    75
      ccv_nnc_tensor_t** updates;
    76
      // Below are only relevant to sub-graph nodes (case_of, while).
    77
      int _inline_graph_ref[2]; // Reference to the sub-graph. Starts at 1.
    78
      int* _heap_graph_ref;
    79
      union {
    80
        struct {
    81
          ccv_nnc_graph_case_of_f expr;
    82
          const void* data;
    83
          int offset;
    84
        } case_of;
    85
        struct {
    86
          ccv_nnc_graph_while_f expr;
    87
          const void* data;
    88
          ccv_nnc_tensor_t** inputs;
    89
          int input_size;
    90
          int tensor_wraps_ref;
    91
        } p_while;
    92
      };
    93
    } ccv_nnc_graph_exec_info_t;
    94
    95
    321k
    #define SCHEDULE_SIGNALS(node) ((node).stream_size <= 1 ? (node)._inline_signals306k : (node)._heap_signals15.1k)
    96
    843k
    #define SCHEDULE_STREAMS(node) ((node).stream_size <= 1 ? (node)._inline_streams776k : (node)._heap_streams67.2k)
    97
    98
    // This struct is used to move pointers from "from" to "to". This is used to bridge between the current loop
    99
    // and the next one. These tensor trees wraps / unwraps follow the conventional tree_execs, but of a graph.
    100
    // At the end of an iteration, before rewrap, the pointer from "from" tensor will be moved to transit. At the
    101
    // beginning of the next iteration, after unwrap, the pointer from transit will be moved to "to" tensor.
    102
    typedef struct {
    103
      ccv_nnc_graph_tensor_wrap_t* to;
    104
      ccv_numeric_data_t transit;
    105
      ccv_nnc_graph_tensor_wrap_t* from;
    106
    } ccv_nnc_graph_tensor_carry_over_t;
    107
    108
    typedef struct {
    109
      int d;
    110
      ccv_nnc_graph_t* graph;
    111
    } ccv_nnc_graph_tensor_wraps_ref_t;
    112
    113
    enum {
    114
      CCV_NNC_GRAPH_STATE_IDLE = 0,
    115
      CCV_NNC_GRAPH_STATE_RUNNING = 1,
    116
      CCV_NNC_GRAPH_STATE_CANCEL = 2,
    117
    };
    118
    119
    struct ccv_nnc_graph_s {
    120
      int p_idx; // Reference to the index in its parent graph's sub-graph array, Starts at 1.
    121
      int exec_idx; // Reference to the index in its parent graph's exec (the graph exec), Starts at 1.
    122
      int topsorted; // Whether this graph is ordered sequentially.
    123
      int breakpoint_offset; // If the graph is sorted, offset denotes the first node that is the breakpoint.
    124
      int breakpoint_size;
    125
      int stream_size;
    126
      int signal_size;
    127
      int buffer_size;
    128
      int run_state;
    129
      ccv_array_t* exec_info; // deferred exec info
    130
      // I think that I can be more explicit about which are sources and which are destinations.
    131
      // These are int types.
    132
      ccv_array_t* sources;
    133
      ccv_array_t* destinations;
    134
      // streams, signals, and waits are used to coordinate multi-stream graph run (several nodes can execute
    135
      // concurrently).
    136
      ccv_nnc_stream_context_t** streams; // Preallocated several streams for use, Default stream will be stream 0.
    137
      co_routine_t** block_stream_tasks; // Used to keep list of tasks that blocked current stream.
    138
      ccv_nnc_stream_signal_t** signals; // Preallocated several signals for use.
    139
      ccv_nnc_graph_static_schedule_t* default_schedule; // The schedule for the whole graph.
    140
      // Buffer that can be used during graph run, in steady state when run graph (with topsorted), it won't have
    141
      // any heap allocations (the usage of buffer first will, but subsequent runs won't).
    142
      void* buffer;
    143
      // Extra information for all tensors that need to be unwrapped.
    144
      ccv_array_t* tensor_wraps; // It contains a ccv_nnc_graph_tensor_wrap_array_t struct.
    145
      ccv_array_t* tensor_wraps_refs; // It contains a ccv_nnc_graph_tensor_wrap_ref_t struct that references to all tensor wraps need to be unwrapped (including all sub-graphs).
    146
      // Some extra information piggy-back on graph struct.
    147
      struct ccv_nnc_graph_s* p; // The parent graph (if current one is a sub-graph).
    148
      struct ccv_nnc_graph_s* pair; // The pair graph (only useful for backward prop graph).
    149
      ccv_array_t* sub_graphs; // A list of its sub-graphs (for while loop).
    150
      // Why some of these I choose to be flat * array, some of these I choose to be ccv_array_t?
    151
      // for flat * array, these are not going to be modified until next time call ccv_nnc_symbolic_graph_backward
    152
      // for ccv_array_t, we can continue to modify what's inside.
    153
      int64_t while_count;
    154
      ccv_nnc_graph_exec_t* breakpoints;
    155
      // End of while loop handling.
    156
      // Extra metadata, useful when we don't want extra memory allocation.
    157
      ccv_array_t* carry_overs; // The array of tensor carry_overs.
    158
    };
    159
    160
    inline static int ccv_array_find_int(ccv_array_t* ints, const int idx)
    161
    427
    {
    162
    427
      int i;
    163
    1.27k
      for (i = 0; i < ints->rnum; i++849)
    164
    849
        if (*(int*)ccv_array_get(ints, i) == idx)
    165
    0
          return 1;
    166
    427
      return 0;
    167
    427
    }
    Unexecuted instantiation: tape.tests.c:ccv_array_find_int
    Unexecuted instantiation: while.backward.tests.c:ccv_array_find_int

    ccv_nnc_graph.c:ccv_array_find_int

    Line
    Count
    Source
    161
    427
    {
    162
    427
      int i;
    163
    1.27k
      for (i = 0; i < ints->rnum; i++849)
    164
    849
        if (*(int*)ccv_array_get(ints, i) == idx)
    165
    0
          return 1;
    166
    427
      return 0;
    167
    427
    }
    Unexecuted instantiation: ccv_nnc_symbolic_graph_compile.c:ccv_array_find_int
    Unexecuted instantiation: ccv_nnc_graph_while.c:ccv_array_find_int
    Unexecuted instantiation: ccv_nnc_tensor_tape.c:ccv_array_find_int
    Unexecuted instantiation: ccv_nnc_graph_case_of.c:ccv_array_find_int
    Unexecuted instantiation: ccv_nnc_graph_run.c:ccv_array_find_int
    Unexecuted instantiation: ccv_cnnp_model.c:ccv_array_find_int
    168
    169
    inline static int ccv_array_find_uint(ccv_array_t* ints, const uint32_t idx)
    170
    153
    {
    171
    153
      int i;
    172
    355
      for (i = 0; i < ints->rnum; i++202)
    173
    270
        if (*(uint32_t*)ccv_array_get(ints, i) == idx)
    174
    68
          return 1;
    175
    85
      return 0;
    176
    153
    }
    Unexecuted instantiation: tape.tests.c:ccv_array_find_uint
    Unexecuted instantiation: while.backward.tests.c:ccv_array_find_uint

    ccv_nnc_graph.c:ccv_array_find_uint

    Line
    Count
    Source
    170
    153
    {
    171
    153
      int i;
    172
    355
      for (i = 0; i < ints->rnum; i++202)
    173
    270
        if (*(uint32_t*)ccv_array_get(ints, i) == idx)
    174
    68
          return 1;
    175
    85
      return 0;
    176
    153
    }
    Unexecuted instantiation: ccv_nnc_symbolic_graph_compile.c:ccv_array_find_uint
    Unexecuted instantiation: ccv_nnc_graph_while.c:ccv_array_find_uint
    Unexecuted instantiation: ccv_nnc_tensor_tape.c:ccv_array_find_uint
    Unexecuted instantiation: ccv_nnc_graph_case_of.c:ccv_array_find_uint
    Unexecuted instantiation: ccv_nnc_graph_run.c:ccv_array_find_uint
    Unexecuted instantiation: ccv_cnnp_model.c:ccv_array_find_uint
    177
    178
    inline static int ccv_nnc_tensors_have_wraps(ccv_nnc_tensor_t* const* const tensors, const int tensor_size)
    179
    97.9k
    {
    180
    97.9k
      int i;
    181
    239k
      for (i = 0; i < tensor_size; i++141k)
    182
    141k
        if (tensors[i] &&
    183
    141k
          CCV_IS_TENSOR_MULTIVIEW106k(tensors[i]) &&
    184
    141k
          ((ccv_nnc_tensor_multiview_t*)tensors[i])->anchor != 71CCV_NNC_MULTIVIEW_PHI71)
    185
    62
          return 1;
    186
    97.8k
      return 0;
    187
    97.9k
    }
    Unexecuted instantiation: tape.tests.c:ccv_nnc_tensors_have_wraps
    Unexecuted instantiation: while.backward.tests.c:ccv_nnc_tensors_have_wraps

    ccv_nnc_graph.c:ccv_nnc_tensors_have_wraps

    Line
    Count
    Source
    179
    97.9k
    {
    180
    97.9k
      int i;
    181
    239k
      for (i = 0; i < tensor_size; i++141k)
    182
    141k
        if (tensors[i] &&
    183
    141k
          CCV_IS_TENSOR_MULTIVIEW106k(tensors[i]) &&
    184
    141k
          ((ccv_nnc_tensor_multiview_t*)tensors[i])->anchor != 70CCV_NNC_MULTIVIEW_PHI70)
    185
    61
          return 1;
    186
    97.8k
      return 0;
    187
    97.9k
    }
    Unexecuted instantiation: ccv_nnc_symbolic_graph_compile.c:ccv_nnc_tensors_have_wraps

    ccv_nnc_graph_while.c:ccv_nnc_tensors_have_wraps

    Line
    Count
    Source
    179
    23
    {
    180
    23
      int i;
    181
    48
      for (i = 0; i < tensor_size; i++25)
    182
    26
        if (tensors[i] &&
    183
    26
          CCV_IS_TENSOR_MULTIVIEW(tensors[i]) &&
    184
    26
          ((ccv_nnc_tensor_multiview_t*)tensors[i])->anchor != 1CCV_NNC_MULTIVIEW_PHI1)
    185
    1
          return 1;
    186
    22
      return 0;
    187
    23
    }
    Unexecuted instantiation: ccv_nnc_tensor_tape.c:ccv_nnc_tensors_have_wraps
    Unexecuted instantiation: ccv_nnc_graph_case_of.c:ccv_nnc_tensors_have_wraps
    Unexecuted instantiation: ccv_nnc_graph_run.c:ccv_nnc_tensors_have_wraps
    Unexecuted instantiation: ccv_cnnp_model.c:ccv_nnc_tensors_have_wraps
    188
    189
    CCV_WARN_UNUSED(void*) ccv_nnc_graph_buffer(ccv_nnc_graph_t* const graph, int size);
    190
    CCV_WARN_UNUSED(ccv_nnc_graph_tensor_wrap_array_t*) ccv_nnc_get_tensor_wrap_array(ccv_nnc_graph_t* const graph, const int tensor_wrap_size, int* const tensor_wraps_ref);
    191
    void ccv_nnc_set_tensor_wraps(ccv_nnc_graph_tensor_wrap_t** const tensor_wraps, ccv_nnc_tensor_t* const* const tensors, const int tensor_size);
    192
    void ccv_nnc_graph_register_tensor_wraps(ccv_nnc_graph_t* graph, const int tensor_wraps_ref_d);
    193
    194
    #endif