A triangle counting assignment for A.U.TH Parallel and distributed systems class.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

224 Zeilen
8.3 KiB

  1. /*!
  2. * \file main.cpp
  3. * \brief Main application file
  4. *
  5. * \author
  6. * Christos Choutouridis AEM:8997
  7. * <cchoutou@ece.auth.gr>
  8. */
  9. #include <iostream>
  10. #include <string>
  11. #include <exception>
  12. #include <utils.h>
  13. #include <config.h>
  14. // Global session data
  15. session_t session;
  16. Log logger;
  17. /*!
  18. * A small command line argument parser
  19. * \return The status of the operation
  20. */
  21. bool get_options(int argc, char* argv[]){
  22. bool status =true;
  23. // iterate over the passed arguments
  24. for (int i=1 ; i<argc ; ++i) {
  25. std::string arg(argv[i]); // get current argument
  26. if (arg == "-i" || arg == "--input") {
  27. session.inputMatrix = InputMatrix::MTX;
  28. if (i+1 < argc)
  29. session.mtxFile = std::ifstream(argv[++i]);
  30. else
  31. status = false;
  32. }
  33. else if (arg == "-o" || arg == "--output") {
  34. session.outputMode = OutputMode::FILE;
  35. if (i+1 < argc)
  36. session.outFile = std::ofstream(argv[++i]);
  37. else
  38. status = false;
  39. }
  40. else if (arg == "-g" || arg == "--generate") {
  41. session.inputMatrix = InputMatrix::GENERATE;
  42. if (i+2 < argc) {
  43. session.gen_size = std::atoi(argv[++i]);
  44. session.gen_prob = std::atof(argv[++i]);
  45. }
  46. else
  47. status = false;
  48. }
  49. else if (arg == "-n" || arg == "--max_trheads") {
  50. session.max_threads = (i+1 < argc) ? std::atoi(argv[++i]) : session.max_threads;
  51. }
  52. else if (arg == "-r" || arg == "--repeat") {
  53. session.repeat = (i+1 < argc) ? std::atoi(argv[++i]) : session.repeat;
  54. }
  55. else if (arg == "-t" || arg == "--timing")
  56. session.timing = true;
  57. else if (arg == "-v" || arg == "--verbose")
  58. session.verbose = true;
  59. else if (arg == "--make_symmetric")
  60. session.makeSymmetric = true;
  61. else if (arg == "--triangular_only")
  62. session.makeSymmetric = false;
  63. else if (arg == "--validate_mtx")
  64. session.validate_mtx = true;
  65. else if (arg == "--dynamic")
  66. session.dynamic = true;
  67. else if (arg == "--print_count") {
  68. session.print_count = true;
  69. session.makeSymmetric = false;
  70. }
  71. else if (arg == "--print_graph") {
  72. session.mtx_print = true;
  73. session.mtx_print_size = (i+1 < argc) ? std::atoi(argv[++i]) : session.mtx_print_size;
  74. }
  75. else if (arg == "-h" || arg == "--help") {
  76. std::cout << "vertex-wise triangular count utility.\n\n";
  77. std::cout << "tcount -i <file> | -g <size> <probability> [-o <file>] [-n <threads>] [--dynamic] [-r <times>] [-t] [-v]\n";
  78. std::cout << " [--make_symmetric] [--triangular_only] [--print_count] [--validate_mtx] [--print_graph <size>]\n";
  79. std::cout << '\n';
  80. std::cout << "Options:\n\n";
  81. std::cout << " -i | --input <file>\n";
  82. std::cout << " Path to mtx file to load.\n\n";
  83. std::cout << " -g | --generate <size> <probability>\n";
  84. std::cout << " Request a random generated graph with size <size> and probability <probability>.\n";
  85. std::cout << " This is very slow, use it with care.\n\n";
  86. std::cout << " -o | --output <file>\n";
  87. std::cout << " Select <file> as output file. Default is stdout.\n\n";
  88. std::cout << " -n | --max_trheads <threads>\n";
  89. std::cout << " Reduce the thread number for the execution to <threads>. <threads> must be less or equal to available CPUs.\n\n";
  90. std::cout << " --dynamic\n";
  91. std::cout << " Request of dynamic scheduling for OpenMP and pthreads. Does not affect cilk versions.\n\n";
  92. std::cout << " -r | --repeat <times>\n";
  93. std::cout << " Repeat the vector calculation <times> times.\n\n";
  94. std::cout << " -t | --timing\n";
  95. std::cout << " Request timing measurements output to stdout.\n\n";
  96. std::cout << " -v | --verbose\n";
  97. std::cout << " Request a more verbose output to stdout.\n\n";
  98. std::cout << " --make_symmetric\n";
  99. std::cout << " Explicitly request a symmetric graph generation. This affects only V3 versions where by default a lower\n";
  100. std::cout << " triangular matrix is used.\n\n";
  101. std::cout << " --triangular_only\n";
  102. std::cout << " NOTE: Requires also \"--print_count\".\n";
  103. std::cout << " Explicitly request to use a lower triangular matrix. This affects only V4 versions where a symmetric\n";
  104. std::cout << " matrix is used by default and produce correct answer ONLY for total triangle counting (--print_count).\n\n";
  105. std::cout << " --print_count\n";
  106. std::cout << " NOTE: When used, also implies \"---triangular_only\" for all versions.\n";
  107. std::cout << " Request a total triangle counting output.\n\n";
  108. std::cout << " --validate_mtx\n";
  109. std::cout << " Request an input matrix validation before execution.\n\n";
  110. std::cout << " --print_graph <size>\n";
  111. std::cout << " Prints the first <size> x <size> part of the matrix to stdout.\n\n";
  112. std::cout << " -h | --help <size>\n";
  113. std::cout << " Prints this and exit.\n";
  114. exit(0);
  115. }
  116. else { // parse error
  117. std::cout << "Invokation error. Try -h for details.\n";
  118. status = false;
  119. }
  120. }
  121. // Input checkers
  122. if (session.inputMatrix == InputMatrix::UNSPECIFIED) {
  123. std::cout << "Error message\n";
  124. status = false;
  125. }
  126. #if CODE_VERSION == V4
  127. else if (!session.makeSymmetric && !session.print_count) {
  128. std::cout << "\"--triangular_only\" requires \"--print_count\"\n";
  129. status = false;
  130. }
  131. #endif
  132. return status;
  133. }
  134. /*!
  135. * get or generate matrix
  136. * \param A Reference to matrix for output (move using RVO)
  137. * \param timer Reference to timer utility to access time printing functionality
  138. */
  139. void prepare_matrix (matrix& A, Timing& timer) {
  140. if (session.inputMatrix == InputMatrix::GENERATE) {
  141. logger << "Initialize matrix with size: " << session.gen_size << " and probability: " << session.gen_prob << logger.endl;
  142. timer.start();
  143. A.size(session.gen_size);
  144. init_ER_graph(A, session.gen_prob);
  145. timer.stop();
  146. timer.print_dt("generate matrix");
  147. }
  148. else {
  149. logger << "Read matrix from file" << logger.endl;
  150. timer.start();
  151. if (session.validate_mtx && !Mtx::is_triangular<matrix::indexType> (session.mtxFile))
  152. throw std::runtime_error("Error: Matrix is not strictly upper or lower");
  153. if (!Mtx::load (A, session.mtxFile)) {
  154. throw std::runtime_error("Error: fail to load matrix");
  155. }
  156. timer.stop();
  157. logger << "Matrix size: " << A.size() << " and capacity: " << A.capacity() << logger.endl;
  158. timer.print_dt("load matrix");
  159. }
  160. if (session.verbose && session.mtx_print) {
  161. logger << "\nMatrix:" << logger.endl;
  162. print_graph (A);
  163. }
  164. }
  165. /*
  166. * main program
  167. */
  168. int main(int argc, char* argv[]) try {
  169. Timing timer;
  170. matrix A;
  171. std::vector<value_t> c;
  172. index_t s;
  173. #if defined ELEARNING
  174. if (!elearn_test()) std::cout << "E-learning test: FAIL\n";
  175. else std::cout << "E-learning test: PASS\n";
  176. exit(0);
  177. #endif
  178. // try to read command line
  179. if (!get_options(argc, argv))
  180. exit(1);
  181. prepare_matrix(A, timer);
  182. threads_info();
  183. for (size_t i =0 ; i<session.repeat ; ++i) {
  184. // repeat calculations as requested by user
  185. logger << "Create vector" << logger.endl;
  186. timer.start();
  187. c = triang_v (A);
  188. timer.stop();
  189. timer.print_dt("create vector");
  190. }
  191. if (session.print_count) {
  192. logger << "Calculate total triangles" << logger.endl;
  193. timer.start();
  194. s = triang_count(c);
  195. timer.stop();
  196. logger << "There are " << s << " triangles" << logger.endl;
  197. timer.print_dt("calculate sum");
  198. }
  199. // output results
  200. if (session.print_count)
  201. triangle_out (s, (session.outputMode == OutputMode::FILE) ? session.outFile : std::cout);
  202. else
  203. vector_out (c, (session.outputMode == OutputMode::FILE) ? session.outFile : std::cout);
  204. return 0;
  205. }
  206. catch (std::exception& e) {
  207. //we probably pollute the user's screen. Comment `cerr << ...` if you don't like it.
  208. std::cerr << e.what() << '\n';
  209. exit(1);
  210. }