AUTH's THMMY "Parallel and distributed systems" course assignments.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

244 lignes
8.2 KiB

  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 <mpi.h>
  16. //#include "matrix.hpp"
  17. #include "config.h"
  18. template <typename T> struct MPI_TypeMapper;
  19. // Specializations for supported types
  20. template <> struct MPI_TypeMapper<char> { static MPI_Datatype getType() { return MPI_CHAR; } };
  21. template <> struct MPI_TypeMapper<unsigned char> { static MPI_Datatype getType() { return MPI_UNSIGNED_CHAR; } };
  22. template <> struct MPI_TypeMapper<short> { static MPI_Datatype getType() { return MPI_SHORT; } };
  23. template <> struct MPI_TypeMapper<int> { static MPI_Datatype getType() { return MPI_INT; } };
  24. template <> struct MPI_TypeMapper<long> { static MPI_Datatype getType() { return MPI_LONG; } };
  25. template <> struct MPI_TypeMapper<long long> { static MPI_Datatype getType() { return MPI_LONG_LONG; } };
  26. template <> struct MPI_TypeMapper<unsigned short>{ static MPI_Datatype getType() { return MPI_UNSIGNED_SHORT; } };
  27. template <> struct MPI_TypeMapper<unsigned long> { static MPI_Datatype getType() { return MPI_UNSIGNED_LONG; } };
  28. template <> struct MPI_TypeMapper<unsigned long long> { static MPI_Datatype getType() { return MPI_UNSIGNED_LONG_LONG; } };
  29. template<typename TID = int>
  30. struct MPI_t {
  31. using ID_t = TID; // Export TID type (currently int defined by the standard)
  32. void init(int *argc, char ***argv) {
  33. // Initialize the MPI environment
  34. MPI_Init(argc, argv);
  35. // Get the number of processes
  36. int size_value, rank_value;
  37. MPI_Comm_size(MPI_COMM_WORLD, &size_value);
  38. MPI_Comm_rank(MPI_COMM_WORLD, &rank_value);
  39. size_ = static_cast<ID_t>(size_value);
  40. rank_ = static_cast<ID_t>(rank_value);
  41. // Get the name of the processor
  42. char processor_name[MPI_MAX_PROCESSOR_NAME];
  43. int name_len;
  44. MPI_Get_processor_name(processor_name, &name_len);
  45. name_ = std::string (processor_name, name_len);
  46. }
  47. void finalize() {
  48. // Finalize the MPI environment.
  49. MPI_Finalize();
  50. }
  51. template<typename T>
  52. void exchange(ID_t partner, const std::vector<T>& send_data, std::vector<T>& recv_data, int tag) {
  53. using namespace std::string_literals;
  54. MPI_Status status;
  55. MPI_Datatype datatype = MPI_TypeMapper<T>::getType();
  56. int send_count = static_cast<int>(send_data.size());
  57. int err = MPI_Sendrecv(
  58. send_data.data(), send_count, datatype, partner, tag,
  59. recv_data.data(), send_count, datatype, partner, tag,
  60. MPI_COMM_WORLD, &status
  61. );
  62. if (err != MPI_SUCCESS) {
  63. char err_msg[MPI_MAX_ERROR_STRING];
  64. int msg_len;
  65. MPI_Error_string(err, err_msg, &msg_len);
  66. throw std::runtime_error("(MPI) MPI_Sendrecv() - " + std::string (err_msg) + '\n');
  67. }
  68. }
  69. // Accessors
  70. [[nodiscard]] ID_t rank() const noexcept { return rank_; }
  71. [[nodiscard]] ID_t size() const noexcept { return size_; }
  72. [[nodiscard]] const std::string& name() const noexcept { return name_; }
  73. private:
  74. ID_t rank_{};
  75. ID_t size_{};
  76. std::string name_{};
  77. };
  78. extern MPI_t<> mpi;
  79. using mpi_id_t = MPI_t<>::ID_t;
  80. template <typename Value_t>
  81. struct ShadowedVec_t {
  82. // STL requirements
  83. using value_type = Value_t;
  84. using iterator = typename std::vector<Value_t>::iterator;
  85. using const_iterator = typename std::vector<Value_t>::const_iterator;
  86. using size_type = typename std::vector<Value_t>::size_type;
  87. // Dispatch to active vector
  88. Value_t& operator[](size_type index) { return getActive()[index]; }
  89. const Value_t& operator[](size_type index) const { return getActive()[index]; }
  90. Value_t& at(size_type index) { return getActive().at(index); }
  91. const Value_t& at(size_type index) const { return getActive().at(index); }
  92. void push_back(const Value_t& value) { getActive().push_back(value); }
  93. void push_back(Value_t&& value) { getActive().push_back(std::move(value)); }
  94. void pop_back() { getActive().pop_back(); }
  95. Value_t& front() { return getActive().front(); }
  96. const Value_t& front() const { return getActive().front(); }
  97. Value_t& back() { return getActive().back(); }
  98. const Value_t& back() const { return getActive().back(); }
  99. iterator begin() { return getActive().begin(); }
  100. const_iterator begin() const { return getActive().begin(); }
  101. iterator end() { return getActive().end(); }
  102. const_iterator end() const { return getActive().end(); }
  103. size_type size() const { return getActive().size(); }
  104. void resize(size_t new_size) {
  105. North.resize(new_size);
  106. South.resize(new_size);
  107. }
  108. void reserve(size_t new_capacity) {
  109. North.reserve(new_capacity);
  110. South.reserve(new_capacity);
  111. }
  112. [[nodiscard]] size_t capacity() const { return getActive().capacity(); }
  113. [[nodiscard]] bool empty() const { return getActive().empty(); }
  114. void clear() { getActive().clear(); }
  115. void swap(std::vector<Value_t>& other) { getActive().swap(other); }
  116. // Switching vectors
  117. void switch_active() { active = (active == north) ? south : north; }
  118. // Accessors
  119. const std::vector<Value_t>& getNorth() const { return North; }
  120. const std::vector<Value_t>& getSouth() const { return South; }
  121. std::vector<Value_t>& getActive() {
  122. return (active == north) ? North : South;
  123. }
  124. const std::vector<Value_t>& getActive() const {
  125. return (active == north) ? North : South;
  126. }
  127. std::vector<Value_t>& getShadow() {
  128. return (active == north) ? South : North;
  129. }
  130. const std::vector<Value_t>& getShadow() const {
  131. return (active == north) ? South : North;
  132. }
  133. private:
  134. enum { north, south } active{north};
  135. std::vector<Value_t> North{};
  136. std::vector<Value_t> South{};
  137. };
  138. using distBuffer_t = ShadowedVec_t<distValue_t>;
  139. extern distBuffer_t Data;
  140. /*!
  141. * A Logger for entire program.
  142. */
  143. struct Log {
  144. struct Endl {} endl; //!< a tag object to to use it as a new line request.
  145. //! We provide logging via << operator
  146. template<typename T>
  147. Log &operator<<(T &&t) {
  148. if (session.verbose) {
  149. if (line_) {
  150. std::cout << "[Log]: " << t;
  151. line_ = false;
  152. } else
  153. std::cout << t;
  154. }
  155. return *this;
  156. }
  157. // overload for special end line handling
  158. Log &operator<<(Endl e) {
  159. (void) e;
  160. if (session.verbose) {
  161. std::cout << '\n';
  162. line_ = true;
  163. }
  164. return *this;
  165. }
  166. private:
  167. bool line_{true};
  168. };
  169. extern Log logger;
  170. /*!
  171. * A small timing utility based on chrono.
  172. */
  173. struct Timing {
  174. using Tpoint = std::chrono::steady_clock::time_point;
  175. using microseconds = std::chrono::microseconds;
  176. using milliseconds = std::chrono::milliseconds;
  177. using seconds = std::chrono::seconds;
  178. //! tool to mark the starting point
  179. Tpoint start() noexcept { return start_ = std::chrono::steady_clock::now(); }
  180. //! tool to mark the ending point
  181. Tpoint stop() noexcept { return stop_ = std::chrono::steady_clock::now(); }
  182. auto dt() noexcept {
  183. return std::chrono::duration_cast<std::chrono::microseconds>(stop_ - start_).count();
  184. }
  185. //! tool to print the time interval
  186. void print_dt(const char *what) noexcept {
  187. if (session.timing) {
  188. auto t = stop_ - start_;
  189. if (std::chrono::duration_cast<microseconds>(t).count() < 10000)
  190. std::cout << "[Timing]: " << what << ": "
  191. << std::to_string(std::chrono::duration_cast<microseconds>(t).count()) << " [usec]\n";
  192. else if (std::chrono::duration_cast<milliseconds>(t).count() < 10000)
  193. std::cout << "[Timing]: " << what << ": "
  194. << std::to_string(std::chrono::duration_cast<milliseconds>(t).count()) << " [msec]\n";
  195. else
  196. std::cout << "[Timing]: " << what << ": "
  197. << std::to_string(std::chrono::duration_cast<seconds>(t).count()) << " [sec]\n";
  198. }
  199. }
  200. private:
  201. Tpoint start_;
  202. Tpoint stop_;
  203. };
  204. #endif /* UTILS_HPP_ */