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

daisytuner / sdfglib / 15340968114

30 May 2025 06:47AM UTC coverage: 58.553% (+0.2%) from 58.324%
15340968114

push

github

web-flow
Add parallel Map node

* Introduce Map data structure

* Prepare infrastructure

* implement analysis support

* Add basic infrastructure

* visualizer/serializer

* include fix

* update from main

* remove default

* happens before test + fixes

* builder test

* dispatcher test

* visitor, copy and serializer tests

* for2map structures

* for2map conversion draft

* add tests

* Bug fixes

* small updates from feedback

* Visitor style pass implementation

* cleanup

* fixes linting errors

---------

Co-authored-by: Lukas Truemper <lukas.truemper@outlook.de>

258 of 381 new or added lines in 26 files covered. (67.72%)

17 existing lines in 14 files now uncovered.

8184 of 13977 relevant lines covered (58.55%)

109.83 hits per line

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

93.2
/src/visualizer/dot_visualizer.cpp
1
#include "sdfg/visualizer/dot_visualizer.h"
2

3
#include <cstddef>
4
#include <string>
5
#include <utility>
6

7
#include "sdfg/data_flow/access_node.h"
8
#include "sdfg/data_flow/memlet.h"
9
#include "sdfg/schedule.h"
10
#include "sdfg/structured_control_flow/control_flow_node.h"
11
#include "sdfg/structured_control_flow/sequence.h"
12
#include "sdfg/structured_sdfg.h"
13

