A triangle counting assignment for A.U.TH Parallel and distributed systems class.
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.
 
 
 
 
 
 

282 lignes
8.1 KiB

  1. /*!
  2. * \file utils.h
  3. * \brief Utilities to handle matrix files, chrono, etc...
  4. *
  5. * \author
  6. * Christos Choutouridis AEM:8997
  7. * <cchoutou@ece.auth.gr>
  8. */
  9. #ifndef UTILS_H_
  10. #define UTILS_H_
  11. #include <string>
  12. #include <sstream>
  13. #include <iostream>
  14. #include <chrono>
  15. #include <random>
  16. #include <impl.hpp>
  17. #include <config.h>
  18. /*!
  19. * A small RAII utility to memory allocation arrays.
  20. * @tparam T The type of pointer for the memory
  21. */
  22. template <typename T>
  23. struct buffer_t {
  24. buffer_t(size_t s) { p = new T[s]; }
  25. ~buffer_t() { delete[] p; }
  26. buffer_t() = default;
  27. buffer_t(buffer_t&&) = default;
  28. buffer_t& operator=(buffer_t&&) = default;
  29. buffer_t(const buffer_t&) = delete;
  30. buffer_t& operator=(const buffer_t&) = delete;
  31. T* allocate(size_t s) { return p = new T[s]; }
  32. T* operator() () { return p; }
  33. T& operator[] (size_t i){ return p[i]; }
  34. private:
  35. T* p{nullptr};
  36. };
  37. /*!
  38. * A toolbox for MatrixMarket format handling
  39. */
  40. struct Mtx {
  41. /*!
  42. * A template version of the coo2csc function provided by PDS lab stuff.
  43. */
  44. template<typename I>
  45. static void coo2csc(I *row, I *col, I const* row_coo, I const* col_coo, I nnz, I n, I isOneBased) {
  46. // ----- cannot assume that input is already 0!
  47. for (I l = 0; l < n+1; l++) col[l] = 0;
  48. // ----- find the correct column sizes
  49. for (I l = 0; l < nnz; l++)
  50. col[col_coo[l] - isOneBased]++;
  51. // ----- cumulative sum
  52. for (I i = 0, cumsum = 0; i < n; i++) {
  53. I temp = col[i];
  54. col[i] = cumsum;
  55. cumsum += temp;
  56. }
  57. col[n] = nnz;
  58. // ----- copy the row indices to the correct place
  59. for (I l = 0; l < nnz; l++) {
  60. I col_l;
  61. col_l = col_coo[l] - isOneBased;
  62. I dst = col[col_l];
  63. row[dst] = row_coo[l] - isOneBased;
  64. col[col_l]++;
  65. }
  66. // ----- revert the column pointers
  67. for (I i = 0, last = 0; i < n; i++) {
  68. I temp = col[i];
  69. col[i] = last;
  70. last = temp;
  71. }
  72. }
  73. /*!
  74. * Utility to check if a matrix input is strictly triangular or not.
  75. * @tparam I Index type
  76. * @param file Reference to input file stream
  77. * @return The status of the operation
  78. */
  79. template<typename I>
  80. static bool is_triangular (std::ifstream& file) {
  81. std::string line, token;
  82. enum state_en {HEADER, SIZE, DATA} state = HEADER;
  83. enum LU_t {Z, LOWER, UPPER} LU = Z;
  84. while (std::getline (file, line, '\n')) {
  85. std::stringstream ss(line);
  86. switch (state) {
  87. case HEADER:
  88. ss >> token;
  89. if (token != "%%MatrixMarket") return false;
  90. else state = SIZE;
  91. break;
  92. case SIZE:
  93. if (line[0] == '%') continue;
  94. else state = DATA;
  95. break;
  96. case DATA:
  97. if (line[0] == '%') continue;
  98. I i, j;
  99. ss >> i >> j;
  100. switch (LU) {
  101. case Z: LU = (i<j) ? UPPER: LOWER; break;
  102. case LOWER: if (i<=j) return false; break;
  103. case UPPER: if (j<=i) return false; break;
  104. }
  105. break;
  106. }
  107. }
  108. file.clear(); // rewind
  109. file.seekg(0);
  110. return true;
  111. }
  112. /*!
  113. * A utility to load an MatrixMarket file to memory
  114. * @tparam DataT The data type
  115. * @tparam IndexT The indexes type
  116. * @param M Reference to matrix for output
  117. * @param file Reference to input file stream to read from
  118. * @return The status of the operation
  119. */
  120. template<typename DataT, typename IndexT, MatrixType MatrixT>
  121. static bool load (SpMat<DataT, IndexT, MatrixT>& M, std::ifstream& file) {
  122. std::string line, token;
  123. enum state_en {HEADER, SIZE, DATA} state = HEADER;
  124. enum LU_t {Z, LOWER, UPPER} LU = Z;
  125. IndexT n1, n2, nnz;
  126. buffer_t<IndexT> col{}, row{}, coo_col{}, coo_row{};
  127. IndexT cnt{};
  128. while (std::getline (file, line, '\n')) {
  129. std::stringstream ss(line);
  130. switch (state) {
  131. case HEADER:
  132. ss >> token;
  133. if (token != "%%MatrixMarket") return false;
  134. else state = SIZE;
  135. break;
  136. case SIZE:
  137. if (line[0] == '%') continue;
  138. else {
  139. ss >> n1 >> n2 >> nnz;
  140. if (session.makeSymmetric)
  141. nnz *= 2;
  142. col.allocate(nnz);
  143. row.allocate(nnz);
  144. coo_col.allocate(nnz);
  145. coo_row.allocate(nnz);
  146. state = DATA;
  147. }
  148. break;
  149. case DATA:
  150. if (line[0] == '%') continue;
  151. IndexT i, j;
  152. ss >> i >> j;
  153. if (LU == Z) {
  154. LU = (i<j) ? UPPER: LOWER;
  155. }
  156. // ignore all values outside the triangle area
  157. if ((LU==LOWER && j<i) || (LU==UPPER && i<j)) {
  158. coo_row[cnt] = i;
  159. coo_col[cnt++] = j;
  160. if (session.makeSymmetric) {
  161. coo_row[cnt] = j;
  162. coo_col[cnt++] = i;
  163. }
  164. }
  165. break;
  166. }
  167. }
  168. if (cnt) {
  169. // convert and construct
  170. coo2csc(&row[0], &col[0], &coo_row[0], &coo_col[0], cnt, n1, 1);
  171. M = SpMat<DataT, IndexT, MatrixT>(n1, cnt, &row[0], &col[0]);
  172. return true;
  173. }
  174. return false;
  175. }
  176. };
  177. /*!
  178. * A small timing utility based on chrono.
  179. */
  180. struct Timing{
  181. using Tpoint = std::chrono::steady_clock::time_point;
  182. using microseconds = std::chrono::microseconds;
  183. using milliseconds = std::chrono::milliseconds;
  184. using seconds = std::chrono::seconds;
  185. //! tool to mark the starting point
  186. Tpoint start () noexcept { return start_ = std::chrono::steady_clock::now(); }
  187. //! tool to mark the ending point
  188. Tpoint stop () noexcept { return stop_ = std::chrono::steady_clock::now(); }
  189. auto dt () noexcept {
  190. return std::chrono::duration_cast<std::chrono::microseconds>(stop_ - start_).count();
  191. }
  192. //! tool to print the time interval
  193. void print_dt (const char* what) noexcept {
  194. if (session.timing) {
  195. auto t = stop_ - start_;
  196. if (std::chrono::duration_cast<microseconds>(t).count() < 10000)
  197. std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast<microseconds>(t).count()) << " [usec]\n";
  198. else if (std::chrono::duration_cast<milliseconds>(t).count() < 10000)
  199. std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast<milliseconds>(t).count()) << " [msec]\n";
  200. else
  201. std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast<seconds>(t).count()) << " [sec]\n";
  202. }
  203. }
  204. private:
  205. Tpoint start_;
  206. Tpoint stop_;
  207. };
  208. /*!
  209. * A Logger for entire program.
  210. */
  211. struct Log {
  212. struct Endl {} endl; //!< a tag object to to use it as a new line request.
  213. //! We provide logging via << operator
  214. template<typename T>
  215. Log& operator<< (T&& t) {
  216. if (session.verbose) {
  217. if (line_) {
  218. std::cout << "[Log]: " << t;
  219. line_ = false;
  220. }
  221. else
  222. std::cout << t;
  223. }
  224. return *this;
  225. }
  226. // overload for special end line handling
  227. Log& operator<< (Endl e) { (void)e;
  228. if (session.verbose) {
  229. std::cout << '\n';
  230. line_ = true;
  231. }
  232. return *this;
  233. }
  234. private:
  235. bool line_ {true};
  236. };
  237. extern Log logger;
  238. //! Total count result printing function
  239. template<typename F>
  240. void triangle_out (value_t s, F&& f) {
  241. f << "Total triangles: " << s << '\n';
  242. }
  243. //! vector out result printing function
  244. template<typename F>
  245. void vector_out (std::vector<value_t>& v, F&& f) {
  246. size_t idx{};
  247. f << "id,c3\n";
  248. for (auto& it : v) f << idx++ <<',' << it << '\n';
  249. f << '\n';
  250. }
  251. /*
  252. * Public non-template api.
  253. * We use matrix alias template. So it has to be defined somewhere
  254. */
  255. void init_ER_graph (matrix& A, double p);
  256. void print_graph (matrix& A);
  257. void threads_info ();
  258. #endif /* UTILS_H_ */