Loading [MathJax]/extensions/tex2jax.js
Parallel numerical verification of the σ_odd problem  October 6, 2018
All Classes Namespaces Files Functions Variables Typedefs Macros
check_gentle_mpi.cpp
Go to the documentation of this file.
1 /* -*- coding: latin-1 -*- */
2 /** \file mpi/check_gentle_mpi.cpp (January 18, 2018)
3  * \brief
4  * Check odd gentle numbers for the varsigma_odd problem
5  * and print bad numbers.
6  *
7  * GPLv3 --- Copyright (C) 2017, 2018 Olivier Pirson
8  * http://www.opimedia.be/
9  */
10 
11 // \cond
12 #include <cstdlib>
13 
14 #include <algorithm>
15 #include <chrono>
16 #include <iostream>
17 #include <iterator>
18 // \endcond
19 
20 #include "../common/helper/helper.hpp"
21 
22 #include "mpi/mpi.hpp"
23 
24 
25 
26 /* *****************
27  * Global variable *
28  *******************/
29 unsigned int rank;
30 
31 
32 
33 /* ***********
34  * Prototype *
35  *************/
36 
37 void
39 
40 
41 
42 /* **********
43  * Function *
44  ************/
45 
46 void
48  if (mpi::is_master(rank)) {
49  std::cerr << "Usage: check_gentle [options] (MPI version)" << std::endl
50  << std::endl
51  << "Version options of the parallel algorithm:" << std::endl
52  << " --dynamic range of number for each process without a barrier (by default)" << std::endl
53  << " --one-by-one one number for each process with a barrier" << std::endl
54  << std::endl
55  << "Options:" << std::endl
56  << " --bad-table filename load bad numbers from this file" << std::endl
57  << " (If load bad numbers then must be contains all bad numbers < first." << std::endl
58  << " Can load them with several files.)" << std::endl
59  << " --first n first odd number to check (3 by default)" << std::endl
60  << " --last n last odd number to check (1000001 by default)" << std::endl
61  << " --nb n number of odd numbers to check" << std::endl
62  << " --no-print do not print bad numbers" << std::endl;
63  }
64 
65  MPI_Finalize();
66  exit(EXIT_FAILURE);
67 }
68 
69 
70 
71 /* ******
72  * Main *
73  ********/
74 int
75 main(int argc, char* argv[]) {
76  // Init MPI
77  MPI_Init(&argc, &argv);
78 
79  rank = mpi::mpi_rank();
80 
81 
82  // Load primes table
84  std::cerr << "! Impossible to load \"" << sigmaodd::prime_filename << '"' << std::endl
85  << std::endl;
86  help_and_exit();
87  }
88 
89 
90  enum Algos: unsigned int {dynamic, one_by_one};
91 
92  const std::string algo_strings[2] = {"dynamic",
93  "one-by-one"};
94 
95  unsigned int algo = dynamic;
96  std::vector<sigmaodd::nat_type> bad_table;
97  sigmaodd::nat_type first = 3;
98  sigmaodd::nat_type last = 1000001;
99  bool print_bad = true;
100 
101 
102  // Read command line parameters
103  for (unsigned int i = 1; i < static_cast<unsigned int>(argc); ++i) {
104  const std::string param(argv[i]);
105 
106  if (param == "--bad-table") {
107  std::string filename = helper::get_string(argc, argv, ++i, &help_and_exit);
108 
109  if (mpi::is_master(rank)) {
110  if (filename.empty() || !helper::is_file_exists(filename)) {
111  std::cerr << "! Failed reading file \"" << filename << '"' << std::endl;
112  help_and_exit();
113  }
114 
115  bad_table = sigmaodd::load_bad_table(filename, bad_table);
116  if (bad_table.empty()) {
117  std::cerr << "! Wrong format for the bad table file \"" << filename << '"' << std::endl;
118  help_and_exit();
119  }
120  }
121  }
122  else if (param == "--first") {
123  first = std::max(3ul, helper::get_ulong(argc, argv, ++i, &help_and_exit));
124  if (sigmaodd::is_even(first)) {
125  ++first;
126  }
127  }
128  else if (param == "--dynamic") {
129  algo = dynamic;
130  }
131  else if (param == "--last") {
132  last = helper::get_ulong(argc, argv, ++i, &help_and_exit);
133  if (sigmaodd::is_even(last)) {
134  --last;
135  }
136  }
137  else if (param == "--nb") {
138  last = first + helper::get_ulong(argc, argv, ++i, &help_and_exit)*2 - 1;
139  }
140  else if (param == "--no-print") {
141  print_bad = false;
142  }
143  else if (param == "--one-by-one") {
144  algo = one_by_one;
145  }
146  else {
147  help_and_exit();
148  }
149  }
150 
151 
152  if (mpi::is_master(rank)) {
153  /*
154  * Master
155  */
156  const std::set<sigmaodd::nat_type> bad_table_set(bad_table.cbegin(), bad_table.cend());
157 
158  bad_table.clear();
159 
160  const auto minmax = std::minmax_element(bad_table_set.cbegin(), bad_table_set.cend());
161 
162 
163  // Print intern configuration
166  std::cout << "Process id: " << rank
167  << "\t# process: " << mpi::mpi_nb_process()
168  << "\tProcess name: " << mpi::mpi_processor_name() << std::endl;
169 
170  // Print parameters
171  std::cout << "mpi/check_gentle"
172  << "\tFirst: " << first
173  << "\tLast: " << last
174  << "\tNb: " << (first <= last
175  ? (last - first)/2 + 1
176  : 0)
177  << "\tAlgorithm: " << algo_strings[algo];
178  if (!bad_table_set.empty()) {
179  std::cout << "\t# bad numbers loaded: " << bad_table_set.size()
180  << "\tBetween " << *minmax.first
181  << "\tand " << *minmax.second << std::endl;
182  }
183  std::cout << std::endl;
184 
185  // Print table legend
186  std::cout << std::endl
187  << 'n' << std::endl;
188  std::cout.flush();
189 
190 
191  // Main calculation
192  const double openmpi_start_time = MPI_Wtime();
193  const std::chrono::steady_clock::time_point clock_start = std::chrono::steady_clock::now();
194 
195  if (algo == dynamic) {
197  bad_table_set,
198  print_bad);
199  }
200  else if (algo == one_by_one) {
202  bad_table_set,
203  print_bad);
204  }
205  else {
206  MPI_Finalize();
207  exit(EXIT_FAILURE);
208  }
209 
210  // End
211  const std::chrono::duration<double> duration = std::chrono::steady_clock::now() - clock_start;
212  const double openmpi_duration = MPI_Wtime() - openmpi_start_time;
213 
214  std::cout << "Total duration: " << helper::duration_to_string(duration)
215  << std::endl;
216  std::cout << "Total OpenMPI: " << helper::duration_ms_to_string(openmpi_duration*1000)
217  << std::endl;
218  }
219  else {
220  /*
221  * Slave
222  */
223  if (algo == dynamic) {
224  // Compute range sent until return finish message
226  }
227  }
228  else if (algo == one_by_one) {
229  // Compute n sent until return finish message
231  }
232  }
233  else {
234  MPI_Finalize();
235  exit(EXIT_FAILURE);
236  }
237  }
238 
239  // Finish MPI
240  MPI_Finalize();
241 
242  return EXIT_SUCCESS;
243 }
unsigned int mpi_rank()
Return the rank of this process.
Definition: mpi__inline.hpp:78
int main(int argc, char *argv[])
bool mpi_slave_wait_compute_n()
Computation of one n by a slave, for the mpi_check_gentle_varsigma_odd__one_by_one() master function...
Definition: mpi.cpp:237
uint64_t nat_type
Type for natural number used in all code, on 64 bits.
Definition: helper.hpp:33
std::string duration_ms_to_string(double duration_ms)
Return a string with the duration expressed in milliseconds, seconds, minutes and hours...
Definition: helper.cpp:48
const std::string prime_filename
Default filename for the binary file "big_data/prime28.bin".
Definition: primes.cpp:35
constexpr bool is_even(nat_type n)
Return true iff n is even.
std::string duration_to_string(std::chrono::duration< double > duration_second)
Return a string with the duration expressed in milliseconds, seconds, minutes and hours...
Definition: helper.cpp:61
void print_mpi_versions()
Print the Open MPI version and the library version.
Definition: mpi.cpp:300
bool read_primes_table()
Read the binary file prime_filename to fill the table with all primes < 2^28. This table must be read...
Definition: primes.cpp:241
unsigned int mpi_nb_process()
Return the number of process.
Definition: mpi__inline.hpp:52
bool is_file_exists(std::string filename)
Return true iff the file (or directory) exists.
Definition: helper.cpp:140
unsigned int rank
std::string get_string(int argc, const char *const argv[], unsigned int i, void(*help_and_exit_function)())
Return argv[i] converted in string.
Definition: helper.cpp:92
std::string mpi_processor_name()
Return the processor name.
Definition: mpi__inline.hpp:66
std::set< nat_type > mpi_check_gentle_varsigma_odd__one_by_one(nat_type first_n, nat_type last_n, const std::set< nat_type > &previous_bad_table, bool print_bad)
Definition: mpi.cpp:147
std::set< nat_type > mpi_check_gentle_varsigma_odd__dynamic(nat_type first_n, nat_type last_n, const std::set< nat_type > &previous_bad_table, bool print_bad, unsigned int range_size, unsigned int master_range_size)
Check in the order all odd gentle numbers between first_n and last_n, and if print_bad then print all...
Definition: mpi.cpp:28
void print_intern_config_compiler()
Print to stdcout the intern configuration of the compiler.
Definition: helper.cpp:148
Implementation of the message-passing (MPI) algorithms presented in the report.
bool mpi_slave_wait_compute_range()
Computation of one range by a slave, for the mpi_check_gentle_varsigma_odd__dynamic() master function...
Definition: mpi.cpp:265
void help_and_exit()
unsigned long get_ulong(int argc, const char *const argv[], unsigned int i, void(*help_and_exit_function)())
Return argv[i] converted in integer.
Definition: helper.cpp:124
std::vector< nat_type > load_bad_table(const std::string &filename, const std::vector< nat_type > &bad_table)
Read a file that contains list of bad numbers, add after bad_table, and return the result...
Definition: helper.cpp:100
constexpr bool is_master(rank_type rank)
Return true iff rank correspond to the master instance.
Definition: mpi__inline.hpp:27