14
namespace sdfg {
15
namespace visualizer {
16

17
void DotVisualizer::visualizeBlock(Schedule& schedule, structured_control_flow::Block& block) {
179✔
18
    this->stream_ << "subgraph cluster_" << block.name() << " {" << std::endl;
179✔
19
    this->stream_.setIndent(this->stream_.indent() + 4);
179✔
20
    this->stream_ << "style=filled;shape=box;fillcolor=white;color=black;label=\"\";" << std::endl;
179✔
21
    this->last_comp_name_cluster_ = "cluster_" + block.name();
179✔
22
    if (block.dataflow().nodes().empty()) {
179✔
23
        this->stream_ << block.name() << " [shape=point,style=invis,label=\"\"];" << std::endl;
2✔
24
        this->stream_.setIndent(this->stream_.indent() - 4);
2✔
25
        this->stream_ << "}" << std::endl;
2✔
26
        this->last_comp_name_ = block.name();
2✔
27
        return;
2✔
28
    }
29
    this->last_comp_name_.clear();
177✔
30
    std::list<data_flow::DataFlowNode*> nodes = block.dataflow().topological_sort();
177✔
31
    for (data_flow::DataFlowNode* node : nodes) {
545✔
32
        if (const data_flow::Tasklet* tasklet = dynamic_cast<data_flow::Tasklet*>(node)) {
368✔
33
            this->stream_ << tasklet->name() << " [shape=octagon,label=\""
354✔
34
                          << tasklet->output(0).first << " = ";
177✔
35
            this->visualizeTasklet(*tasklet);
177✔
36
            this->stream_ << "\"];" << std::endl;
177✔
37
            for (data_flow::Memlet& iedge : block.dataflow().in_edges(*tasklet)) {
192✔
38
                data_flow::AccessNode const& src =
15✔
39
                    dynamic_cast<data_flow::AccessNode const&>(iedge.src());
15✔
40
                this->stream_ << src.name() << " -> " << tasklet->name() << " [label=\"   "
30✔
41
                              << iedge.dst_conn() << " = " << src.data();
15✔
42
                if (!symbolic::is_nvptx(symbolic::symbol(src.data()))) {
15✔
43
                    types::IType const& type = schedule.sdfg().type(src.data());
15✔
44
                    this->visualizeSubset(schedule.sdfg(), type, iedge.subset());
15✔
45
                }
15✔
46
                this->stream_ << "   \"];" << std::endl;
15✔
47
            }
48
            for (data_flow::Memlet& oedge : block.dataflow().out_edges(*tasklet)) {
354✔
49
                data_flow::AccessNode const& dst =
177✔
50
                    dynamic_cast<data_flow::AccessNode const&>(oedge.dst());
177✔
51
                types::IType const& type = schedule.sdfg().type(dst.data());
177✔
52
                this->stream_ << tasklet->name() << " -> " << dst.name() << " [label=\"   "
354✔
53
                              << dst.data();
177✔
54
                this->visualizeSubset(schedule.sdfg(), type, oedge.subset());
177✔
55
                this->stream_ << " = " << oedge.src_conn() << "   \"];" << std::endl;
177✔
56
            }
57
            if (this->last_comp_name_.empty()) this->last_comp_name_ = tasklet->name();
177✔
58
        } else if (const data_flow::AccessNode* access_node =
368✔
59
                       dynamic_cast<data_flow::AccessNode*>(node)) {
191✔
60
            bool source = false, sink = false;
190✔
61
            for (data_flow::Memlet& edge : block.dataflow().out_edges(*access_node)) {
190✔
62
                if ((source = (edge.src_conn() == "void"))) break;
14✔
63
            }
64
            for (data_flow::Memlet& edge : block.dataflow().in_edges(*access_node)) {
190✔
65
                if ((sink = (edge.dst_conn() == "void"))) break;
177✔
66
            }
67
            if (!source && !sink) continue;
190✔
68
            this->stream_ << access_node->name() << " [";
190✔
69
            if (!schedule.sdfg().is_internal(access_node->data())) this->stream_ << "penwidth=3.0,";
190✔
70
            if (schedule.sdfg().is_transient(access_node->data()))
190✔
71
                this->stream_ << "style=\"dashed,filled\",";
178✔
72
            this->stream_ << "label=\"" << access_node->data() << "\"];" << std::endl;
190✔
73
        } else if (const data_flow::LibraryNode* libnode =
191✔
74
                       dynamic_cast<data_flow::LibraryNode*>(node)) {
1✔
75
            this->stream_ << libnode->name() << " [shape=doubleoctagon,label=\"";
1✔
76
            this->visualizeLibraryNode(libnode->call());
1✔
77
            this->stream_ << "\"];" << std::endl;
1✔
78
            if (this->last_comp_name_.empty()) this->last_comp_name_ = libnode->name();
1✔
79
        }
1✔
80
    }
81
    this->stream_.setIndent(this->stream_.indent() - 4);
177✔
82
    this->stream_ << "}" << std::endl;
177✔
83
}
179✔
84

85
void DotVisualizer::visualizeSequence(Schedule& schedule,
189✔
86
                                      structured_control_flow::Sequence& sequence) {
87
    std::string last_comp_name_tmp, last_comp_name_cluster_tmp;
189✔
88
    for (size_t i = 0; i < sequence.size(); ++i) {
386✔
89
        std::pair<ControlFlowNode&, Transition&> child = sequence.at(i);
197✔
90
        this->visualizeNode(schedule, child.first);
197✔
91
        if ((i > 0) && !last_comp_name_tmp.empty() && !this->last_comp_name_.empty()) {
197✔
92
            this->stream_ << last_comp_name_tmp << " -> " << this->last_comp_name_ << " [";
8✔
93
            if (!last_comp_name_cluster_tmp.empty())
8✔
94
                this->stream_ << "ltail=\"" << last_comp_name_cluster_tmp << "\",";
8✔
95
            if (!this->last_comp_name_cluster_.empty())
8✔
96
                this->stream_ << "lhead=\"" << this->last_comp_name_cluster_ << "\",";
6✔
97
            this->stream_ << "minlen=3]"
8✔
98
                          << ";" << std::endl;
8✔
99
        }
8✔
100
        last_comp_name_tmp = this->last_comp_name_;
197✔
101
        this->last_comp_name_.clear();
197✔
102
        last_comp_name_cluster_tmp = this->last_comp_name_cluster_;
197✔
103
        this->last_comp_name_cluster_.clear();
197✔
104
    }
197✔
105
}
189✔
106

107
void DotVisualizer::visualizeIfElse(Schedule& schedule, structured_control_flow::IfElse& if_else) {
3✔
108
    this->stream_ << "subgraph cluster_" << if_else.name() << " {" << std::endl;
3✔
109
    this->stream_.setIndent(this->stream_.indent() + 4);
3✔
110
    this->stream_ << "style=filled;shape=box;fillcolor=white;color=black;label=\"if:\";"
6✔
111
                  << std::endl
3✔
112
                  << if_else.name() << " [shape=point,style=invis,label=\"\"];" << std::endl;
3✔
113
    for (size_t i = 0; i < if_else.size(); ++i) {
9✔
114
        this->stream_ << "subgraph cluster_" << if_else.name() << "_" << std::to_string(i) << " {"
12✔
115
                      << std::endl;
6✔
116
        this->stream_.setIndent(this->stream_.indent() + 4);
6✔
117
        this->stream_ << "style=filled;shape=box;fillcolor=white;color=black;label=\""
12✔
118
                      << this->expression(if_else.at(i).second->__str__()) << "\";" << std::endl;
6✔
119
        this->visualizeSequence(schedule, if_else.at(i).first);
6✔
120
        this->stream_.setIndent(this->stream_.indent() - 4);
6✔
121
        this->stream_ << "}" << std::endl;
6✔
122
    }
6✔
123
    this->stream_.setIndent(this->stream_.indent() - 4);
3✔
124
    this->stream_ << "}" << std::endl;
3✔
125
    this->last_comp_name_ = if_else.name();
3✔
126
    this->last_comp_name_cluster_ = "cluster_" + if_else.name();
3✔
127
}
3✔
128

129
void DotVisualizer::visualizeWhile(Schedule& schedule, structured_control_flow::While& while_loop) {
2✔
130
    this->stream_ << "subgraph cluster_" << while_loop.name() << " {" << std::endl;
2✔
131
    this->stream_.setIndent(this->stream_.indent() + 4);
2✔
132
    this->stream_ << "style=filled;shape=box;fillcolor=white;color=black;label=\"while:\";"
4✔
133
                  << std::endl
2✔
134
                  << while_loop.name() << " [shape=point,style=invis,label=\"\"];" << std::endl;
2✔
135
    this->visualizeSequence(schedule, while_loop.root());
2✔
136
    this->stream_.setIndent(this->stream_.indent() - 4);
2✔
137
    this->stream_ << "}" << std::endl;
2✔
138
    this->last_comp_name_ = while_loop.name();
2✔
139
    this->last_comp_name_cluster_ = "cluster_" + while_loop.name();
2✔
140
}
2✔
141

142
void DotVisualizer::visualizeFor(Schedule& schedule, structured_control_flow::For& loop) {
9✔
143
    this->stream_ << "subgraph cluster_" << loop.name() << " {" << std::endl;
9✔
144
    this->stream_.setIndent(this->stream_.indent() + 4);
9✔
145
    this->stream_ << "style=filled;shape=box;fillcolor=white;color=black;label=\"for: ";
9✔
146
    this->visualizeForBounds(loop.indvar(), loop.init(), loop.condition(), loop.update());
9✔
147
    LoopSchedule loop_schedule = schedule.loop_schedule(&loop);
9✔
148
    if (loop_schedule == LoopSchedule::VECTORIZATION) this->stream_ << " (vectorized)";
9✔
149
    if (loop_schedule == LoopSchedule::MULTICORE) this->stream_ << " (parallelized)";
9✔
150
    this->stream_ << "\";" << std::endl
18✔
151
                  << loop.name() << " [shape=point,style=invis,label=\"\"];" << std::endl;
9✔
152
    this->visualizeSequence(schedule, loop.root());
9✔
153
    this->stream_.setIndent(this->stream_.indent() - 4);
9✔
154
    this->stream_ << "}" << std::endl;
9✔
155
    this->last_comp_name_ = loop.name();
9✔
156
    this->last_comp_name_cluster_ = "cluster_" + loop.name();
9✔
157
}
9✔
158

159
void DotVisualizer::visualizeReturn(Schedule& schedule,
1✔
160
                                    structured_control_flow::Return& return_node) {
161
    this->stream_ << return_node.name() << " [shape=cds,label=\" return  \"];" << std::endl;
1✔
162
    this->last_comp_name_ = return_node.name();
1✔
163
    this->last_comp_name_cluster_.clear();
1✔
164
}
1✔
165
void DotVisualizer::visualizeBreak(Schedule& schedule, structured_control_flow::Break& break_node) {
1✔
166
    this->stream_ << break_node.name() << " [shape=cds,label=\" break  \"];" << std::endl;
1✔
167
    this->last_comp_name_ = break_node.name();
1✔
168
    this->last_comp_name_cluster_.clear();
1✔
169
}
1✔
170

171
void DotVisualizer::visualizeContinue(Schedule& schedule,
1✔
172
                                      structured_control_flow::Continue& continue_node) {
173
    this->stream_ << continue_node.name() << " [shape=cds,label=\" continue  \"];" << std::endl;
1✔
174
    this->last_comp_name_ = continue_node.name();
1✔
175
    this->last_comp_name_cluster_.clear();
1✔
176
}
1✔
177

178
void DotVisualizer::visualizeKernel(Schedule& schedule,
1✔
179
                                    structured_control_flow::Kernel& kernel_node) {
180
    bool gridDim_x = false;
1✔
181
    bool gridDim_y = false;
1✔
182
    bool gridDim_z = false;
1✔
183
    bool blockDim_x = false;
1✔
184
    bool blockDim_y = false;
1✔
185
    bool blockDim_z = false;
1✔
186
    bool blockIdx_x = false;
1✔
187
    bool blockIdx_y = false;
1✔
188
    bool blockIdx_z = false;
1✔
189
    bool threadIdx_x = false;
1✔
190
    bool threadIdx_y = false;
1✔
191
    bool threadIdx_z = false;
1✔
192

193
    for (std::string const& container : schedule.sdfg().containers()) {
20✔
194
        gridDim_x = gridDim_x || (container == kernel_node.gridDim_x()->get_name());
19✔
195
        gridDim_y = gridDim_y || (container == kernel_node.gridDim_y()->get_name());
19✔
196
        gridDim_z = gridDim_z || (container == kernel_node.gridDim_z()->get_name());
19✔
197
        blockDim_x = blockDim_x || (container == kernel_node.blockDim_x()->get_name());
19✔
198
        blockDim_y = blockDim_y || (container == kernel_node.blockDim_y()->get_name());
19✔
199
        blockDim_z = blockDim_z || (container == kernel_node.blockDim_z()->get_name());
19✔
200
        blockIdx_x = blockIdx_x || (container == kernel_node.blockIdx_x()->get_name());
19✔
201
        blockIdx_y = blockIdx_y || (container == kernel_node.blockIdx_y()->get_name());
19✔
202
        blockIdx_z = blockIdx_z || (container == kernel_node.blockIdx_z()->get_name());
19✔
203
        threadIdx_x = threadIdx_x || (container == kernel_node.threadIdx_x()->get_name());
19✔
204
        threadIdx_y = threadIdx_y || (container == kernel_node.threadIdx_y()->get_name());
19✔
205
        threadIdx_z = threadIdx_z || (container == kernel_node.threadIdx_z()->get_name());
19✔
206
    }
207

208
    size_t replacements_size_before = this->replacements_.size();
1✔
209

210
    if (gridDim_x)
1✔
211
        this->replacements_.push_back(
2✔
212
            {kernel_node.gridDim_x()->get_name(), kernel_node.gridDim_x_init()->__str__()});
1✔
213
    if (gridDim_y)
1✔
214
        this->replacements_.push_back(
2✔
215
            {kernel_node.gridDim_y()->get_name(), kernel_node.gridDim_y_init()->__str__()});
1✔
216
    if (gridDim_z)
1✔
217
        this->replacements_.push_back(
2✔
218
            {kernel_node.gridDim_z()->get_name(), kernel_node.gridDim_z_init()->__str__()});
1✔
219
    if (blockDim_x)
1✔
220
        this->replacements_.push_back(
2✔
221
            {kernel_node.blockDim_x()->get_name(), kernel_node.blockDim_x_init()->__str__()});
1✔
222
    if (blockDim_y)
1✔
223
        this->replacements_.push_back(
2✔
224
            {kernel_node.blockDim_y()->get_name(), kernel_node.blockDim_y_init()->__str__()});
1✔
225
    if (blockDim_z)
1✔
226
        this->replacements_.push_back(
2✔
227
            {kernel_node.blockDim_z()->get_name(), kernel_node.blockDim_z_init()->__str__()});
1✔
228
    if (blockIdx_x)
1✔
229
        this->replacements_.push_back(
2✔
230
            {kernel_node.blockIdx_x()->get_name(), kernel_node.blockIdx_x_init()->__str__()});
1✔
231
    if (blockIdx_y)
1✔
232
        this->replacements_.push_back(
2✔
233
            {kernel_node.blockIdx_y()->get_name(), kernel_node.blockIdx_y_init()->__str__()});
1✔
234
    if (blockIdx_z)
1✔
235
        this->replacements_.push_back(
2✔
236
            {kernel_node.blockIdx_z()->get_name(), kernel_node.blockIdx_z_init()->__str__()});
1✔
237
    if (threadIdx_x)
1✔
238
        this->replacements_.push_back(
2✔
239
            {kernel_node.threadIdx_x()->get_name(), kernel_node.threadIdx_x_init()->__str__()});
1✔
240
    if (threadIdx_y)
1✔
241
        this->replacements_.push_back(
2✔
242
            {kernel_node.threadIdx_y()->get_name(), kernel_node.threadIdx_y_init()->__str__()});
1✔
243
    if (threadIdx_z)
1✔
244
        this->replacements_.push_back(
2✔
245
            {kernel_node.threadIdx_z()->get_name(), kernel_node.threadIdx_z_init()->__str__()});
1✔
246

247
    this->visualizeSequence(schedule, kernel_node.root());
1✔
248

249
    this->replacements_.resize(replacements_size_before);
1✔
250
}
1✔
251

NEW
252
void DotVisualizer::visualizeMap(Schedule& schedule, structured_control_flow::Map& map_node) {
×
NEW
253
    this->stream_ << "subgraph cluster_" << map_node.name() << " {" << std::endl;
×
NEW
254
    this->stream_.setIndent(this->stream_.indent() + 4);
×
NEW
255
    this->stream_ << "style=filled;shape=box;fillcolor=white;color=black;label=\"map: ";
×
NEW
256
    this->stream_ << map_node.indvar()->get_name() << "[0:";
×
NEW
257
    this->stream_ << map_node.num_iterations()->__str__() << "];";
×
NEW
258
    LoopSchedule loop_schedule = schedule.loop_schedule(&map_node);
×
NEW
259
    if (loop_schedule == LoopSchedule::VECTORIZATION) this->stream_ << " (vectorized)";
×
NEW
260
    if (loop_schedule == LoopSchedule::MULTICORE) this->stream_ << " (parallelized)";
×
NEW
261
    this->stream_ << "\";" << std::endl
×
NEW
262
                  << map_node.name() << " [shape=point,style=invis,label=\"\"];" << std::endl;
×
NEW
263
    this->visualizeSequence(schedule, map_node.root());
×
NEW
264
    this->stream_.setIndent(this->stream_.indent() - 4);
×
NEW
265
    this->stream_ << "}" << std::endl;
×
NEW
266
    this->last_comp_name_ = map_node.name();
×
NEW
267
    this->last_comp_name_cluster_ = "cluster_" + map_node.name();
×
NEW
268
}
×
269

270
void DotVisualizer::visualize() {
171✔
271
    this->stream_.clear();
171✔
272
    this->stream_ << "digraph " << this->schedule_.name() << " {" << std::endl;
171✔
273
    this->stream_.setIndent(4);
171✔
274
    this->stream_ << "graph [compound=true];" << std::endl;
171✔
275
    for (size_t i = 0; i < schedule_.size(); ++i) {
342✔
276
        StructuredSDFG const& sdfg = this->schedule_.schedule(i).sdfg();
171✔
277
        StructuredSDFG& function = this->schedule_.schedule(i).builder().subject();
171✔
278
        this->stream_ << "subgraph cluster_" << sdfg.name() << " {" << std::endl;
171✔
279
        this->stream_.setIndent(8);
171✔
280
        this->stream_ << "node [style=filled,fillcolor=white];" << std::endl
171✔
281
                      << "style=filled;color=lightblue;label=\"";
171✔
282
        std::string condition = this->expression(this->schedule_.condition(i)->__str__());
171✔
283
        if (condition != "True") this->stream_ << condition;
171✔
284
        this->stream_ << "\";" << std::endl;
171✔
285
        this->visualizeSequence(this->schedule_.schedule(i), function.root());
171✔
286
        this->stream_.setIndent(4);
171✔
287
        this->stream_ << "}" << std::endl;
171✔
288
    }
171✔
289
    this->stream_.setIndent(0);
171✔
290
    this->stream_ << "}" << std::endl;
171✔
291
}
171✔
292

293
}  // namespace visualizer
294
}  // namespace sdfg
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

© 2025 Coveralls, Inc