Coverage Report

Created: 2024-08-19 11:27

/home/liu/actions-runner/_work/ccv/ccv/test/unit/nnc/custom.tests.c
Line
Count
Source
1
#include "case.h"
2
#include "ccv_case.h"
3
#include "ccv_nnc_case.h"
4
#include <ccv.h>
5
#include <nnc/ccv_nnc.h>
6
#include <nnc/ccv_nnc_easy.h>
7
#include "3rdparty/dsfmt/dSFMT.h"
8
9
TEST_SETUP()
10
{
11
  ccv_nnc_init();
12
}
13
14
static int _ccv_nnc_cmd_custom_exec(const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, ccv_nnc_tensor_t* const* const inputs, const int input_size, ccv_nnc_tensor_t* const* const outputs, const int output_size, ccv_nnc_stream_context_t* const stream_context)
15
3
{
16
3
  if (cmd.cmd == CCV_NNC_CUSTOM_FORWARD)
17
2
  {
18
2
    ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
19
2
    const ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph);
20
2
    ccv_nnc_tensor_variable_set(graph, x, inputs[0]);
21
2
    const ccv_nnc_tensor_variable_t z = ccv_nnc_tensor_variable_new(graph);
22
2
    ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x), TENSOR_VARIABLE_LIST(z), 0, 0);
23
2
    const ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_variable_new(graph);
24
2
    ccv_nnc_tensor_variable_set(graph, y, outputs[0]);
25
2
    ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(z), TENSOR_VARIABLE_LIST(y), 0, 0);
26
2
    ccv_nnc_dynamic_graph_free(graph);
27
2
  } else {
28
1
    ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
29
1
    const ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph);
30
1
    ccv_nnc_tensor_variable_set(graph, x, inputs[1]);
31
1
    const ccv_nnc_tensor_variable_t z = ccv_nnc_tensor_variable_new(graph);
32
1
    ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x), TENSOR_VARIABLE_LIST(z), 0, 0);
33
1
    const ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_variable_new(graph);
34
1
    ccv_nnc_tensor_variable_set(graph, y, inputs[2]);
35
1
    ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(z), TENSOR_VARIABLE_LIST(y), 0, 0);
36
1
    const ccv_nnc_tensor_variable_t dy = ccv_nnc_tensor_variable_new(graph);
37
1
    ccv_nnc_tensor_variable_set(graph, dy, inputs[0]);
38
1
    const ccv_nnc_tensor_variable_t dx = ccv_nnc_tensor_variable_new(graph);
39
1
    ccv_nnc_tensor_variable_set(graph, dx, outputs[0]);
40
1
    ccv_nnc_dynamic_graph_backward(graph, TENSOR_VARIABLE_LIST(y), &dy, TENSOR_VARIABLE_LIST(x), TENSOR_VARIABLE_LIST(dx), 0);
41
1
    ccv_nnc_dynamic_graph_free(graph);
42
1
  }
43
3
  return CCV_NNC_EXEC_SUCCESS;
44
3
}
45
46
static ccv_nnc_cmd_vtab_t _custom_isa = {
47
  .exec = _ccv_nnc_cmd_custom_exec,
48
};
49
50
TEST_CASE("custom forward operation with dynamic graph")
51
1
{
52
1
  const ccv_nnc_cmd_t cmd = ccv_nnc_cmd(CCV_NNC_CUSTOM_FORWARD, &_custom_isa, (ccv_nnc_cmd_param_t){}, 0);
53
1
  ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
54
1
  const ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x");
55
1
  const ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y");
56
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, cmd, TENSOR_SYMBOL_LIST(x), TENSOR_SYMBOL_LIST(y), "custom");
57
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS | CCV_NNC_AUTOGEN_ALL_EXECS);
58
1
  ccv_nnc_graph_t* graph;
59
1
  ccv_nnc_tensor_arena_t* tensor_arena;
60
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena;
61
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0,
62
1
    TENSOR_SYMBOL_LIST(y),
63
1
    SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph),
64
1
    &graph, &tensor_arena, &graph_exec_arena);
65
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
66
1
  ccv_nnc_tensor_t* const x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
67
1
  x_tensor->data.f32[0] = 10;
68
1
  ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
69
1
  ccv_nnc_tensor_t* const y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
70
1
  REQUIRE_EQ_WITH_TOLERANCE(y_tensor->data.f32[0], log(log(10)), 1e-5, "computed result should be identical");
71
1
  ccv_nnc_graph_free(graph);
72
1
  ccv_nnc_tensor_arena_free(tensor_arena);
73
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
74
1
}
75
76
TEST_CASE("custom backward operation with dynamic graph")
77
1
{
78
1
  const ccv_nnc_cmd_t cmd = ccv_nnc_cmd(CCV_NNC_CUSTOM_FORWARD, &_custom_isa, (ccv_nnc_cmd_param_t){}, 0);
79
1
  ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
80
1
  const ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x");
81
1
  const ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y");
82
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, cmd, TENSOR_SYMBOL_LIST(x), TENSOR_SYMBOL_LIST(y), "custom");
83
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS | CCV_NNC_AUTOGEN_ALL_EXECS);
84
1
  ccv_nnc_symbolic_graph_backward(symbolic_graph, TENSOR_SYMBOL_LIST(y), TENSOR_SYMBOL_LIST(x), SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph));
85
1
  const ccv_nnc_tensor_symbol_t dy = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, y);
86
1
  ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_SET_FORWARD(1), TENSOR_SYMBOL_LIST(), TENSOR_SYMBOL_LIST(dy), "set");
87
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS | CCV_NNC_AUTOGEN_ALL_EXECS);
88
1
  const ccv_nnc_tensor_symbol_t dx = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, x);
89
1
  ccv_nnc_graph_t* graph;
90
1
  ccv_nnc_tensor_arena_t* tensor_arena;
91
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena;
92
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0,
93
1
    TENSOR_SYMBOL_LIST(dx),
94
1
    SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph),
95
1
    &graph, &tensor_arena, &graph_exec_arena);
96
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
97
1
  ccv_nnc_tensor_t* const x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
98
1
  x_tensor->data.f32[0] = 10;
99
1
  ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
100
1
  ccv_nnc_tensor_t* const dx_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, dx);
101
1
  REQUIRE_EQ_WITH_TOLERANCE(dx_tensor->data.f32[0], 1. / (log(10) * 10), 1e-5, "computed result should be identical");
102
1
  ccv_nnc_graph_free(graph);
103
1
  ccv_nnc_tensor_arena_free(tensor_arena);
104
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
105
1
}
106
107
#include "case_main.h"