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

celerity / celerity-runtime / 9944865221

15 Jul 2024 06:42PM UTC coverage: 93.084%. First build
9944865221

Pull #255

github

fknorr
Add multi-device selection & tests

This allows selecting multiple devices per node as anticipated by the
IDAG scheduler. When multiple processes are launched per node, this
will fall back to old (or hybrid) behavior of distributing devices
among local nodes.

Co-authored-by: Philip Salzmann <philip.salzmann@uibk.ac.at>
Pull Request #255: [IDAG] Upstream Multi-Device Selection + Tests

3181 of 3679 branches covered (86.46%)

Branch coverage included in aggregate %.

107 of 109 new or added lines in 2 files covered. (98.17%)

7236 of 7512 relevant lines covered (96.33%)

165142.91 hits per line

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

89.58
/include/utils.h
1
#pragma once
2

3
#include <algorithm>
4
#include <cassert>
5
#include <cstdint>
6
#include <functional>
7
#include <string>
8
#include <tuple>
9
#include <type_traits>
10
#include <typeinfo>
11

12
#include <fmt/format.h>
13

14
#include "types.h"
15

16

17
namespace celerity::detail::utils {
18

19
/// Like std::move, but move-constructs the result so it does not reference the argument after returning.
20
template <typename T>
21
T take(T& from) {
450✔
22
        return std::move(from);
450✔
23
}
24

25
template <typename T, typename P>
26
bool isa(const P* p) {
78,653✔
27
        return dynamic_cast<const T*>(p) != nullptr;
78,653!
28
}
29

30
template <typename T, typename P>
31
auto as(P* p) {
17,631✔
32
        assert(isa<T>(p));
17,631✔
33
        return static_cast<std::conditional_t<std::is_const_v<P>, const T*, T*>>(p);
17,631✔
34
}
35

36
template <typename BitMaskT>
37
constexpr inline uint32_t popcount(const BitMaskT bit_mask) noexcept {
38
        static_assert(std::is_integral_v<BitMaskT> && std::is_unsigned_v<BitMaskT>, "popcount argument needs to be an unsigned integer type.");
39

40
        uint32_t counter = 0;
41
        for(auto b = bit_mask; b; b >>= 1) {
42
                counter += b & 1;
43
        }
44
        return counter;
45
}
46

47
// Implementation from Boost.ContainerHash, licensed under the Boost Software License, Version 1.0.
48
inline void hash_combine(std::size_t& seed, std::size_t value) { seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2); }
35,932✔
49

50
struct pair_hash {
51
        template <typename U, typename V>
52
        std::size_t operator()(const std::pair<U, V>& p) const {
10,038✔
53
                std::size_t seed = 0;
10,038✔
54
                hash_combine(seed, std::hash<U>{}(p.first));
10,038✔
55
                hash_combine(seed, std::hash<V>{}(p.second));
10,038✔
56
                return seed;
10,038✔
57
        }
58
};
59

60
} // namespace celerity::detail::utils
61

62
namespace celerity::detail::utils_detail {
63

64
template <typename... Without, typename... ToKeep, typename T, typename... Ts>
65
constexpr auto tuple_without_impl(const std::tuple<ToKeep...>& to_keep, const std::tuple<T, Ts...>& to_check) {
14✔
66
        if constexpr((std::is_same_v<T, Without> || ...)) {
67
                if constexpr(sizeof...(Ts) == 0) {
68
                        return to_keep;
6✔
69
                } else {
70
                        return tuple_without_impl<Without...>(to_keep, std::tuple{std::get<Ts>(to_check)...});
71
                }
72
        } else {
73
                if constexpr(sizeof...(Ts) == 0) {
74
                        return std::tuple_cat(to_keep, to_check);
5✔
75
                } else {
76
                        return tuple_without_impl<Without...>(std::tuple_cat(to_keep, std::tuple{std::get<T>(to_check)}), std::tuple{std::get<Ts>(to_check)...});
3✔
77
                }
78
        }
79
}
80

81
template <typename Tuple, typename Callback>
82
constexpr void tuple_for_each_pair_impl(const Tuple&, Callback&&, std::index_sequence<>) {}
5,572✔
83

84
template <typename Tuple, size_t I1, size_t I2, size_t... Is, typename Callback>
85
constexpr void tuple_for_each_pair_impl(const Tuple& tuple, const Callback& cb, std::index_sequence<I1, I2, Is...>) {
10,432✔
86
        cb(std::get<I1>(tuple), std::get<I2>(tuple));
10,432✔
87
        tuple_for_each_pair_impl(tuple, cb, std::index_sequence<Is...>{});
10,432✔
88
}
10,432✔
89

90
template <typename Container, typename Key, typename Enable = void>
91
struct has_member_find : std::false_type {};
92

93
template <typename Container, typename Key>
94
struct has_member_find<Container, Key, std::void_t<decltype(std::declval<const Container&>().find(std::declval<const Key&>()))>> : std::true_type {};
95

96
template <typename Container, typename Key>
97
inline constexpr bool has_member_find_v = has_member_find<Container, Key>::value;
98

99
} // namespace celerity::detail::utils_detail
100

