utils.hpp
1 
5 #pragma once
6 
7 #include <array>
8 #include <chrono>
9 #include <cmath>
10 #include <cstdlib>
11 #include <memory>
12 #include <sstream>
13 #include <string>
14 #include <type_traits>
15 #include <utility>
16 #include <vector>
17 
18 #include <cuda.h>
19 #include <cuda_runtime_api.h>
20 
21 namespace rapidsmpf {
22 
24 using Clock = std::chrono::high_resolution_clock;
26 using Duration = std::chrono::duration<double>;
27 
36 template <typename T>
37 std::string to_precision(T value, int precision = 2) {
38  std::stringstream ss;
39  ss.precision(precision);
40  ss << std::fixed;
41  ss << value;
42  return ss.str();
43 }
44 
52 std::string inline format_nbytes(double nbytes, int precision = 2) {
53  constexpr std::array<const char*, 6> units = {" B", " KiB", " MiB", " GiB", " TiB"};
54  double n = nbytes;
55  for (auto const& unit : units) {
56  if (std::abs(n) < 1024.0) {
57  return to_precision(n, precision) + unit;
58  }
59  n /= 1024.0;
60  }
61  return to_precision(n, precision) + " PiB";
62 }
63 
71 std::string inline format_duration(double seconds, int precision = 2) {
72  double sec = std::abs(seconds);
73  if (sec < 1e-6) {
74  return to_precision(seconds * 1e9, precision) + " ns";
75  } else if (sec < 1e-3) {
76  return to_precision(seconds * 1e6, precision) + " us";
77  } else if (sec < 1) {
78  return to_precision(seconds * 1e3, precision) + " ms";
79  } else {
80  return to_precision(seconds, precision) + " s";
81  }
82 }
83 
96 template <typename MapType>
97 std::pair<typename MapType::key_type, typename MapType::mapped_type> extract_item(
98  MapType& map, typename MapType::const_iterator position
99 ) {
100  auto node = map.extract(position);
101  if (!node) {
102  throw std::out_of_range("Invalid iterator passed to extract");
103  }
104  return {std::move(node.key()), std::move(node.mapped())};
105 }
106 
117 template <typename MapType>
118 std::pair<typename MapType::key_type, typename MapType::mapped_type> extract_item(
119  MapType& map, typename MapType::key_type const& key
120 ) {
121  auto node = map.extract(key);
122  if (!node) {
123  throw std::out_of_range("Invalid key passed to extract");
124  }
125  return {std::move(node.key()), std::move(node.mapped())};
126 }
127 
139 template <typename MapType>
140 typename MapType::mapped_type extract_value(
141  MapType& map, typename MapType::key_type const& key
142 ) {
143  return std::move(extract_item(map, key).second);
144 }
145 
159 template <typename MapType>
160 typename MapType::mapped_type extract_value(
161  MapType& map, typename MapType::const_iterator position
162 ) {
163  return std::move(extract_item(map, position).second);
164 }
165 
176 template <typename MapType>
177 typename MapType::key_type extract_key(
178  MapType& map, typename MapType::key_type const& key
179 ) {
180  return std::move(extract_item(map, key).first);
181 }
182 
195 template <typename MapType>
196 typename MapType::key_type extract_key(
197  MapType& map, typename MapType::const_iterator position
198 ) {
199  return std::move(extract_item(map, position).first);
200 }
201 
212 template <typename MapType>
213 auto to_vector(MapType&& map) {
214  using ValueType = typename std::remove_reference_t<MapType>::mapped_type;
215  std::vector<ValueType> vec;
216  vec.reserve(map.size());
217  for (auto&& [key, value] : map) {
218  vec.push_back(std::move(value));
219  }
220  return vec;
221 }
222 
228 bool is_running_under_valgrind();
229 
238 template <typename T>
239 constexpr T safe_div(T x, T y) {
240  return (y == 0) ? 0 : x / y;
241 }
242 
249 std::string trim(std::string const& str);
250 
257 std::string to_lower(std::string str);
258 
265 std::string to_upper(std::string str);
266 
287 template <typename T>
288 T parse_string(std::string const& value) {
289  std::stringstream sstream(value);
290  T ret;
291  sstream >> ret;
292  if (sstream.fail()) {
293  throw std::invalid_argument("cannot parse \"" + std::string{value} + "\"");
294  }
295  return ret;
296 }
297 
312 template <>
313 bool parse_string(std::string const& value);
314 
315 // Macro to concatenate two tokens x and y.
316 #define RAPIDSMPF_CONCAT_DETAIL_(x, y) x##y
317 #define RAPIDSMPF_CONCAT(x, y) RAPIDSMPF_CONCAT_DETAIL_(x, y)
318 
319 // Stringify a macro argument.
320 #define RAPIDSMPF_STRINGIFY_DETAIL_(x) #x
321 #define RAPIDSMPF_STRINGIFY(x) RAPIDSMPF_STRINGIFY_DETAIL_(x)
322 
339 #define RAPIDSMPF_OVERLOAD_BY_ARG_COUNT(_1, _2, NAME, ...) NAME
340 
341 namespace detail {
342 
352 template <typename T>
353 constexpr T* to_pointer(T* ptr) noexcept {
354  return ptr;
355 }
356 
358 template <typename T>
359 constexpr T* to_pointer(T& ptr) noexcept {
360  return std::addressof(ptr);
361 }
362 
364 template <typename T>
365 constexpr T* to_pointer(std::unique_ptr<T>& ptr) noexcept {
366  return ptr.get();
367 }
368 
370 template <typename T>
371 constexpr T* to_pointer(std::shared_ptr<T>& ptr) noexcept {
372  return ptr.get();
373 }
374 
375 } // namespace detail
376 
378 template <class... Ts>
379 struct overloaded : Ts... {
380  using Ts::operator()...;
381 };
382 
386 #define RAPIDSMPF_CUDA_VERSION_AT_LEAST(version) (CUDART_VERSION >= version)
387 
388 
400 int get_current_numa_node_id();
401 
402 } // namespace rapidsmpf
constexpr T * to_pointer(T *ptr) noexcept
Returns the raw pointer from a pointer, reference, or smart pointer.
Definition: utils.hpp:353
Helper for overloaded lambdas using std::visit.
Definition: utils.hpp:379