Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Use 'auto' with functions returning iterators [sonar].
[simgrid.git] / src / smpi / internals / smpi_config.cpp
1 /* Copyright (c) 2008-2021. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5 #include "smpi_config.hpp"
6 #include "include/xbt/config.hpp"
7 #include "mc/mc.h"
8 #include "private.hpp"
9 #include "smpi_coll.hpp"
10 #include "xbt/parse_units.hpp"
11
12 #include <cfloat> /* DBL_MAX */
13 #include <boost/algorithm/string.hpp> /* trim */
14 #include <boost/tokenizer.hpp>
15
16 #if SIMGRID_HAVE_MC
17 #include "src/mc/mc_config.hpp"
18 #endif
19
20 #if defined(__APPLE__)
21 # include <AvailabilityMacros.h>
22 # ifndef MAC_OS_X_VERSION_10_12
23 #   define MAC_OS_X_VERSION_10_12 101200
24 # endif
25 constexpr bool HAVE_WORKING_MMAP = (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12);
26 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__sun) || defined(__HAIKU__)
27 constexpr bool HAVE_WORKING_MMAP = false;
28 #else
29 constexpr bool HAVE_WORKING_MMAP = true;
30 #endif
31
32 SharedMallocType _smpi_cfg_shared_malloc = SharedMallocType::GLOBAL;
33 SmpiPrivStrategies _smpi_cfg_privatization = SmpiPrivStrategies::NONE;
34 double _smpi_cfg_host_speed;
35
36 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_config, smpi, "Logging specific to SMPI (config)");
37
38 simgrid::config::Flag<std::string> _smpi_cfg_host_speed_string{
39     "smpi/host-speed", "Speed of the host running the simulation (in flop/s). Used to bench the operations.", "20000f",
40     [](const std::string& str) {
41       _smpi_cfg_host_speed = xbt_parse_get_speed("smpi/host-speed", 1, str, "option smpi/host-speed");
42       xbt_assert(_smpi_cfg_host_speed > 0.0, "Invalid value (%s) for 'smpi/host-speed': it must be positive.",
43                  _smpi_cfg_host_speed_string.get().c_str());
44     }};
45
46 simgrid::config::Flag<bool> _smpi_cfg_simulate_computation{
47   "smpi/simulate-computation", "Whether the computational part of the simulated application should be simulated.",
48    true};
49 simgrid::config::Flag<std::string> _smpi_cfg_shared_malloc_string{
50   "smpi/shared-malloc", "Whether SMPI_SHARED_MALLOC is enabled. Disable it for debugging purposes.", "global", 
51   [](const std::string& val) {   
52     if ((val == "yes") || (val == "1") || (val == "on") || (val == "global")) {
53       _smpi_cfg_shared_malloc = SharedMallocType::GLOBAL;
54     } else if (val == "local") {
55       _smpi_cfg_shared_malloc = SharedMallocType::LOCAL;
56     } else if ((val == "no") || (val == "0") || (val == "off")) {
57       _smpi_cfg_shared_malloc = SharedMallocType::NONE;
58     } else {
59       xbt_die("Invalid value '%s' for option smpi/shared-malloc. Possible values: 'on' or 'global', 'local', 'off'",
60       val.c_str());
61     } 
62   } };
63
64 simgrid::config::Flag<double> _smpi_cfg_cpu_threshold{
65   "smpi/cpu-threshold", "Minimal computation time (in seconds) not discarded, or -1 for infinity.", 1e-6,
66   [](const double& val){
67     if (val < 0)
68       _smpi_cfg_cpu_threshold = DBL_MAX;
69   }};
70
71 simgrid::config::Flag<int> _smpi_cfg_async_small_thresh{"smpi/async-small-thresh",
72                                                         "Maximal size of messages that are to be sent asynchronously, without waiting for the receiver",
73                                                         0};
74 simgrid::config::Flag<int> _smpi_cfg_detached_send_thresh{"smpi/send-is-detached-thresh",
75                                                           "Threshold of message size where MPI_Send stops behaving like MPI_Isend and becomes MPI_Ssend", 
76                                                           65536};
77 simgrid::config::Flag<bool> _smpi_cfg_grow_injected_times{"smpi/grow-injected-times",
78                                                           "Whether we want to make the injected time in MPI_Iprobe and MPI_Test grow, to "
79                                                           "allow faster simulation. This can make simulation less precise, though.",
80                                                           true};
81 simgrid::config::Flag<double> _smpi_cfg_iprobe_cpu_usage{"smpi/iprobe-cpu-usage",
82                                                         "Maximum usage of CPUs by MPI_Iprobe() calls. We've observed that MPI_Iprobes "
83                                                         "consume significantly less power than the maximum of a specific application. "
84                                                         "This value is then (Iprobe_Usage/Max_Application_Usage).",
85                                                         1.0};
86
87 simgrid::config::Flag<bool>  _smpi_cfg_trace_call_location{"smpi/trace-call-location",
88                                                            "Should filename and linenumber of MPI calls be traced?", false};
89 simgrid::config::Flag<bool> _smpi_cfg_trace_call_use_absolute_path{"smpi/trace-call-use-absolute-path",
90                                                                    "Should filenames for trace-call tracing be absolute or not?", false};
91 simgrid::config::Flag<std::string> _smpi_cfg_comp_adjustment_file{"smpi/comp-adjustment-file",
92     "A file containing speedups or slowdowns for some parts of the code.", 
93     "", [](const std::string& filename){
94       if (not filename.empty()) {
95         std::ifstream fstream(filename);
96         xbt_assert(fstream.is_open(), "Could not open file %s. Does it exist?", filename.c_str());
97         std::string line;
98         using Tokenizer = boost::tokenizer<boost::escaped_list_separator<char>>;
99         std::getline(fstream, line); // Skip the header line
100         while (std::getline(fstream, line)) {
101           Tokenizer tok(line);
102           auto it              = tok.begin();
103           auto end             = std::next(tok.begin());
104           std::string location = *it;
105           boost::trim(location);
106           location2speedup.insert(std::pair<std::string, double>(location, std::stod(*end)));
107         }
108       }
109     }};
110
111 simgrid::config::Flag<bool> _smpi_cfg_default_errhandler_is_error{
112   "smpi/errors-are-fatal", "Whether MPI errors are fatal or just return. Default is true", true };
113 simgrid::config::Flag<bool> _smpi_cfg_pedantic{
114   "smpi/pedantic", "Activate extra checks that may crash slightly incorrect codes which would not crash on actual implementations", true };
115 simgrid::config::Flag<double> _smpi_init_sleep(
116   "smpi/init", "Time to inject inside a call to MPI_Init", 0.0);
117 #if HAVE_PAPI
118   simgrid::config::Flag<std::string> _smpi_cfg_papi_events_file{"smpi/papi-events",
119                                                                 "This switch enables tracking the specified counters with PAPI", ""};
120 #endif
121
122 simgrid::config::Flag<double> _smpi_cfg_auto_shared_malloc_thresh("smpi/auto-shared-malloc-thresh",
123                                                                   "Threshold size for the automatic sharing of memory",
124                                                                   0);
125
126 simgrid::config::Flag<bool> _smpi_cfg_display_alloc("smpi/display-allocs",
127                                                     "Whether we should display a memory allocations analysis after simulation.",
128                                                      false);
129
130 simgrid::config::Flag<int> _smpi_cfg_list_leaks("smpi/list-leaks",
131                                                 "Whether we should display the n first MPI handle leaks (addresses and type only) after simulation",
132                                                 -1);
133
134 double smpi_cfg_host_speed(){
135   return _smpi_cfg_host_speed;
136 }
137
138 bool smpi_cfg_simulate_computation(){
139   return _smpi_cfg_simulate_computation;
140 }
141
142 SharedMallocType smpi_cfg_shared_malloc(){
143   return _smpi_cfg_shared_malloc;
144 }
145
146 double smpi_cfg_cpu_thresh(){
147   return _smpi_cfg_cpu_threshold;
148 }
149
150 SmpiPrivStrategies smpi_cfg_privatization(){
151   return _smpi_cfg_privatization;
152 }
153
154 int smpi_cfg_async_small_thresh(){
155   return _smpi_cfg_async_small_thresh;
156 }
157
158 int smpi_cfg_detached_send_thresh(){
159   return _smpi_cfg_detached_send_thresh;
160 }
161
162 bool smpi_cfg_grow_injected_times(){
163   return _smpi_cfg_grow_injected_times;
164 }
165
166 double smpi_cfg_iprobe_cpu_usage(){
167   return _smpi_cfg_iprobe_cpu_usage;
168 }
169
170 bool smpi_cfg_trace_call_location(){
171   return _smpi_cfg_trace_call_location;
172 }
173
174 bool smpi_cfg_trace_call_use_absolute_path(){
175   return _smpi_cfg_trace_call_use_absolute_path;
176 }
177
178 bool smpi_cfg_display_alloc(){
179   return _smpi_cfg_list_leaks != -1 ? true : _smpi_cfg_display_alloc;
180 }
181
182 std::string smpi_cfg_comp_adjustment_file(){
183   return _smpi_cfg_comp_adjustment_file;
184 }
185 #if HAVE_PAPI
186 std::string smpi_cfg_papi_events_file(){
187   return _smpi_cfg_papi_events_file;
188 }
189 #endif
190 double smpi_cfg_auto_shared_malloc_thresh(){
191   return _smpi_cfg_auto_shared_malloc_thresh;
192 }
193
194 // public version declared in smpi.h (without parameter, and with C linkage)
195 void smpi_init_options()
196 {
197   smpi_init_options_internal(false);
198 }
199
200 void smpi_init_options_internal(bool called_by_smpi_main)
201 {
202   static bool smpi_options_initialized = false;
203   static bool running_with_smpi_main   = false;
204
205   if (called_by_smpi_main)
206     running_with_smpi_main = true;
207
208   // return if already called
209   if (smpi_options_initialized)
210     return;
211   simgrid::config::declare_flag<bool>("smpi/display-timing", "Whether we should display the timing after simulation.", false);
212   simgrid::config::declare_flag<bool>("smpi/keep-temps", "Whether we should keep the generated temporary files.", false);
213   simgrid::config::declare_flag<std::string>("smpi/tmpdir", "tmp dir for dlopen files", "/tmp");
214
215   simgrid::config::declare_flag<std::string>("smpi/coll-selector", "Which collective selector to use", "default");
216   simgrid::config::declare_flag<std::string>("smpi/gather", "Which collective to use for gather", "");
217   simgrid::config::declare_flag<std::string>("smpi/allgather", "Which collective to use for allgather", "");
218   simgrid::config::declare_flag<std::string>("smpi/barrier", "Which collective to use for barrier", "");
219   simgrid::config::declare_flag<std::string>("smpi/reduce_scatter", "Which collective to use for reduce_scatter", "");
220   simgrid::config::declare_flag<std::string>("smpi/scatter", "Which collective to use for scatter", "");
221   simgrid::config::declare_flag<std::string>("smpi/allgatherv", "Which collective to use for allgatherv", "");
222   simgrid::config::declare_flag<std::string>("smpi/allreduce", "Which collective to use for allreduce", "");
223   simgrid::config::declare_flag<std::string>("smpi/alltoall", "Which collective to use for alltoall", "");
224   simgrid::config::declare_flag<std::string>("smpi/alltoallv", "Which collective to use for alltoallv", "");
225   simgrid::config::declare_flag<std::string>("smpi/bcast", "Which collective to use for bcast", "");
226   simgrid::config::declare_flag<std::string>("smpi/reduce", "Which collective to use for reduce", "");
227
228   const char* default_privatization = std::getenv("SMPI_PRIVATIZATION");
229   if (default_privatization == nullptr)
230     default_privatization = "no";
231
232   simgrid::config::declare_flag<std::string>(
233       "smpi/privatization", "How we should privatize global variable at runtime (no, yes, mmap, dlopen).",
234       default_privatization, [](const std::string& smpi_privatize_option) {
235         if (smpi_privatize_option == "no" || smpi_privatize_option == "0")
236           _smpi_cfg_privatization = SmpiPrivStrategies::NONE;
237         else if (smpi_privatize_option == "yes" || smpi_privatize_option == "1")
238           _smpi_cfg_privatization = SmpiPrivStrategies::DEFAULT;
239         else if (smpi_privatize_option == "mmap")
240           _smpi_cfg_privatization = SmpiPrivStrategies::MMAP;
241         else if (smpi_privatize_option == "dlopen")
242           _smpi_cfg_privatization = SmpiPrivStrategies::DLOPEN;
243         else
244           xbt_die("Invalid value for smpi/privatization: '%s'", smpi_privatize_option.c_str());
245
246         if (not running_with_smpi_main) {
247           XBT_DEBUG("Running without smpi_main(); disable smpi/privatization.");
248           _smpi_cfg_privatization = SmpiPrivStrategies::NONE;
249         }
250         if (not HAVE_WORKING_MMAP && _smpi_cfg_privatization == SmpiPrivStrategies::MMAP) {
251           XBT_INFO("mmap privatization is broken on this platform, switching to dlopen privatization instead.");
252           _smpi_cfg_privatization = SmpiPrivStrategies::DLOPEN;
253         }
254       });
255
256   simgrid::config::declare_flag<std::string>("smpi/privatize-libs", 
257                                             "Add libraries (; separated) to privatize (libgfortran for example)."
258                                             "You need to provide the full names of the files (libgfortran.so.4), or its full path", 
259                                             "");
260   simgrid::config::declare_flag<double>("smpi/shared-malloc-blocksize",
261                                         "Size of the bogus file which will be created for global shared allocations", 
262                                         1UL << 20);
263   simgrid::config::declare_flag<std::string>("smpi/shared-malloc-hugepage",
264                                              "Path to a mounted hugetlbfs, to use huge pages with shared malloc.", 
265                                              "");
266
267   simgrid::config::declare_flag<std::string>(
268       "smpi/os", "Small messages timings (MPI_Send minimum time for small messages)", "0:0:0:0:0");
269   simgrid::config::declare_flag<std::string>(
270       "smpi/ois", "Small messages timings (MPI_Isend minimum time for small messages)", "0:0:0:0:0");
271   simgrid::config::declare_flag<std::string>(
272       "smpi/or", "Small messages timings (MPI_Recv minimum time for small messages)", "0:0:0:0:0");
273
274   simgrid::config::declare_flag<bool>("smpi/finalization-barrier", "Do we add a barrier in MPI_Finalize or not", false);
275
276   smpi_options_initialized = true;
277 }
278
279 void smpi_check_options()
280 {
281 #if SIMGRID_HAVE_MC
282   if (MC_is_active()) {
283     if (_sg_mc_buffering == "zero")
284       simgrid::config::set_value<int>("smpi/send-is-detached-thresh", 0);
285     else if (_sg_mc_buffering == "infty")
286       simgrid::config::set_value<int>("smpi/send-is-detached-thresh", INT_MAX);
287     else
288       THROW_IMPOSSIBLE;
289   }
290 #endif
291
292   xbt_assert(smpi_cfg_async_small_thresh() <= smpi_cfg_detached_send_thresh(),
293              "smpi/async-small-thresh (=%d) should be smaller or equal to smpi/send-is-detached-thresh (=%d)",
294              smpi_cfg_async_small_thresh(),
295              smpi_cfg_detached_send_thresh());
296
297   if (simgrid::config::is_default("smpi/host-speed") && not MC_is_active()) {
298     XBT_INFO("You did not set the power of the host running the simulation.  "
299              "The timings will certainly not be accurate.  "
300              "Use the option \"--cfg=smpi/host-speed:<flops>\" to set its value.  "
301              "Check "
302              "https://simgrid.org/doc/latest/Configuring_SimGrid.html#automatic-benchmarking-of-smpi-code for more "
303              "information.");
304   }
305
306   simgrid::smpi::colls::set_collectives();
307   simgrid::smpi::colls::smpi_coll_cleanup_callback = nullptr;
308 }
309