A triangle counting assignment for A.U.TH Parallel and distributed systems class.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

231 linhas
8.9 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\n";
  114. std::cout << "Examples:\n\n";
  115. std::cout << " Get the total count of matrix in <MFILE> and calculate the time for vector creation 5 times:\n";
  116. std::cout << " > ./tcount -i <MFILE> --timing --print_count -r 5\n\n";
  117. std::cout << " Get the vector to <OUTFILE> of matrix in <MFILE> and print the time to stdout using dynamic scheduling\n";
  118. std::cout << " > ./tcount -i <MFILE> -o <OUTFILE> --timing --dynamic\n\n";
  119. std::cout << " Get the total count of matrix in <MFILE> using <N> workers only\n";
  120. std::cout << " > ./tcount -i <MFILE> -n <N> --print_count\n";
  121. exit(0);
  122. }
  123. else { // parse error
  124. std::cout << "Invocation error. Try -h for details.\n";
  125. status = false;
  126. }
  127. }
  128. // Input checkers
  129. if (session.inputMatrix == InputMatrix::UNSPECIFIED) {
  130. std::cout << "Invocation error. Try -h for details.\n";
  131. status = false;
  132. }
  133. #if CODE_VERSION == V4
  134. else if (!session.makeSymmetric && !session.print_count) {
  135. std::cout << "\"--triangular_only\" requires \"--print_count\"\n";
  136. status = false;
  137. }
  138. #endif
  139. return status;
  140. }
  141. /*!
  142. * get or generate matrix
  143. * \param A Reference to matrix for output (move using RVO)
  144. * \param timer Reference to timer utility to access time printing functionality
  145. */
  146. void prepare_matrix (matrix& A, Timing& timer) {
  147. if (session.inputMatrix == InputMatrix::GENERATE) {
  148. logger << "Initialize matrix with size: " << session.gen_size << " and probability: " << session.gen_prob << logger.endl;
  149. timer.start();
  150. A.size(session.gen_size);
  151. init_ER_graph(A, session.gen_prob);
  152. timer.stop();
  153. timer.print_dt("generate matrix");
  154. }
  155. else {
  156. logger << "Read matrix from file" << logger.endl;
  157. timer.start();
  158. if (session.validate_mtx && !Mtx::is_triangular<matrix::indexType> (session.mtxFile))
  159. throw std::runtime_error("Error: Matrix is not strictly upper or lower");
  160. if (!Mtx::load (A, session.mtxFile)) {
  161. throw std::runtime_error("Error: fail to load matrix");
  162. }
  163. timer.stop();
  164. logger << "Matrix size: " << A.size() << " and capacity: " << A.capacity() << logger.endl;
  165. timer.print_dt("load matrix");
  166. }
  167. if (session.mtx_print) {
  168. logger << "\nMatrix:" << logger.endl;
  169. print_graph (A);
  170. }
  171. }
  172. /*
  173. * main program
  174. */
  175. int main(int argc, char* argv[]) try {
  176. Timing timer;
  177. matrix A;
  178. std::vector<value_t> c;
  179. index_t s;
  180. #if defined ELEARNING
  181. if (!elearn_test()) std::cout << "E-learning test: FAIL\n";
  182. else std::cout << "E-learning test: PASS\n";
  183. exit(0);
  184. #endif
  185. // try to read command line
  186. if (!get_options(argc, argv))
  187. exit(1);
  188. prepare_matrix(A, timer);
  189. threads_info();
  190. for (size_t i =0 ; i<session.repeat ; ++i) {
  191. // repeat calculations as requested by user
  192. logger << "Create vector" << logger.endl;
  193. timer.start();
  194. c = triang_v (A);
  195. timer.stop();
  196. timer.print_dt("create vector");
  197. }
  198. if (session.print_count) {
  199. logger << "Calculate total triangles" << logger.endl;
  200. timer.start();
  201. s = triang_count(c);
  202. timer.stop();
  203. logger << "There are " << s << " triangles" << logger.endl;
  204. timer.print_dt("calculate sum");
  205. }
  206. // output results
  207. if (session.print_count)
  208. triangle_out (s, (session.outputMode == OutputMode::FILE) ? session.outFile : std::cout);
  209. else
  210. vector_out (c, (session.outputMode == OutputMode::FILE) ? session.outFile : std::cout);
  211. return 0;
  212. }
  213. catch (std::exception& e) {
  214. //we probably pollute the user's screen. Comment `cerr << ...` if you don't like it.
  215. std::cerr << e.what() << '\n';
  216. exit(1);
  217. }