• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

daisytuner / docc / 26831349290

02 Jun 2026 03:50PM UTC coverage: 61.29% (-0.01%) from 61.302%
26831349290

Pull #725

github

web-flow
Merge a7e2175c0 into 887730e20
Pull Request #725: Tensor node backport

932 of 1642 new or added lines in 52 files covered. (56.76%)

92 existing lines in 33 files now uncovered.

35584 of 58058 relevant lines covered (61.29%)

11020.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

16.99
/sdfg/src/data_flow/library_nodes/math/tensor/spatial_tensor_node.cpp
1
#include "sdfg/data_flow/library_nodes/math/tensor/spatial_tensor_node.h"
2

3
namespace sdfg::math::tensor {
4

5

6
SpatialTensorNode::SpatialTensorNode(
7
    size_t element_id,
8
    const DebugInfo& debug_info,
9
    const graph::Vertex vertex,
10
    data_flow::DataFlowGraph& parent,
11
    const data_flow::LibraryNodeCode& code,
12
    const std::vector<std::string>& outputs,
13
    const std::vector<std::string>& inputs,
14
    const data_flow::ImplementationType& impl_type,
15
    QuantizationType quantization,
16
    const std::vector<symbolic::Expression>& shape,
17
    const std::vector<symbolic::Expression>& kernel_shape,
18
    const std::vector<symbolic::Expression>& strides,
19
    const std::vector<symbolic::Expression>& pads,
20
    const std::vector<symbolic::Expression>& dilations
21
)
22
    : TensorNode(element_id, debug_info, vertex, parent, code, outputs, inputs, impl_type), shape_(shape),
52✔
23
      kernel_shape_(kernel_shape), strides_(strides), pads_(pads), dilations_(dilations),
52✔
24
      fixed_quantization_(quantization) {}
52✔
25

NEW
26
QuantizationType SpatialTensorNode::fixed_quantization() const { return fixed_quantization_; }
×
27

NEW
28
QuantizationType SpatialTensorNode::quantization(const data_flow::DataFlowGraph& data_flow_graph) const {
×
NEW
29
    if (fixed_quantization_ != QUANTIZATION_MATCH_INPUTS) {
×
NEW
30
        return fixed_quantization_;
×
NEW
31
    } else {
×
NEW
32
        return this->primitive_type(data_flow_graph);
×
NEW
33
    }
×
NEW
34
}
×
35

36
std::optional<QuantizationType> SpatialTensorNode::uniform_quantization(const data_flow::DataFlowGraph& data_flow_graph
NEW
37
) const {
×
NEW
38
    if (fixed_quantization_ != QUANTIZATION_MATCH_INPUTS) {
×
NEW
39
        auto inferred = this->primitive_type(data_flow_graph);
×
NEW
40
        if (inferred == fixed_quantization_) {
×
NEW
41
            return fixed_quantization_;
×
NEW
42
        } else {
×
NEW
43
            return std::nullopt;
×
NEW
44
        }
×
NEW
45
    } else {
×
NEW
46
        return this->primitive_type(data_flow_graph);
×
NEW
47
    }
×
NEW
48
}
×
49

NEW
50
void SpatialTensorNode::set_fixed_quantization(const QuantizationType quant) { fixed_quantization_ = quant; }
×
51

52
symbolic::SymbolSet SpatialTensorNode::symbols() const {
16✔
53
    symbolic::SymbolSet syms;
16✔
54
    for (auto& expr : shape_) {
64✔
55
        for (auto& atom : symbolic::atoms(expr)) {
64✔
56
            syms.insert(atom);
6✔
57
        }
6✔
58
    }
64✔
59
    for (auto& expr : kernel_shape_) {
32✔
60
        for (auto& atom : symbolic::atoms(expr)) {
32✔
NEW
61
            syms.insert(atom);
×
NEW
62
        }
×
63
    }
32✔
64
    for (auto& expr : strides_) {
28✔
65
        for (auto& atom : symbolic::atoms(expr)) {
28✔
NEW
66
            syms.insert(atom);
×
NEW
67
        }
×
68
    }
28✔
69
    for (auto& expr : pads_) {
52✔
70
        for (auto& atom : symbolic::atoms(expr)) {
52✔
NEW
71
            syms.insert(atom);
×
NEW
72
        }
×
73
    }
52✔
74
    for (auto& expr : dilations_) {
26✔
75
        for (auto& atom : symbolic::atoms(expr)) {
26✔
NEW
76
            syms.insert(atom);
×
NEW
77
        }
×
78
    }
26✔
79
    return syms;
16✔
80
}
16✔
81

82
void SpatialTensorNode::replace(const symbolic::Expression old_expression, const symbolic::Expression new_expression) {
1✔
83
    for (auto& expr : shape_) {
4✔
84
        expr = symbolic::subs(expr, old_expression, new_expression);
4✔
85
    }
4✔
86
    for (auto& expr : kernel_shape_) {
2✔
87
        expr = symbolic::subs(expr, old_expression, new_expression);
2✔
88
    }
2✔
89
    for (auto& expr : strides_) {
1✔
NEW
90
        expr = symbolic::subs(expr, old_expression, new_expression);
×
NEW
91
    }
×
92
    for (auto& expr : pads_) {
1✔
NEW
93
        expr = symbolic::subs(expr, old_expression, new_expression);
×
NEW
94
    }
×
95
    for (auto& expr : dilations_) {
1✔
NEW
96
        expr = symbolic::subs(expr, old_expression, new_expression);
×
NEW
97
    }
×
98
}
1✔
99

NEW
100
size_t SpatialTensorNode::num_spatial_dims() const {
×
NEW
101
    auto& s = shape_;
×
NEW
102
    assert(s.size() >= 2);
×
NEW
103
    return s.size() - 2;
×
NEW
104
}
×
105

NEW
106
symbolic::Expression SpatialTensorNode::output_spatial_dim(size_t i) const {
×
NEW
107
    size_t n_spatial = num_spatial_dims();
×
NEW
108
    assert(i < n_spatial);
×
109

NEW
110
    auto& s = shape_;
×
NEW
111
    auto& ks = kernel_shape_;
×
NEW
112
    auto& st = strides_;
×
NEW
113
    auto& pa = pads_;
×
NEW
114
    auto& di = dilations_;
×
115

NEW
116
    auto d_in = s[2 + i];
×
NEW
117
    auto k = ks[i];
×
118

NEW
119
    symbolic::Expression stride = st.empty() ? symbolic::Expression(symbolic::one()) : st[i];
×
NEW
120
    symbolic::Expression dilation = di.empty() ? symbolic::Expression(symbolic::one()) : di[i];
×
121

122
    // pads layout: [begin_d0, begin_d1, …, end_d0, end_d1, …]
NEW
123
    symbolic::Expression pad_begin = pa.empty() ? symbolic::Expression(symbolic::zero()) : pa[i];
×
NEW
124
    symbolic::Expression pad_end = pa.empty() ? symbolic::Expression(symbolic::zero()) : pa[n_spatial + i];
×
125

126
    // numerator = D_i + pad_begin + pad_end - dilation * (k - 1) - 1
NEW
127
    auto numerator = symbolic::
×
NEW
128
        sub(symbolic::add(symbolic::add(d_in, pad_begin), pad_end),
×
NEW
129
            symbolic::add(symbolic::mul(dilation, symbolic::sub(k, symbolic::one())), symbolic::one()));
×
130

NEW
131
    return symbolic::add(symbolic::div(numerator, stride), symbolic::one());
×
NEW
132
}
×
133

NEW
134
symbolic::Expression SpatialTensorNode::output_spatial_volume() const {
×
NEW
135
    size_t n_spatial = num_spatial_dims();
×
NEW
136
    symbolic::Expression result = symbolic::Expression(symbolic::one());
×
NEW
137
    for (size_t i = 0; i < n_spatial; ++i) {
×
NEW
138
        result = symbolic::mul(result, output_spatial_dim(i));
×
NEW
139
    }
×
NEW
140
    return result;
×
NEW
141
}
×
142

NEW
143
symbolic::Expression SpatialTensorNode::kernel_volume() const {
×
NEW
144
    auto& ks = kernel_shape_;
×
NEW
145
    return SymEngine::mul(ks);
×
NEW
146
}
×
147

NEW
148
std::basic_ostream<char>& SpatialTensorNode::operator<<(std::basic_ostream<char>& os) const {
×
NEW
149
    os << "shape=[";
×
NEW
150
    for (size_t i = 0; i < shape_.size(); ++i) {
×
NEW
151
        if (i > 0) os << ", ";
×
NEW
152
        os << shape_[i]->__str__();
×
NEW
153
    }
×
NEW
154
    os << "], kernel_shape=[";
×
NEW
155
    for (size_t i = 0; i < kernel_shape_.size(); ++i) {
×
NEW
156
        if (i > 0) os << ", ";
×
NEW
157
        os << kernel_shape_[i]->__str__();
×
NEW
158
    }
×
NEW
159
    os << "], strides=[";
×
NEW
160
    for (size_t i = 0; i < strides_.size(); ++i) {
×
NEW
161
        if (i > 0) os << ", ";
×
NEW
162
        os << strides_[i]->__str__();
×
NEW
163
    }
×
NEW
164
    os << "], pads=[";
×
NEW
165
    for (size_t i = 0; i < pads_.size(); ++i) {
×
NEW
166
        if (i > 0) os << ", ";
×
NEW
167
        os << pads_[i]->__str__();
×
NEW
168
    }
×
NEW
169
    os << "], dilations=[";
×
NEW
170
    for (size_t i = 0; i < dilations_.size(); ++i) {
×
NEW
171
        if (i > 0) os << ", ";
×
NEW
172
        os << dilations_[i]->__str__();
×
NEW
173
    }
×
NEW
174
    os << "], ";
×
NEW
175
    os << "quant=" << types::primitive_type_to_string(fixed_quantization_);
×
NEW
176
    return os;
×
NEW
177
}
×
178

NEW
179
void SpatialTensorNodeBaseSerializer::fill_base_values(const SpatialTensorNode& node, nlohmann::json& j) {
×
NEW
180
    j["code"] = node.code().value();
×
181

NEW
182
    serializer::JSONSerializer serializer;
×
183

NEW
184
    j["shape"] = nlohmann::json::array();
×
NEW
185
    for (auto& dim : node.shape()) {
×
NEW
186
        j["shape"].push_back(serializer.expression(dim));
×
NEW
187
    }
×
188

NEW
189
    j["kernel_shape"] = nlohmann::json::array();
×
NEW
190
    for (auto& dim : node.kernel_shape()) {
×
NEW
191
        j["kernel_shape"].push_back(serializer.expression(dim));
×
NEW
192
    }
×
193

NEW
194
    j["strides"] = nlohmann::json::array();
×
NEW
195
    for (auto& stride : node.strides()) {
×
NEW
196
        j["strides"].push_back(serializer.expression(stride));
×
NEW
197
    }
×
198

NEW
199
    j["pads"] = nlohmann::json::array();
×
NEW
200
    for (auto& pad : node.pads()) {
×
NEW
201
        j["pads"].push_back(serializer.expression(pad));
×
NEW
202
    }
×
203

NEW
204
    j["dilations"] = nlohmann::json::array();
×
NEW
205
    for (auto& dilation : node.dilations()) {
×
NEW
206
        j["dilations"].push_back(serializer.expression(dilation));
×
NEW
207
    }
×
208

NEW
209
    j["result_quant"] = node.quantization();
×
NEW
210
}
×
211

212
SpatialTensorNodeBaseSerializer::BaseDeser SpatialTensorNodeBaseSerializer::deserialize_base_values(const nlohmann::json&
NEW
213
                                                                                                        j) {
×
NEW
214
    assert(j.contains("element_id"));
×
NEW
215
    assert(j.contains("code"));
×
NEW
216
    assert(j.contains("debug_info"));
×
NEW
217
    assert(j.contains("kernel_shape"));
×
218

NEW
219
    std::vector<symbolic::Expression> shape;
×
NEW
220
    if (j.contains("shape")) {
×
NEW
221
        for (const auto& dim : j["shape"]) {
×
NEW
222
            shape.push_back(symbolic::parse(dim.get<std::string>()));
×
NEW
223
        }
×
NEW
224
    }
×
225

NEW
226
    std::vector<symbolic::Expression> kernel_shape;
×
NEW
227
    for (const auto& dim : j["kernel_shape"]) {
×
NEW
228
        kernel_shape.push_back(symbolic::parse(dim.get<std::string>()));
×
NEW
229
    }
×
230

NEW
231
    std::vector<symbolic::Expression> strides;
×
NEW
232
    if (j.contains("strides")) {
×
NEW
233
        for (const auto& stride : j["strides"]) {
×
NEW
234
            strides.push_back(symbolic::parse(stride.get<std::string>()));
×
NEW
235
        }
×
NEW
236
    }
×
237

NEW
238
    std::vector<symbolic::Expression> pads;
×
NEW
239
    if (j.contains("pads")) {
×
NEW
240
        for (const auto& pad : j["pads"]) {
×
NEW
241
            pads.push_back(symbolic::parse(pad.get<std::string>()));
×
NEW
242
        }
×
NEW
243
    }
×
244

NEW
245
    std::vector<symbolic::Expression> dilations;
×
NEW
246
    if (j.contains("dilations")) {
×
NEW
247
        for (const auto& dilation : j["dilations"]) {
×
NEW
248
            dilations.push_back(symbolic::parse(dilation.get<std::string>()));
×
NEW
249
        }
×
NEW
250
    }
×
251

NEW
252
    sdfg::serializer::JSONSerializer serializer;
×
NEW
253
    DebugInfo debug_info = serializer.json_to_debug_info(j["debug_info"]);
×
254

NEW
255
    return {
×
NEW
256
        .shape = shape,
×
NEW
257
        .kernel_shape = kernel_shape,
×
NEW
258
        .strides = strides,
×
NEW
259
        .pads = pads,
×
NEW
260
        .dilations = dilations,
×
NEW
261
        .quantization = deserialize_quantization(j, "result_quant", QUANTIZATION_MATCH_INPUTS),
×
NEW
262
        .debug_info = debug_info
×
NEW
263
    };
×
NEW
264
}
×
265

266
} // namespace sdfg::math::tensor
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc