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

daisytuner / docc / 28094136925

24 Jun 2026 11:07AM UTC coverage: 61.875% (+0.1%) from 61.779%
28094136925

push

github

web-flow
defines transformation json schema and aligns transformations (#809)

249 of 329 new or added lines in 38 files covered. (75.68%)

5 existing lines in 5 files now uncovered.

37186 of 60099 relevant lines covered (61.87%)

1014.83 hits per line

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

39.29
/opt/src/transformations/offloading/rocm_parallelize_nested_map.cpp
1
#include "sdfg/transformations/offloading/rocm_parallelize_nested_map.h"
2

3
#include <sdfg/analysis/loop_analysis.h>
4
#include "sdfg/exceptions.h"
5
#include "sdfg/symbolic/symbolic.h"
6
#include "sdfg/targets/rocm/rocm.h"
7

8
namespace sdfg {
9
namespace transformations {
10

11
ROCMParallelizeNestedMap::ROCMParallelizeNestedMap(structured_control_flow::Map& loop, size_t block_size)
12
    : loop_(loop), block_size_(block_size) {}
2✔
13

14
std::string ROCMParallelizeNestedMap::name() const { return "ROCMParallelizeNestedMap"; }
×
15

16
bool ROCMParallelizeNestedMap::
17
    can_be_applied(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
2✔
18
    auto& loop_analysis = analysis_manager.get<analysis::LoopAnalysis>();
2✔
19

20
    // Condition: Check if map is not yet parallelized with ROCM
21
    if (loop_.schedule_type().value() != ScheduleType_Sequential::value()) {
2✔
22
        return false;
×
23
    }
×
24

25
    // Condition: Check if parent loop exists
26
    auto parent = loop_analysis.parent_loop(&loop_);
2✔
27
    if (parent == nullptr) {
2✔
28
        return false;
×
29
    }
×
30

31
    // Condition: Check if parent loop is a ROCM map, and not Z dimension (final dimension)
32
    if (auto map = dynamic_cast<structured_control_flow::Map*>(parent)) {
2✔
33
        if (map->schedule_type().value() != rocm::ScheduleType_ROCM::value()) {
2✔
34
            return false;
×
35
        }
×
36
        if (rocm::ScheduleType_ROCM::dimension(map->schedule_type()) == rocm::ROCMDimension::Z) {
2✔
37
            return false;
×
38
        }
×
39
        auto parent_indvar = map->indvar();
2✔
40
        auto ancestor = parent;
2✔
41
        while (ancestor) {
4✔
42
            if (auto map_ancestor = dynamic_cast<structured_control_flow::Map*>(ancestor)) {
2✔
43
                parent_indvar = map_ancestor->indvar();
2✔
44
                for (auto& arg : symbolic::atoms(loop_.condition())) {
2✔
45
                    if (symbolic::eq(arg, parent_indvar)) {
2✔
46
                        return false;
×
47
                    }
×
48
                }
2✔
49
            }
2✔
50
            ancestor = loop_analysis.parent_loop(ancestor);
2✔
51
        }
2✔
52
    } else {
2✔
53
        return false;
×
54
    }
×
55

56
    // Note: arbitrary `init` and `stride` are permitted. The ROCm dispatcher
57
    // emits `<map.indvar> = init + thread_flat_id * stride`, so the body sees
58
    // the natural strided value; `num_iterations()` accounts for both when
59
    // computing the grid geometry.
60

61
    // Condition: Resulting ROCm grid dimension must not exceed hardware limits.
62
    // Y and Z grid dimensions are limited to 65535.
63
    auto num_iters = loop_.num_iterations();
2✔
64
    if (!num_iters.is_null() && SymEngine::is_a<SymEngine::Integer>(*num_iters)) {
2✔
65
        int64_t iters = SymEngine::down_cast<const SymEngine::Integer&>(*num_iters).as_int();
2✔
66
        int64_t block = static_cast<int64_t>(block_size_);
2✔
67
        int64_t grid_size = (iters + block - 1) / block;
2✔
68

69
        constexpr int64_t max_grid_dim_yz = 65535;
2✔
70
        if (grid_size > max_grid_dim_yz) {
2✔
71
            return false;
1✔
72
        }
1✔
73
    }
2✔
74

75
    return true;
1✔
76
}
2✔
77

78
void ROCMParallelizeNestedMap::apply(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
×
79
    auto& loop_analysis = analysis_manager.get<analysis::LoopAnalysis>();
×
80
    auto parent = loop_analysis.parent_loop(&loop_);
×
81

82
    auto parent_dim =
×
83
        rocm::ScheduleType_ROCM::dimension(static_cast<structured_control_flow::Map*>(parent)->schedule_type());
×
84

85
    rocm::ROCMDimension child_dim;
×
86
    if (parent_dim == rocm::ROCMDimension::X) {
×
87
        child_dim = rocm::ROCMDimension::Y;
×
88
    } else if (parent_dim == rocm::ROCMDimension::Y) {
×
89
        child_dim = rocm::ROCMDimension::Z;
×
90
    } else {
×
91
        throw InvalidSDFGException("Parent loop is Z dimension, cannot parallelize nested map.");
×
92
    }
×
93

94
    auto new_schedule = rocm::ScheduleType_ROCM::create();
×
95
    rocm::ScheduleType_ROCM::dimension(new_schedule, child_dim);
×
96
    rocm::ScheduleType_ROCM::block_size(new_schedule, symbolic::integer(block_size_));
×
97

98
    builder.update_schedule_type(loop_, new_schedule);
×
99
}
×
100

101
void ROCMParallelizeNestedMap::to_json(nlohmann::json& j) const {
×
102
    j["transformation_type"] = this->name();
×
NEW
103
    j["parameters"] = nlohmann::json::object();
×
NEW
104
    j["parameters"]["block_size"] = block_size_;
×
105

NEW
106
    serializer::JSONSerializer ser_flat(false);
×
NEW
107
    j["subgraph"] = nlohmann::json::object();
×
NEW
108
    j["subgraph"]["0"] = nlohmann::json::object();
×
NEW
109
    ser_flat.serialize_node(j["subgraph"]["0"], loop_);
×
UNCOV
110
}
×
111

112
ROCMParallelizeNestedMap ROCMParallelizeNestedMap::
113
    from_json(builder::StructuredSDFGBuilder& builder, const nlohmann::json& j) {
×
114
    // Prefer the embedding-compatible representation (subgraph/parameters),
115
    // but fall back to legacy fields (loop/block_size) if needed.
NEW
116
    const auto& subgraph = j.at("subgraph");
×
NEW
117
    const auto& node_desc = subgraph.at("0");
×
NEW
118
    size_t loop_id = node_desc.at("element_id").get<size_t>();
×
119

NEW
120
    size_t block_size = j.at("parameters").at("block_size").get<size_t>();
×
NEW
121
    auto loop = dynamic_cast<structured_control_flow::Map*>(builder.find_element_by_id(loop_id));
×
122
    if (!loop) {
×
123
        throw InvalidTransformationDescriptionException("Element with ID " + std::to_string(loop_id) + " is not a loop.");
×
124
    }
×
125
    return ROCMParallelizeNestedMap(*loop, block_size);
×
126
}
×
127

128
} // namespace transformations
129
} // 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

© 2026 Coveralls, Inc