Logo AND Algorithmique Numérique Distribuée

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