101
namespace celerity::detail::utils {
102

103
/// See `utils::type_switch_t`.
104
template <typename Lookup, typename... KVs>
105
struct type_switch {};
106

107
/// `switch` equivalent of `std::conditional_t`. Use as `utils::type_switch_t<lookup-type, key-type-1(result-type-1), key-type-2(result-type-2), ...>`
108
template <typename Lookup, typename... KVs>
109
using type_switch_t = typename type_switch<Lookup, KVs...>::type;
110

111
template <typename MatchingKey, typename Value, typename... KVs>
112
struct type_switch<MatchingKey, MatchingKey(Value), KVs...> {
113
        using type = Value;
114
};
115

116
template <typename NonMatching, typename Key, typename Value, typename... KVs>
117
struct type_switch<NonMatching, Key(Value), KVs...> {
118
        using type = type_switch_t<NonMatching, KVs...>;
119
};
120

121
template <typename... Without, typename... Ts>
122
constexpr auto tuple_without(const std::tuple<Ts...>& tuple) {
18✔
123
        if constexpr(sizeof...(Ts) > 0) {
124
                return utils_detail::tuple_without_impl<Without...>({}, tuple);
11✔
125
        } else {
126
                return tuple;
7✔
127
        }
128
}
129

130
template <typename Tuple, typename Callback>
131
constexpr void tuple_for_each_pair(const Tuple& tuple, const Callback& cb) {
5,572✔
132
        static_assert(std::tuple_size_v<Tuple> % 2 == 0, "an even number of entries is required");
133
        utils_detail::tuple_for_each_pair_impl(tuple, cb, std::make_index_sequence<std::tuple_size_v<Tuple>>{});
5,572✔
134
}
5,572✔
135

136
/// Fiddles out the base name of a (possibly templated) struct or class from a full (possibly mangled) type name.
137
/// The input parameter should be `typeid(Struct*)`, i.e. a _pointer_ to the desired struct type.
138
std::string get_simplified_type_name_from_pointer(const std::type_info& pointer_type_info);
139

140
/// Fiddles out the base name of a (possibly templated) struct or class from a full (possibly mangled) type name.
141
template <typename Struct>
142
std::string get_simplified_type_name() {
1,705✔
143
        // Using a pointer will also make this function work types that have no definitions, which commonly happens for kernel name type.
144
        return get_simplified_type_name_from_pointer(typeid(Struct*));
1,705✔
145
}
146

147
/// Escapes "<", ">", and "&" with their corresponding HTML escape sequences
148
std::string escape_for_dot_label(std::string str);
149

150
/// Print the buffer id as either 'B1' or 'B1 "name"' (if `name` is non-empty)
151
std::string make_buffer_debug_label(const buffer_id bid, const std::string& name = "");
152

153
[[noreturn]] void unreachable();
154

155
enum class panic_solution {
156
        log_and_abort,     ///< default
157
        throw_logic_error, ///< enabled in unit tests to detect and recover from panics
158
};
159

160
/// Globally and atomically sets the behavior of `utils::panic()`.
161
void set_panic_solution(panic_solution solution);
162

163
/// Either throws or aborts with a message, depending on the global `panic_solution` setting.
164
[[noreturn]] void panic(const std::string& msg);
165

166
/// Either throws or aborts with a message, depending on the global `panic_solution` setting.
167
template <typename... FmtParams>
168
[[noreturn]] void panic(fmt::format_string<FmtParams...> fmt_string, FmtParams&&... fmt_args) {
×
169
        // TODO also receive a std::source_location with C++20.
170
        panic(fmt::format(fmt_string, std::forward<FmtParams>(fmt_args)...));
×
171
}
172

173
/// Ignores, logs, or panics on an error depending on the `error_policy`.
174
void report_error(const error_policy policy, const std::string& msg);
175

176
/// Ignores, logs, or panics on an error depending on the `error_policy`.
177
template <typename... FmtParams, std::enable_if_t<sizeof...(FmtParams) >= 1, int> = 0>
178
void report_error(const error_policy policy, const fmt::format_string<FmtParams...> fmt_string, FmtParams&&... fmt_args) {
31✔
179
        // TODO also receive a std::source_location with C++20.
180
        if(policy != error_policy::ignore) { report_error(policy, fmt::format(fmt_string, std::forward<FmtParams>(fmt_args)...)); }
79!
181
}
14✔
182

183
template <typename Container>
184
Container set_intersection(const Container& lhs, const Container& rhs) {
3✔
185
        using std::begin, std::end;
186
        assert(std::is_sorted(begin(lhs), end(lhs)));
3✔
187
        assert(std::is_sorted(begin(rhs), end(rhs)));
3✔
188
        Container intersection;
3✔
189
        std::set_intersection(begin(lhs), end(lhs), begin(rhs), end(rhs), std::back_inserter(intersection));
6✔
190
        return intersection;
3✔
NEW
191
}
×
192

193
template <typename Container, typename Key>
194
bool contains(const Container& container, const Key& key) {
6✔
195
        using std::begin, std::end;
196
        if constexpr(utils_detail::has_member_find_v<Container, Key>) {
197
                return container.find(key) != end(container);
198
        } else {
199
                return std::find(begin(container), end(container), key) != end(container);
18✔
200
        }
201
}
202

203
} // namespace celerity::detail::utils
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