AUTH's THMMY "Parallel and distributed systems" course assignments.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

utils.hpp 4.3 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /**
  2. * \file
  3. * \brief Utilities header
  4. *
  5. * \author
  6. * Christos Choutouridis AEM:8997
  7. * <cchoutou@ece.auth.gr>
  8. */
  9. #ifndef UTILS_HPP_
  10. #define UTILS_HPP_
  11. #include <vector>
  12. #include <iostream>
  13. #include <chrono>
  14. #include <unistd.h>
  15. #include <algorithm>
  16. #include "config.h"
  17. /*!
  18. * A Logger for entire program.
  19. */
  20. struct Log {
  21. struct Endl {} endl; //!< a tag object to to use it as a new line request.
  22. //! We provide logging via << operator
  23. template<typename T>
  24. Log &operator<<(T &&t) {
  25. if (config.verbose) {
  26. if (line_) {
  27. std::cout << "[Log]: " << t;
  28. line_ = false;
  29. } else
  30. std::cout << t;
  31. }
  32. return *this;
  33. }
  34. // overload for special end line handling
  35. Log &operator<<(Endl e) {
  36. (void) e;
  37. if (config.verbose) {
  38. std::cout << '\n';
  39. line_ = true;
  40. }
  41. return *this;
  42. }
  43. private:
  44. bool line_{true};
  45. };
  46. extern Log logger;
  47. /*!
  48. * A small timing utility based on chrono that supports timing rounds
  49. * and returning the median of them. Time can accumulate to the measurement
  50. * for each round.
  51. */
  52. struct Timing {
  53. using Tpoint = std::chrono::steady_clock::time_point;
  54. using Tduration = std::chrono::microseconds;
  55. using microseconds = std::chrono::microseconds;
  56. using milliseconds = std::chrono::milliseconds;
  57. using seconds = std::chrono::seconds;
  58. //! Setup measurement rounds
  59. void init(size_t rounds) {
  60. duration_.resize(rounds);
  61. for (auto& d : duration_)
  62. d = Tduration::zero();
  63. }
  64. //! tool to mark the starting point
  65. Tpoint start() noexcept { return mark_ = std::chrono::steady_clock::now(); }
  66. //! tool to mark the ending point
  67. Tpoint stop() noexcept {
  68. Tpoint now = std::chrono::steady_clock::now();
  69. duration_[current_] += dt(now, mark_);
  70. return now;
  71. }
  72. //! Switch timing slot
  73. void next() noexcept {
  74. ++current_;
  75. current_ %= duration_.size();
  76. }
  77. Tduration& median() noexcept {
  78. std::sort(duration_.begin(), duration_.end());
  79. return duration_[duration_.size()/2];
  80. }
  81. //! A duration calculation utility
  82. static Tduration dt(Tpoint t2, Tpoint t1) noexcept {
  83. return std::chrono::duration_cast<Tduration>(t2 - t1);
  84. }
  85. //! Tool to print the time interval
  86. static void print_duration(const Tduration& duration, const char *what) noexcept {
  87. if (std::chrono::duration_cast<microseconds>(duration).count() < 10000)
  88. std::cout << "[Timing] " << what << ": "
  89. << std::to_string(std::chrono::duration_cast<microseconds>(duration).count()) << " [usec]\n";
  90. else if (std::chrono::duration_cast<milliseconds>(duration).count() < 10000)
  91. std::cout << "[Timing] " << what << ": "
  92. << std::to_string(std::chrono::duration_cast<milliseconds>(duration).count()) << " [msec]\n";
  93. else {
  94. char stime[26]; // fit ulong
  95. auto sec = std::chrono::duration_cast<seconds>(duration).count();
  96. auto msec = (std::chrono::duration_cast<milliseconds>(duration).count() % 1000) / 10; // keep 2 digit
  97. std::sprintf(stime, "%ld.%1ld", sec, msec);
  98. std::cout << "[Timing] " << what << ": " << stime << " [sec]\n";
  99. }
  100. }
  101. private:
  102. size_t current_{0};
  103. Tpoint mark_{};
  104. std::vector<Tduration> duration_{1};
  105. };
  106. /*!
  107. * A "high level function"-like utility macro to forward a function call
  108. * and accumulate the execution time to the corresponding timing object.
  109. *
  110. * @param Tim The Timing object [Needs to have methods start() and stop()]
  111. * @param Func The function name
  112. * @param ... The arguments to pass to function (the preprocessor way)
  113. */
  114. #define timeCall(Tim, Func, ...) \
  115. Tim.start(); \
  116. Func(__VA_ARGS__); \
  117. Tim.stop(); \
  118. /*!
  119. * A utility to check if a number is power of two
  120. *
  121. * @tparam Integral The integral type of the number to check
  122. * @param x The number to check
  123. * @return True if it is power of 2, false otherwise
  124. */
  125. template <typename Integral>
  126. constexpr inline bool isPowerOfTwo(Integral x) noexcept {
  127. return (!(x & (x - 1)) && x);
  128. }
  129. #endif /* UTILS_HPP_ */