ssca.cpp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  1. // Copyright 2004 The Trustees of Indiana University.
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Nick Edmonds
  6. // Andrew Lumsdaine
  7. #include <boost/graph/use_mpi.hpp>
  8. #define CSR
  9. #ifdef CSR
  10. # include <boost/graph/distributed/compressed_sparse_row_graph.hpp>
  11. #else
  12. # include <boost/graph/distributed/adjacency_list.hpp>
  13. #endif
  14. #include <boost/test/minimal.hpp>
  15. #include <boost/graph/distributed/mpi_process_group.hpp>
  16. #include <boost/graph/distributed/queue.hpp>
  17. #include <boost/graph/parallel/distribution.hpp>
  18. #include <boost/lexical_cast.hpp>
  19. #include <boost/bind.hpp>
  20. #include <sys/time.h>
  21. #include <time.h>
  22. #include <boost/random.hpp>
  23. #include <boost/property_map/parallel/distributed_property_map.hpp>
  24. #include <boost/random/linear_congruential.hpp>
  25. #include <boost/graph/distributed/graphviz.hpp>
  26. #include <boost/graph/graph_traits.hpp>
  27. #include <boost/graph/iteration_macros.hpp>
  28. #include <boost/graph/parallel/algorithm.hpp>
  29. #include <boost/graph/breadth_first_search.hpp>
  30. #include <boost/pending/queue.hpp>
  31. #include <boost/graph/rmat_graph_generator.hpp>
  32. #include <boost/graph/distributed/betweenness_centrality.hpp>
  33. #include <boost/graph/distributed/filtered_graph.hpp>
  34. #include <boost/graph/parallel/container_traits.hpp>
  35. #include <boost/graph/properties.hpp>
  36. #include <algorithm>
  37. #include <vector>
  38. #include <string>
  39. #include <iostream>
  40. #include <iomanip>
  41. #include <fstream>
  42. #include <string>
  43. #include <sstream>
  44. #include <stdint.h>
  45. using namespace boost;
  46. // #define DEBUG
  47. typedef rand48 RandomGenerator;
  48. /****************************************************************************
  49. * Timing
  50. ****************************************************************************/
  51. #ifndef PBGL_ACCOUNTING
  52. typedef double time_type;
  53. inline time_type get_time()
  54. {
  55. timeval tp;
  56. gettimeofday(&tp, 0);
  57. return tp.tv_sec + tp.tv_usec / 1000000.0;
  58. }
  59. std::string print_time(time_type t)
  60. {
  61. std::ostringstream out;
  62. out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
  63. return out.str();
  64. }
  65. #endif // PBGL_ACCOUNTING
  66. /****************************************************************************
  67. * Edge weight generator iterator *
  68. ****************************************************************************/
  69. template<typename F, typename RandomGenerator>
  70. class generator_iterator
  71. {
  72. public:
  73. typedef std::input_iterator_tag iterator_category;
  74. typedef typename F::result_type value_type;
  75. typedef const value_type& reference;
  76. typedef const value_type* pointer;
  77. typedef void difference_type;
  78. explicit
  79. generator_iterator(RandomGenerator& gen, const F& f = F())
  80. : f(f), gen(&gen)
  81. {
  82. value = this->f(gen);
  83. }
  84. reference operator*() const { return value; }
  85. pointer operator->() const { return &value; }
  86. generator_iterator& operator++()
  87. {
  88. value = f(*gen);
  89. return *this;
  90. }
  91. generator_iterator operator++(int)
  92. {
  93. generator_iterator temp(*this);
  94. ++(*this);
  95. return temp;
  96. }
  97. bool operator==(const generator_iterator& other) const
  98. { return f == other.f; }
  99. bool operator!=(const generator_iterator& other) const
  100. { return !(*this == other); }
  101. private:
  102. F f;
  103. RandomGenerator* gen;
  104. value_type value;
  105. };
  106. template<typename F, typename RandomGenerator>
  107. inline generator_iterator<F, RandomGenerator>
  108. make_generator_iterator( RandomGenerator& gen, const F& f)
  109. { return generator_iterator<F, RandomGenerator>(gen, f); }
  110. template<typename Graph, typename DistanceMap, typename WeightMap, typename ColorMap>
  111. struct ssca_visitor : bfs_visitor<>
  112. {
  113. typedef typename property_traits<WeightMap>::value_type Weight;
  114. typedef typename property_traits<ColorMap>::value_type ColorValue;
  115. typedef color_traits<ColorValue> Color;
  116. ssca_visitor(DistanceMap& distance, const WeightMap& weight, ColorMap& color,
  117. Weight max_)
  118. : distance(distance), weight(weight), color(color), max_(max_) {}
  119. template<typename Edge>
  120. void tree_edge(Edge e, const Graph& g)
  121. {
  122. int new_distance = get(weight, e) == (std::numeric_limits<Weight>::max)() ?
  123. (std::numeric_limits<Weight>::max)() : get(distance, source(e, g)) + get(weight, e);
  124. put(distance, target(e, g), new_distance);
  125. if (new_distance > max_)
  126. put(color, target(e, g), Color::black());
  127. }
  128. private:
  129. DistanceMap& distance;
  130. const WeightMap& weight;
  131. ColorMap& color;
  132. Weight max_;
  133. };
  134. // Generate source vertices for approximate BC
  135. template <typename Graph, typename Buffer>
  136. void
  137. generate_sources(const Graph& g, Buffer sources,
  138. typename graph_traits<Graph>::vertices_size_type num_sources)
  139. {
  140. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  141. typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
  142. typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
  143. typedef typename boost::graph::parallel::process_group_type<Graph>::type
  144. process_group_type;
  145. process_group_type pg = g.process_group();
  146. typename process_group_type::process_id_type id = process_id(pg);
  147. typename process_group_type::process_size_type p = num_processes(pg);
  148. // Don't feel like adding a special case for num_sources < p
  149. assert(num_sources >= p);
  150. minstd_rand gen;
  151. uniform_int<vertices_size_type> rand_vertex(0, num_vertices(g) - 1);
  152. std::vector<vertex_descriptor> all_sources, local_sources;
  153. vertices_size_type local_vertices = vertices_size_type(floor((double)num_sources / p));
  154. local_vertices += (id < (num_sources - (p * local_vertices)) ? 1 : 0);
  155. while (local_vertices > 0) {
  156. vertex_iterator iter = vertices(g).first;
  157. std::advance(iter, rand_vertex(gen));
  158. if (out_degree(*iter, g) != 0
  159. && std::find(local_sources.begin(), local_sources.end(), *iter) == local_sources.end()) {
  160. local_sources.push_back(*iter);
  161. --local_vertices;
  162. }
  163. }
  164. all_gather(pg, local_sources.begin(), local_sources.end(), all_sources);
  165. std::sort(all_sources.begin(), all_sources.end());
  166. for (typename std::vector<vertex_descriptor>::iterator iter = all_sources.begin();
  167. iter != all_sources.end(); ++iter)
  168. sources.push(*iter);
  169. }
  170. // Kernel 2 - Classify large sets
  171. template <typename Graph, typename WeightMap>
  172. void classify_sets(const Graph& g, const WeightMap& weight_map,
  173. std::vector<std::pair<typename graph_traits<Graph>::vertex_descriptor,
  174. typename graph_traits<Graph>::vertex_descriptor> > & global_S)
  175. {
  176. typedef typename boost::graph::parallel::process_group_type<Graph>::type
  177. process_group_type;
  178. process_group_type pg = g.process_group();
  179. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  180. std::vector<std::pair<vertex_descriptor, vertex_descriptor> > S;
  181. time_type start = get_time();
  182. #ifdef CSR
  183. typedef typename property_map<Graph, vertex_owner_t>::const_type OwnerMap;
  184. typedef typename property_map<Graph, vertex_local_t>::const_type LocalMap;
  185. OwnerMap owner = get(vertex_owner, g);
  186. LocalMap local = get(vertex_local, g);
  187. #endif
  188. int max_ = 0;
  189. BGL_FORALL_EDGES_T(e, g, Graph) {
  190. #ifdef CSR
  191. if (get(owner, source(e, g)) == process_id(pg)) {
  192. #endif
  193. int w = get(weight_map, e);
  194. if (w > max_) {
  195. max_ = w;
  196. S.clear();
  197. }
  198. if (w >= max_)
  199. S.push_back(std::make_pair(source(e, g), target(e, g)));
  200. #ifdef CSR
  201. }
  202. #endif
  203. }
  204. int global_max = all_reduce(pg, max_, boost::parallel::maximum<int>());
  205. if (max_ < global_max)
  206. S.clear();
  207. global_S.clear();
  208. all_gather(pg, S.begin(), S.end(), global_S);
  209. // This is probably unnecessary as long as the sets of edges owned by procs is disjoint
  210. std::sort(global_S.begin(), global_S.end());
  211. std::unique(global_S.begin(), global_S.end());
  212. synchronize(pg);
  213. time_type end = get_time();
  214. if (process_id(pg) == 0) {
  215. std::cerr << " Distributed Graph: " << print_time(end - start) << std::endl
  216. << " Max int weight = " << global_max << std::endl;
  217. }
  218. }
  219. template <typename ProcessGroup, typename Graph, typename WeightMap,
  220. typename EdgeVector>
  221. void seq_classify_sets(const ProcessGroup& pg, const Graph& g,
  222. const WeightMap& weight_map, EdgeVector& S)
  223. {
  224. typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
  225. typedef typename property_traits<WeightMap>::value_type edge_weight_type;
  226. time_type start = get_time();
  227. edge_weight_type max_ = 0;
  228. BGL_FORALL_EDGES_T(e, g, Graph) {
  229. edge_weight_type w = get(weight_map, e);
  230. if (w > max_) {
  231. max_ = w;
  232. S.clear();
  233. }
  234. if (w >= max_)
  235. S.push_back(e);
  236. }
  237. synchronize(pg);
  238. time_type end = get_time();
  239. if (process_id(pg) == 0)
  240. std::cerr << " Non-Distributed Graph: " << print_time(end - start) << std::endl
  241. << " Max int weight = " << max_ << std::endl;
  242. }
  243. // Kernel 3 - Graph Extraction
  244. template <typename Graph, typename OwnerMap, typename LocalMap,
  245. typename WeightMap, typename DistanceMap, typename ColorMap,
  246. typename EdgeVector>
  247. void subgraph_extraction(Graph& g, const OwnerMap& owner, const LocalMap& local,
  248. const WeightMap& weight_map, DistanceMap distances,
  249. ColorMap color_map, const EdgeVector& S,
  250. int subGraphEdgeLength)
  251. {
  252. // Nick: I think turning the vertex black when the maximum distance is
  253. // exceeded will prevent BFS from exploring beyond the subgraph.
  254. // Unfortunately we can't run subgraph extraction in parallel
  255. // because the subgraphs may overlap
  256. typedef typename property_traits<ColorMap>::value_type ColorValue;
  257. typedef color_traits<ColorValue> Color;
  258. typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
  259. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  260. typedef typename boost::graph::parallel::process_group_type<Graph>::type
  261. process_group_type;
  262. typedef boost::graph::distributed::distributed_queue<process_group_type,
  263. OwnerMap, queue<vertex_descriptor> > queue_t;
  264. process_group_type pg = g.process_group();
  265. typename process_group_type::process_id_type id = process_id(pg);
  266. queue_t Q(pg, owner);
  267. EdgeVector sources(S.begin(), S.end());
  268. #ifdef DEBUG
  269. std::vector<std::vector<vertex_descriptor> > subgraphs;
  270. #endif
  271. synchronize(pg);
  272. typedef typename std::vector<std::pair<vertex_descriptor, vertex_descriptor> >::iterator
  273. source_iterator;
  274. time_type start = get_time();
  275. for (source_iterator iter = sources.begin(); iter != sources.end(); ++iter) {
  276. // Reinitialize distance and color maps every BFS
  277. BGL_FORALL_VERTICES_T(v, g, Graph) {
  278. if (get(owner, v) == id) {
  279. local_put(color_map, v, Color::white());
  280. local_put(distances, v, (std::numeric_limits<int>::max)());
  281. }
  282. }
  283. vertex_descriptor u = iter->first, v = iter->second;
  284. local_put(distances, u, 0);
  285. local_put(distances, v, 0);
  286. while (!Q.empty()) Q.pop();
  287. if (get(owner, u) == id)
  288. Q.push(u);
  289. local_put(color_map, u, Color::gray());
  290. breadth_first_search(g, v, Q,
  291. ssca_visitor<Graph, DistanceMap, WeightMap, ColorMap>
  292. (distances, weight_map, color_map, subGraphEdgeLength),
  293. color_map);
  294. // At this point all vertices with distance > 0 in addition to the
  295. // starting vertices compose the subgraph.
  296. #ifdef DEBUG
  297. subgraphs.push_back(std::vector<vertex_descriptor>());
  298. std::vector<vertex_descriptor>& subgraph = subgraphs.back();
  299. BGL_FORALL_VERTICES_T(v, g, Graph) {
  300. if (get(distances, v) < (std::numeric_limits<int>::max)())
  301. subgraph.push_back(v);
  302. }
  303. #endif
  304. }
  305. synchronize(pg);
  306. time_type end = get_time();
  307. #ifdef DEBUG
  308. for (unsigned int i = 0; i < subgraphs.size(); i++) {
  309. all_gather(pg, subgraphs[i].begin(), subgraphs[i].end(), subgraphs[i]);
  310. std::sort(subgraphs[i].begin(), subgraphs[i].end());
  311. subgraphs[i].erase(std::unique(subgraphs[i].begin(), subgraphs[i].end()),
  312. subgraphs[i].end());
  313. }
  314. if (process_id(pg) == 0)
  315. for (int i = 0; abs(i) < subgraphs.size(); i++) {
  316. std::cerr << "Subgraph " << i << " :\n";
  317. for (int j = 0; abs(j) < subgraphs[i].size(); j++)
  318. std::cerr << " " << get(local, subgraphs[i][j]) << "@"
  319. << get(owner, subgraphs[i][j]) << std::endl;
  320. }
  321. #endif
  322. if (process_id(pg) == 0)
  323. std::cerr << " Distributed Graph: " << print_time(end - start) << std::endl;
  324. }
  325. template <typename ProcessGroup, typename Graph, typename WeightMap,
  326. typename DistanceMap, typename ColorMap, typename EdgeVector>
  327. void seq_subgraph_extraction(const ProcessGroup& pg, const Graph& g,
  328. const WeightMap& weight_map, DistanceMap distances,
  329. ColorMap color_map, const EdgeVector& S,
  330. int subGraphEdgeLength)
  331. {
  332. // Nick: I think turning the vertex black when the maximum distance is
  333. // exceeded will prevent BFS from exploring beyond the subgraph.
  334. using boost::graph::distributed::mpi_process_group;
  335. typedef typename property_traits<ColorMap>::value_type ColorValue;
  336. typedef color_traits<ColorValue> Color;
  337. typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
  338. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  339. boost::queue<vertex_descriptor> Q;
  340. std::vector<edge_descriptor> sources(S.begin(), S.end());
  341. #ifdef DEBUG
  342. std::vector<std::vector<vertex_descriptor> > subgraphs;
  343. #endif
  344. synchronize(pg);
  345. typedef ProcessGroup process_group_type;
  346. typename process_group_type::process_id_type id = process_id(pg);
  347. typename process_group_type::process_size_type p = num_processes(pg);
  348. time_type start = get_time();
  349. for (int i = id; i < sources.size(); i += p) {
  350. // Reinitialize distance and color maps every BFS
  351. BGL_FORALL_VERTICES_T(v, g, Graph) {
  352. put(color_map, v, Color::white());
  353. put(distances, v, (std::numeric_limits<int>::max)());
  354. }
  355. vertex_descriptor u = source(sources[i], g),
  356. v = target(sources[i], g);
  357. put(distances, u, 0);
  358. put(distances, v, 0);
  359. while (!Q.empty()) Q.pop();
  360. Q.push(u);
  361. put(color_map, u, Color::gray());
  362. breadth_first_search(g, v, Q,
  363. ssca_visitor<Graph, DistanceMap, WeightMap, ColorMap>
  364. (distances, weight_map, color_map, subGraphEdgeLength),
  365. color_map);
  366. #ifdef DEBUG
  367. subgraphs.push_back(std::vector<vertex_descriptor>());
  368. std::vector<vertex_descriptor>& subgraph = subgraphs.back();
  369. BGL_FORALL_VERTICES_T(v, g, Graph) {
  370. if (get(distances, v) < (std::numeric_limits<int>::max)())
  371. subgraph.push_back(v);
  372. }
  373. #endif
  374. }
  375. synchronize(pg);
  376. time_type end = get_time();
  377. #ifdef DEBUG
  378. std::vector<vertex_descriptor> ser_subgraphs;
  379. for (int i = 0; i < subgraphs.size(); ++i) {
  380. for (int j = 0; j < subgraphs[i].size(); ++j)
  381. ser_subgraphs.push_back(subgraphs[i][j]);
  382. ser_subgraphs.push_back(graph_traits<Graph>::null_vertex());
  383. }
  384. all_gather(pg, ser_subgraphs.begin(), ser_subgraphs.end(), ser_subgraphs);
  385. int i = 0;
  386. typename std::vector<vertex_descriptor>::iterator iter(ser_subgraphs.begin());
  387. while (iter != ser_subgraphs.end()) {
  388. std::cerr << "Subgraph " << i << " :\n";
  389. while (*iter != graph_traits<Graph>::null_vertex()) {
  390. std::cerr << " " << *iter << std::endl;
  391. ++iter;
  392. }
  393. ++i;
  394. ++iter;
  395. }
  396. #endif
  397. if (process_id(pg) == 0)
  398. std::cerr << " Non-Distributed Graph: " << print_time(end - start) << std::endl;
  399. }
  400. template <typename ProcessGroup, typename Graph, typename CentralityMap>
  401. void
  402. extract_max_bc_vertices(const ProcessGroup& pg, const Graph& g, const CentralityMap& centrality,
  403. std::vector<typename graph_traits<Graph>::vertex_descriptor>& max_bc_vec)
  404. {
  405. using boost::graph::parallel::process_group;
  406. using boost::parallel::all_gather;
  407. using boost::parallel::all_reduce;
  408. // Find set of vertices with highest BC score
  409. typedef typename property_traits<CentralityMap>::value_type centrality_type;
  410. std::vector<centrality_type> max_bc_vertices;
  411. centrality_type max_ = 0;
  412. max_bc_vec.clear();
  413. BGL_FORALL_VERTICES_T(v, g, Graph) {
  414. if (get(centrality, v) == max_)
  415. max_bc_vec.push_back(v);
  416. else if (get(centrality, v) > max_) {
  417. max_ = get(centrality, v);
  418. max_bc_vec.clear();
  419. max_bc_vec.push_back(v);
  420. }
  421. }
  422. centrality_type global_max = all_reduce(pg, max_, boost::parallel::minimum<int>());
  423. if (global_max > max_)
  424. max_bc_vec.clear();
  425. all_gather(pg, max_bc_vec.begin(), max_bc_vec.end(), max_bc_vec);
  426. }
  427. // Function object to filter edges divisible by 8
  428. // EdgeWeightMap::value_type must be integral!
  429. template <typename EdgeWeightMap>
  430. struct edge_weight_not_divisible_by_eight {
  431. typedef typename property_traits<EdgeWeightMap>::value_type weight_type;
  432. edge_weight_not_divisible_by_eight() { }
  433. edge_weight_not_divisible_by_eight(EdgeWeightMap weight) : m_weight(weight) { }
  434. template <typename Edge>
  435. bool operator()(const Edge& e) const {
  436. return (get(m_weight, e) & ((std::numeric_limits<weight_type>::max)() - 7)) != get(m_weight, e);
  437. }
  438. EdgeWeightMap m_weight;
  439. };
  440. //
  441. // Vertex and Edge properties
  442. //
  443. #ifdef CSR
  444. typedef int weight_type;
  445. struct WeightedEdge {
  446. WeightedEdge(weight_type weight = 0) : weight(weight) { }
  447. weight_type weight;
  448. };
  449. struct VertexProperties {
  450. VertexProperties(int distance = 0, default_color_type color = white_color)
  451. : distance(distance), color(color) { }
  452. int distance;
  453. default_color_type color;
  454. };
  455. #endif
  456. template <typename RandomGenerator, typename ProcessGroup, typename vertices_size_type,
  457. typename edges_size_type>
  458. void
  459. run_non_distributed_graph_tests(RandomGenerator& gen, const ProcessGroup& pg,
  460. vertices_size_type n, edges_size_type m,
  461. std::size_t maxEdgeWeight, uint64_t seed,
  462. int K4Alpha, double a, double b, double c, double d,
  463. int subGraphEdgeLength, bool show_degree_dist,
  464. bool full_bc, bool verify)
  465. {
  466. #ifdef CSR
  467. typedef compressed_sparse_row_graph<directedS, VertexProperties, WeightedEdge>
  468. seqGraph;
  469. #else
  470. typedef adjacency_list<vecS, vecS, directedS,
  471. // Vertex properties
  472. property<vertex_distance_t, int,
  473. property<vertex_color_t, default_color_type> >,
  474. // Edge properties
  475. property<edge_weight_t, int> > seqGraph;
  476. #endif
  477. // Generate sequential graph for non_distributed betweenness centrality
  478. // Reseed the PRNG to get the same graph
  479. gen.seed(seed);
  480. synchronize(pg);
  481. time_type start = get_time();
  482. #ifdef CSR
  483. seqGraph sg(edges_are_sorted,
  484. sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(gen, n, m, a, b, c, d),
  485. sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(),
  486. make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
  487. n);
  488. #else
  489. seqGraph sg(unique_rmat_iterator<RandomGenerator, seqGraph>(gen, n, m, a, b, c, d),
  490. unique_rmat_iterator<RandomGenerator, seqGraph>(),
  491. make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
  492. n);
  493. #endif
  494. // Not strictly necessary to synchronize here, but it make sure that the
  495. // time we measure is the time needed for all copies of the graph to be
  496. // constructed
  497. synchronize(pg);
  498. time_type end = get_time();
  499. if (process_id(pg) == 0)
  500. std::cerr<< "Kernel 1:\n"
  501. << " Non-Distributed Graph: " << print_time(end - start) << std::endl;
  502. std::map<int, int> degree_dist;
  503. if ( show_degree_dist ) {
  504. BGL_FORALL_VERTICES_T(v, sg, seqGraph) {
  505. degree_dist[out_degree(v, sg)]++;
  506. }
  507. std::cerr << "Degree - Fraction of vertices of that degree\n";
  508. for (std::map<int, int>::iterator iter = degree_dist.begin();
  509. iter != degree_dist.end(); ++iter)
  510. std::cerr << " " << iter->first << " - " << double(iter->second) / num_vertices(sg) << std::endl << std::endl;
  511. }
  512. //
  513. // Kernel 2 - Classify large sets
  514. //
  515. std::vector<graph_traits<seqGraph>::edge_descriptor> seqS;
  516. if (process_id(pg) == 0)
  517. std::cerr << "Kernel 2:\n";
  518. seq_classify_sets(pg, sg,
  519. #ifdef CSR
  520. get(&WeightedEdge::weight, sg),
  521. #else
  522. get(edge_weight, sg),
  523. #endif
  524. seqS);
  525. //
  526. // Kernel 3 - Graph Extraction
  527. //
  528. #ifdef CSR
  529. typedef weight_type weight_t;
  530. weight_t unit_weight(1);
  531. #else
  532. int unit_weight(1);;
  533. #endif
  534. if (process_id(pg) == 0)
  535. std::cerr << "Kernel 3:\n";
  536. seq_subgraph_extraction(pg, sg,
  537. #ifdef CSR
  538. // get(&WeightedEdge::weight, sg),
  539. ref_property_map<graph_traits<seqGraph>::edge_descriptor, weight_t>(unit_weight),
  540. get(&VertexProperties::distance, sg),
  541. get(&VertexProperties::color, sg),
  542. #else
  543. // get(edge_weight, sg),
  544. ref_property_map<graph_traits<seqGraph>::edge_descriptor, int>(unit_weight),
  545. get(vertex_distance, sg),
  546. get(vertex_color, sg),
  547. #endif
  548. seqS, subGraphEdgeLength);
  549. #ifdef CSR
  550. typedef property_map<seqGraph, weight_type WeightedEdge::*>::type seqEdgeWeightMap;
  551. edge_weight_not_divisible_by_eight<seqEdgeWeightMap> sg_filter(get(&WeightedEdge::weight, sg));
  552. #else
  553. typedef property_map<seqGraph, edge_weight_t>::type seqEdgeWeightMap;
  554. edge_weight_not_divisible_by_eight<seqEdgeWeightMap> sg_filter(get(edge_weight, sg));
  555. #endif
  556. typedef filtered_graph<const seqGraph, edge_weight_not_divisible_by_eight<seqEdgeWeightMap> >
  557. filteredSeqGraph;
  558. filteredSeqGraph fsg(sg, sg_filter);
  559. std::vector<graph_traits<seqGraph>::vertex_descriptor> max_seq_bc_vec;
  560. // Non-Distributed Centrality Map
  561. typedef property_map<seqGraph, vertex_index_t>::const_type seqIndexMap;
  562. typedef iterator_property_map<std::vector<int>::iterator, seqIndexMap> seqCentralityMap;
  563. std::vector<int> non_distributed_centralityS(num_vertices(sg), 0);
  564. seqCentralityMap non_distributed_centrality(non_distributed_centralityS.begin(),
  565. get(vertex_index, sg));
  566. vertices_size_type n0 = 0;
  567. BGL_FORALL_VERTICES_T(v, fsg, filteredSeqGraph) {
  568. if (out_degree(v, fsg) == 0) ++n0;
  569. }
  570. if (process_id(pg) == 0)
  571. std::cerr << "Kernel 4:\n";
  572. // Run Betweenness Centrality
  573. if (full_bc) {
  574. // Non-Distributed Graph BC
  575. start = get_time();
  576. non_distributed_brandes_betweenness_centrality(pg, fsg, non_distributed_centrality);
  577. extract_max_bc_vertices(pg, fsg, non_distributed_centrality, max_seq_bc_vec);
  578. end = get_time();
  579. edges_size_type nonDistributedExactTEPs = edges_size_type(floor(7 * n* (n - n0) / (end - start)));
  580. if (process_id(pg) == 0)
  581. std::cerr << " non-Distributed Graph Exact = " << print_time(end - start) << " ("
  582. << nonDistributedExactTEPs << " TEPs)\n";
  583. }
  584. // Non-Distributed Graph Approximate BC
  585. std::vector<int> nonDistributedApproxCentralityS(num_vertices(sg), 0);
  586. seqCentralityMap nonDistributedApproxCentrality(nonDistributedApproxCentralityS.begin(),
  587. get(vertex_index, sg));
  588. queue<typename graph_traits<filteredSeqGraph>::vertex_descriptor> sources;
  589. {
  590. minstd_rand gen;
  591. uniform_int<vertices_size_type> rand_vertex(0, num_vertices(fsg) - 1);
  592. int remaining_sources = floor(pow(2, K4Alpha));
  593. std::vector<typename graph_traits<filteredSeqGraph>::vertex_descriptor> temp_sources;
  594. while (remaining_sources > 0) {
  595. typename graph_traits<filteredSeqGraph>::vertex_descriptor v =
  596. vertex(rand_vertex(gen), fsg);
  597. if (out_degree(v, fsg) != 0
  598. && std::find(temp_sources.begin(), temp_sources.end(), v) == temp_sources.end()) {
  599. temp_sources.push_back(v);
  600. --remaining_sources;
  601. }
  602. }
  603. for (int i = 0; i < temp_sources.size(); ++i)
  604. sources.push(temp_sources[i]);
  605. }
  606. start = get_time();
  607. non_distributed_brandes_betweenness_centrality(pg, fsg, buffer(sources).
  608. centrality_map(nonDistributedApproxCentrality));
  609. extract_max_bc_vertices(pg, fsg, nonDistributedApproxCentrality, max_seq_bc_vec);
  610. end = get_time();
  611. edges_size_type nonDistributedApproxTEPs = edges_size_type(floor(7 * n * pow(2, K4Alpha) / (end - start)));
  612. if (process_id(pg) == 0)
  613. std::cerr << " Non-Distributed Graph Approximate (" << floor(pow(2, K4Alpha)) << " sources) = "
  614. << print_time(end - start) << " (" << nonDistributedApproxTEPs << " TEPs)\n";
  615. // Verify Correctness of Kernel 4
  616. if (full_bc && verify && process_id(pg) == 0) {
  617. std::vector<int> seq_centralityS(num_vertices(fsg), 0);
  618. seqCentralityMap seq_centrality(seq_centralityS.begin(), get(vertex_index, fsg));
  619. max_seq_bc_vec.clear();
  620. property_traits<seqCentralityMap>::value_type max_ = 0;
  621. start = get_time();
  622. brandes_betweenness_centrality(fsg, seq_centrality);
  623. typedef filtered_graph<const seqGraph, edge_weight_not_divisible_by_eight<seqEdgeWeightMap> >
  624. filteredSeqGraph;
  625. BGL_FORALL_VERTICES_T(v, fsg, filteredSeqGraph ) {
  626. if (get(seq_centrality, v) == max_)
  627. max_seq_bc_vec.push_back(v);
  628. else if (get(seq_centrality, v) > max_) {
  629. max_ = get(seq_centrality, v);
  630. max_seq_bc_vec.clear();
  631. max_seq_bc_vec.push_back(v);
  632. }
  633. }
  634. end = get_time();
  635. edges_size_type sequentialTEPs = edges_size_type(floor(7 * n* (n - n0) / (end - start)));
  636. std::cerr << " Sequential = " << print_time(end - start) << " (" << sequentialTEPs << " TEPs)\n";
  637. typename ProcessGroup::process_id_type id = process_id(pg);
  638. typename ProcessGroup::process_size_type p = num_processes(pg);
  639. assert((double)n/p == floor((double)n/p));
  640. std::cerr << "\nVerifying non-scalable betweenness centrality...\n";
  641. {
  642. bool passed = true;
  643. // Verify non-scalable betweenness centrality
  644. BGL_FORALL_VERTICES_T(v, sg, seqGraph) {
  645. if (get(non_distributed_centrality, v) != get(seq_centrality, v)) {
  646. std::cerr << " " << id << ": Error - centrality of " << v
  647. << " does not match the sequential result ("
  648. << get(non_distributed_centrality, v) << " vs. "
  649. << get(seq_centrality, v) << ")\n";
  650. passed = false;
  651. }
  652. }
  653. if (passed)
  654. std::cerr << " PASSED\n";
  655. }
  656. }
  657. }
  658. template <typename RandomGenerator, typename ProcessGroup, typename vertices_size_type,
  659. typename edges_size_type>
  660. void
  661. run_distributed_graph_tests(RandomGenerator& gen, const ProcessGroup& pg,
  662. vertices_size_type n, edges_size_type m,
  663. std::size_t maxEdgeWeight, uint64_t seed,
  664. int K4Alpha, double a, double b, double c, double d,
  665. int subGraphEdgeLength, bool show_degree_dist,
  666. bool emit_dot_file, bool full_bc, bool verify)
  667. {
  668. #ifdef CSR
  669. typedef compressed_sparse_row_graph<directedS, VertexProperties, WeightedEdge, no_property,
  670. distributedS<ProcessGroup> > Graph;
  671. #else
  672. typedef adjacency_list<vecS,
  673. distributedS<ProcessGroup, vecS>,
  674. directedS,
  675. // Vertex properties
  676. property<vertex_distance_t, int,
  677. property<vertex_color_t, default_color_type> >,
  678. // Edge properties
  679. property<edge_weight_t, int> > Graph;
  680. #endif
  681. gen.seed(seed);
  682. parallel::variant_distribution<ProcessGroup> distrib
  683. = parallel::block(pg, n);
  684. typedef typename ProcessGroup::process_id_type process_id_type;
  685. process_id_type id = process_id(pg);
  686. typedef typename property_map<Graph, vertex_owner_t>::const_type OwnerMap;
  687. typedef typename property_map<Graph, vertex_local_t>::const_type LocalMap;
  688. typedef keep_local_edges<parallel::variant_distribution<ProcessGroup>,
  689. process_id_type>
  690. EdgeFilter;
  691. //
  692. // Kernel 1 - Graph construction
  693. // Nick: The benchmark specifies that we only have to time graph generation from
  694. // edge tuples, the generator generates the edge tuples at graph construction
  695. // time so we're timing some overhead in the random number generator, etc.
  696. synchronize(pg);
  697. time_type start = get_time();
  698. #ifdef CSR
  699. // typedef sorted_unique_rmat_iterator<RandomGenerator, Graph, EdgeFilter> RMATIter;
  700. typedef sorted_rmat_iterator<RandomGenerator, Graph, keep_all_edges> RMATIter;
  701. Graph g(//RMATIter(gen, n, m, a, b, c, d, false, true, EdgeFilter(distrib, id)),
  702. RMATIter(gen, n, m, a, b, c, d, true, keep_all_edges()),
  703. RMATIter(),
  704. make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
  705. n, pg, distrib);
  706. #else
  707. typedef unique_rmat_iterator<RandomGenerator, Graph, EdgeFilter> RMATIter;
  708. Graph g(RMATIter(gen, n, m, a, b, c, d, true EdgeFilter(distrib, id)),
  709. RMATIter(),
  710. make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
  711. n, pg, distrib);
  712. #endif
  713. synchronize(pg);
  714. time_type end = get_time();
  715. if (id == 0)
  716. std::cerr<< "Kernel 1:\n"
  717. << " Distributed Graph: " << print_time(end - start) << std::endl;
  718. if ( emit_dot_file )
  719. write_graphviz("ssca.dot", g);
  720. //
  721. // Kernel 2 - Classify large sets
  722. //
  723. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  724. std::vector<std::pair<vertex_descriptor, vertex_descriptor> > S;
  725. if (id == 0)
  726. std::cerr << "Kernel 2:\n";
  727. classify_sets(g,
  728. #ifdef CSR
  729. get(&WeightedEdge::weight, g),
  730. #else
  731. get(edge_weight, g),
  732. #endif
  733. S);
  734. //
  735. // Kernel 3 - Graph Extraction
  736. //
  737. OwnerMap owner = get(vertex_owner, g);
  738. LocalMap local = get(vertex_local, g);
  739. if (id == 0)
  740. std::cerr << "Kernel 3:\n";
  741. #ifdef CSR
  742. typedef weight_type weight_t;
  743. weight_t unit_weight(1);
  744. #else
  745. int unit_weight(1);;
  746. #endif
  747. subgraph_extraction(g, owner, local,
  748. #ifdef CSR
  749. // get(&WeightedEdge::weight, g),
  750. ref_property_map<typename graph_traits<Graph>::edge_descriptor, weight_t>(unit_weight),
  751. get(&VertexProperties::distance, g),
  752. get(&VertexProperties::color, g),
  753. #else
  754. // get(edge_weight, g),
  755. ref_property_map<graph_traits<Graph>::edge_descriptor, int>(unit_weight),
  756. get(vertex_distance, g),
  757. get(vertex_color, g),
  758. #endif
  759. S, subGraphEdgeLength);
  760. //
  761. // Kernel 4 - Betweenness Centrality
  762. //
  763. // Filter edges with weights divisible by 8
  764. #ifdef CSR
  765. typedef typename property_map<Graph, weight_type WeightedEdge::*>::type EdgeWeightMap;
  766. edge_weight_not_divisible_by_eight<EdgeWeightMap> filter(get(&WeightedEdge::weight, g));
  767. #else
  768. typedef typename property_map<Graph, edge_weight_t>::type EdgeWeightMap;
  769. edge_weight_not_divisible_by_eight<EdgeWeightMap> filter(get(edge_weight, g));
  770. #endif
  771. typedef filtered_graph<const Graph, edge_weight_not_divisible_by_eight<EdgeWeightMap> >
  772. filteredGraph;
  773. filteredGraph fg(g, filter);
  774. // Vectors of max BC scores for all tests
  775. std::vector<typename graph_traits<Graph>::vertex_descriptor> max_bc_vec;
  776. // Distributed Centrality Map
  777. typedef typename property_map<Graph, vertex_index_t>::const_type IndexMap;
  778. typedef iterator_property_map<std::vector<int>::iterator, IndexMap> CentralityMap;
  779. std::vector<int> centralityS(num_vertices(g), 0);
  780. CentralityMap centrality(centralityS.begin(), get(vertex_index, g));
  781. // Calculate number of vertices of degree 0
  782. vertices_size_type local_n0 = 0, n0;
  783. BGL_FORALL_VERTICES_T(v, fg, filteredGraph) {
  784. if (out_degree(v, g) == 0) local_n0++;
  785. }
  786. n0 = boost::parallel::all_reduce(pg, local_n0, std::plus<vertices_size_type>());
  787. if (id == 0)
  788. std::cerr << "Kernel 4:\n";
  789. // Run Betweenness Centrality
  790. if (full_bc) {
  791. // Distributed Graph Full BC
  792. start = get_time();
  793. brandes_betweenness_centrality(fg, centrality);
  794. extract_max_bc_vertices(pg, g, centrality, max_bc_vec);
  795. end = get_time();
  796. edges_size_type exactTEPs = edges_size_type(floor(7 * n* (n - n0) / (end - start)));
  797. if (id == 0)
  798. std::cerr << " Exact = " << print_time(end - start) << " ("
  799. << exactTEPs << " TEPs)\n";
  800. }
  801. // Distributed Graph Approximate BC
  802. std::vector<int> approxCentralityS(num_vertices(g), 0);
  803. CentralityMap approxCentrality(approxCentralityS.begin(), get(vertex_index, g));
  804. queue<vertex_descriptor> sources;
  805. generate_sources(g, sources, vertices_size_type(floor(pow(2, K4Alpha))));
  806. start = get_time();
  807. brandes_betweenness_centrality(fg, buffer(sources).centrality_map(approxCentrality));
  808. extract_max_bc_vertices(pg, fg, approxCentrality, max_bc_vec);
  809. end = get_time();
  810. edges_size_type approxTEPs = edges_size_type(floor(7 * n * pow(2, K4Alpha) / (end - start)));
  811. if (id == 0)
  812. std::cerr << " Approximate (" << floor(pow(2, K4Alpha)) << " sources) = "
  813. << print_time(end - start) << " (" << approxTEPs << " TEPs)\n";
  814. // Verify Correctness of Kernel 4
  815. if (full_bc && verify && id == 0) {
  816. // Build non-distributed graph to verify against
  817. typedef adjacency_list<vecS, vecS, directedS,
  818. // Vertex properties
  819. property<vertex_distance_t, int,
  820. property<vertex_color_t, default_color_type> >,
  821. // Edge properties
  822. property<edge_weight_t, int> > seqGraph;
  823. gen.seed(seed);
  824. #ifdef CSR
  825. seqGraph sg(sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(gen, n, m, a, b, c, d),
  826. sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(),
  827. make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
  828. n);
  829. #else
  830. seqGraph sg(unique_rmat_iterator<RandomGenerator, seqGraph>(gen, n, m, a, b, c, d),
  831. unique_rmat_iterator<RandomGenerator, seqGraph>(),
  832. make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
  833. n);
  834. #endif
  835. typedef property_map<seqGraph, edge_weight_t>::type seqEdgeWeightMap;
  836. edge_weight_not_divisible_by_eight<seqEdgeWeightMap> sg_filter(get(edge_weight, sg));
  837. filtered_graph<const seqGraph, edge_weight_not_divisible_by_eight<seqEdgeWeightMap> >
  838. fsg(sg, sg_filter);
  839. // Build sequential centrality map
  840. typedef property_map<seqGraph, vertex_index_t>::const_type seqIndexMap;
  841. typedef iterator_property_map<std::vector<int>::iterator, seqIndexMap> seqCentralityMap;
  842. std::vector<int> seq_centralityS(num_vertices(sg), 0);
  843. seqCentralityMap seq_centrality(seq_centralityS.begin(), get(vertex_index, sg));
  844. std::vector<graph_traits<seqGraph>::vertex_descriptor> max_seq_bc_vec;
  845. max_seq_bc_vec.clear();
  846. property_traits<seqCentralityMap>::value_type max_ = 0;
  847. start = get_time();
  848. brandes_betweenness_centrality(fsg, seq_centrality);
  849. typedef filtered_graph<const seqGraph, edge_weight_not_divisible_by_eight<seqEdgeWeightMap> >
  850. filteredSeqGraph;
  851. BGL_FORALL_VERTICES_T(v, fsg, filteredSeqGraph ) {
  852. if (get(seq_centrality, v) == max_)
  853. max_seq_bc_vec.push_back(v);
  854. else if (get(seq_centrality, v) > max_) {
  855. max_ = get(seq_centrality, v);
  856. max_seq_bc_vec.clear();
  857. max_seq_bc_vec.push_back(v);
  858. }
  859. }
  860. end = get_time();
  861. edges_size_type sequentialTEPs = edges_size_type(floor(7 * n* (n - n0) / (end - start)));
  862. std::cerr << " Sequential = " << print_time(end - start) << " (" << sequentialTEPs << " TEPs)\n";
  863. typename ProcessGroup::process_size_type p = num_processes(pg);
  864. assert((double)n/p == floor((double)n/p));
  865. std::cerr << "\nVerifying betweenness centrality...\n";
  866. {
  867. bool passed = true;
  868. // Verify exact betweenness centrality
  869. BGL_FORALL_VERTICES_T(v, g, Graph) {
  870. if (get(centrality, v) != seq_centralityS[(n/p) * get(owner, v) + get(local, v)]) {
  871. std::cerr << " " << id << ": Error - centrality of " << get(local, v) << "@" << get(owner, v)
  872. << " does not match the sequential result (" << get(centrality, v) << " vs. "
  873. << seq_centralityS[(n/p) * get(owner, v) + get(local, v)] << ")\n";
  874. passed = false;
  875. }
  876. }
  877. if (passed)
  878. std::cerr << " PASSED\n";
  879. }
  880. }
  881. }
  882. void usage()
  883. {
  884. std::cerr << "SSCA benchmark.\n\n"
  885. << "Usage : ssca [options]\n\n"
  886. << "Options are:\n"
  887. << "\t--vertices v\t\t\tNumber of vertices in the graph\n"
  888. << "\t--edges v\t\t\tNumber of edges in the graph\n"
  889. << "\t--seed s\t\t\tSeed for synchronized random number generator\n"
  890. << "\t--full-bc\t\t\tRun full (exact) Betweenness Centrality\n"
  891. << "\t--max-weight miw\t\tMaximum integer edge weight\n"
  892. << "\t--subgraph-edge-length sel\tEdge length of subgraphs to extract in Kernel 3\n"
  893. << "\t--k4alpha k\t\t\tValue of K4Alpha in Kernel 4\n"
  894. << "\t--scale s\t\t\tSCALE parameter for the SSCA benchmark (sets n, m, and C)\n"
  895. << "\t--dot\t\t\t\tEmit a dot file containing the graph\n"
  896. << "\t--verify\t\t\tVerify result\n"
  897. << "\t--degree-dist\t\t\t Output degree distribution of graph\n"
  898. << "\t--no-distributed-graph\t\tOmit distributed graph tests\n";
  899. }
  900. int test_main(int argc, char* argv[])
  901. {
  902. mpi::environment env(argc, argv);
  903. using boost::graph::distributed::mpi_process_group;
  904. #ifdef CSR
  905. typedef compressed_sparse_row_graph<directedS, VertexProperties, WeightedEdge, no_property,
  906. distributedS<mpi_process_group> > Graph;
  907. #else
  908. typedef adjacency_list<vecS,
  909. distributedS<mpi_process_group, vecS>,
  910. directedS,
  911. // Vertex properties
  912. property<vertex_distance_t, int,
  913. property<vertex_color_t, default_color_type> >,
  914. // Edge properties
  915. property<edge_weight_t, int> > Graph;
  916. #endif
  917. typedef graph_traits<Graph>::vertices_size_type vertices_size_type;
  918. typedef graph_traits<Graph>::edges_size_type edges_size_type;
  919. RandomGenerator gen;
  920. // Default args
  921. vertices_size_type n = 100;
  922. edges_size_type m = 8*n;
  923. uint64_t seed = 1;
  924. int maxEdgeWeight = 100,
  925. subGraphEdgeLength = 8,
  926. K4Alpha = 0.5;
  927. double a = 0.57, b = 0.19, c = 0.19, d = 0.05;
  928. bool emit_dot_file = false, verify = false, full_bc = true,
  929. distributed_graph = true, show_degree_dist = false,
  930. non_distributed_graph = true;
  931. mpi_process_group pg;
  932. if (argc == 1) {
  933. if (process_id(pg) == 0)
  934. usage();
  935. exit(-1);
  936. }
  937. // Parse args
  938. for (int i = 1; i < argc; ++i) {
  939. std::string arg = argv[i];
  940. if (arg == "--vertices")
  941. n = boost::lexical_cast<vertices_size_type>( argv[i+1] );
  942. if (arg == "--seed")
  943. seed = boost::lexical_cast<uint64_t>( argv[i+1] );
  944. if (arg == "--full-bc")
  945. full_bc = (argv[i+1]== "true");
  946. if (arg == "--max-weight")
  947. maxEdgeWeight = boost::lexical_cast<int>( argv[i+1] );
  948. if (arg == "--subgraph-edge-length")
  949. subGraphEdgeLength = boost::lexical_cast<int>( argv[i+1] );
  950. if (arg == "--edges")
  951. m = boost::lexical_cast<edges_size_type>( argv[i+1] );
  952. if (arg == "--k4alpha")
  953. K4Alpha = boost::lexical_cast<int>( argv[i+1] );
  954. if (arg == "--dot")
  955. emit_dot_file = true;
  956. if (arg == "--verify")
  957. verify = true;
  958. if (arg == "--degree-dist")
  959. show_degree_dist = true;
  960. if (arg == "--no-distributed-graph")
  961. distributed_graph = false;
  962. if (arg == "--no-non-distributed-graph")
  963. non_distributed_graph = false;
  964. if (arg == "--scale") {
  965. vertices_size_type scale = boost::lexical_cast<vertices_size_type>( argv[i+1] );
  966. maxEdgeWeight = n = vertices_size_type(floor(pow(2, scale)));
  967. m = 8 * n;
  968. }
  969. if (arg == "--help") {
  970. if (process_id(pg) == 0)
  971. usage();
  972. exit(-1);
  973. }
  974. }
  975. if (non_distributed_graph) {
  976. if (process_id(pg) == 0)
  977. std::cerr << "Non-Distributed Graph Tests\n";
  978. run_non_distributed_graph_tests(gen, pg, n, m, maxEdgeWeight, seed, K4Alpha, a, b, c, d,
  979. subGraphEdgeLength, show_degree_dist, full_bc, verify);
  980. }
  981. if (distributed_graph) {
  982. if (process_id(pg) == 0)
  983. std::cerr << "Distributed Graph Tests\n";
  984. run_distributed_graph_tests(gen, pg, n, m, maxEdgeWeight, seed, K4Alpha, a, b, c, d,
  985. subGraphEdgeLength, show_degree_dist, emit_dot_file,
  986. full_bc, verify);
  987. }
  988. return 0;
  989. }