OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
IpplInfo.cpp
Go to the documentation of this file.
1//
2// IpplInfo has the following capabilities:
3// 1) It initializes all globally-used Ippl variables, such as the
4// Communicate class and other manager classes;
5// 2) It parses command-line arguments to determine how to configure the
6// global state of the Ippl application;
7// 3) It properly selects and configures the Communicate class, generally
8// resulting in initialization of the parallel machine;
9// 4) It offers to the user a single class with access member functions to
10// query for information about the Ippl application (such as what is
11// the Communicate class instance to use, how many processors are there
12// in the current run, etc.)
13//
14// Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
15//
16// All rights reserved
17//
18// This file is part of OPAL.
19//
20// OPAL is free software: you can redistribute it and/or modify
21// it under the terms of the GNU General Public License as published by
22// the Free Software Foundation, either version 3 of the License, or
23// (at your option) any later version.
24//
25// You should have received a copy of the GNU General Public License
26// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
27//
28#include "Utility/IpplInfo.h"
29#include "Utility/Inform.h"
30#include "Utility/IpplStats.h"
31#include "Utility/PAssert.h"
33#include "Utility/vmap.h"
35#include "Message/CommCreator.h"
36#include "Message/Communicate.h"
37
38#include "IpplVersions.h"
39
40#include <unistd.h>
41#include <cstdio>
42#include <csignal>
43
45// public static members of IpplInfo, initialized to default values
52
54 if (Comm == 0)
55 Comm = new Communicate();
56 if (Stats == 0)
57 Stats = new IpplStats();
58 if (Info == 0)
59 Info = new Inform("Ippl");
60 if (Warn == 0)
61 Warn = new Inform("Warning", std::cerr);
62 if (Error == 0)
63 Error = new Inform("Error", std::cerr, INFORM_ALL_NODES);
64 if (Debug == 0)
65 Debug = new Inform("**DEBUG**", std::cerr, INFORM_ALL_NODES);
66}
67
69 delete Comm;
70 delete Stats;
71 delete Info;
72 delete Warn;
73 delete Error;
74 delete Debug;
75
76 Comm = 0;
77 Stats = 0;
78 Info = 0;
79 Warn = 0;
80 Error = 0;
81 Debug = 0;
82}
83
84std::stack<StaticIpplInfo> IpplInfo::stashedStaticMembers;
85
86// should we use the optimization of deferring guard cell fills until
87// absolutely needed? Can be changed to true by specifying the
88// flag --defergcfill
90
91// should we use the compression capabilities in {[Bare]Field,LField}? Can be
92// changed to false by specifying the flag --nofieldcompression
94
95// private static members of IpplInfo, initialized to default values
96MPI_Comm IpplInfo::communicator_m = MPI_COMM_WORLD;
98bool IpplInfo::CommInitialized = false;
99bool IpplInfo::PrintStats = false;
100bool IpplInfo::NeedDeleteComm = false;
101int IpplInfo::MyArgc = 0;
102char **IpplInfo::MyArgv = 0;
103int IpplInfo::MyNode = 0;
105int IpplInfo::NumSMPs = 1;
106int* IpplInfo::SMPIDList = 0;
107int* IpplInfo::SMPNodeList = 0;
108bool IpplInfo::UseChecksums = false;
109bool IpplInfo::Retransmit = false;
111int IpplInfo::ChunkSize = 512*1024; // 512K == 64K doubles
112bool IpplInfo::PerSMPParallelIO = false;
113bool IpplInfo::offsetStorage = false;
115
117// print out current state to the given output stream
118std::ostream& operator<<(std::ostream& o, const IpplInfo&) {
119 o << "------------------------------------------\n";
120 o << "IPPL Framework Application Summary:\n";
121 o << " Running on node " << IpplInfo::myNode();
122 o << ", out of " << IpplInfo::getNodes() << " total.\n";
123 o << " Number of SMPs: " << IpplInfo::getSMPs() << "\n";
124 o << " Relative SMP node: " << IpplInfo::mySMPNode();
125 o << ", out of " << IpplInfo::getSMPNodes(IpplInfo::mySMP());
126 o << " nodes.\n";
127 o << " Communication method: " << IpplInfo::Comm->name() << "\n";
128 o << " Disc read chunk size: " << IpplInfo::chunkSize() << " bytes.\n";
129 o << " Deferring guard cell fills? ";
131 o << " Turning off Field compression? ";
132 o << IpplInfo::noFieldCompression << "\n";
133 o << " Offsetting storage? ";
134 o << IpplInfo::offsetStorage << "\n";
135 o << " Using extra compression checks in expressions? ";
137 o << " Use per-SMP parallel IO? ";
138 o << IpplInfo::perSMPParallelIO() << "\n";
139 o << " Computing message CRC checksums? ";
140 o << IpplInfo::useChecksums() << "\n";
141 o << " Retransmit messages on error (only if checkums on)? ";
142 o << IpplInfo::retransmit() << "\n";
143
144 o << " Elapsed wall-clock time (in seconds): ";
145 o << IpplInfo::Stats->getTime().clock_time() << "\n";
146 o << " Elapsed CPU-clock time (in seconds) : ";
147 o << IpplInfo::Stats->getTime().cpu_time() << "\n";
148 o << "------------------------------------------\n";
149 return o;
150}
151
152
154// Constructor 1: parse argc, argv, and create proper Communicate object
155// The second argument controls whether the IPPL-specific command line
156// arguments are stripped out (the default) or left in (if the setting
157// is IpplInfo::KEEP).
158IpplInfo::IpplInfo(int& argc, char**& argv, int removeargs, MPI_Comm mpicomm) {
159
160 int i; // loop variables
161 int connectoption = (-1); // for connection method option
162 int retargc; // number of args to return to caller
163 char **retargv; // arguments to return
164 bool printsummary = false; // print summary at end of constructor
165
166 //Inform dbgmsg("IpplInfo(argc,argv)", INFORM_ALL_NODES);
167
168 // determine whether we should strip out ippl-specific arguments, or keep
169 bool stripargs = (removeargs != KEEP);
170
171 communicator_m = mpicomm;
172
173 if (NumCreated == 0) {
174 Comm = new Communicate();
175 Stats = new IpplStats();
176 Info = new Inform("Ippl");
177 Warn = new Inform("Warning", std::cerr);
178 Error = new Inform("Error", std::cerr, INFORM_ALL_NODES);
179 Debug = new Inform("**DEBUG**", std::cerr, INFORM_ALL_NODES);
180 }
181 // You can only specify argc, argv once; if it is done again, print a warning
182 // and continue as if we had not given argc, argv.
183 if ( CommInitialized ) {
184 // ADA WARNMSG("Attempt to create IpplInfo with argc, argv again." << endl);
185 //WARNMSG("Using previous argc,argv settings." << endl);
186 } else {
187 // dbgmsg << "Starting initialization: argc = " << argc << ", " << endl;
188 // for (unsigned int dbgi=0; dbgi < argc; ++dbgi)
189 // dbgmsg << " argv[" << dbgi << "] = '" << argv[dbgi] << "'" << endl;
190
191 // first make a pass through the arguments, figure out whether we should
192 // run in parallel, and start up the parallel environment. After this,
193 // process all the other cmdline args
194 std::string commtype;
195 bool startcomm = false;
196 bool comminit = true; // do comm. system's init call
197 int nprocs = (-1); // num of processes to start; -1 means default
198
199
200 /*
201 if no argument is given, we assume mpi as
202 communication method
203 */
204 commtype = std::string("mpi");
205 startcomm = true;
206
207 for (i=1; i < argc; ++i) {
208 if ( ( strcmp(argv[i], "--processes") == 0 ) ||
209 ( strcmp(argv[i], "-procs") == 0 ) ) {
210 // The user specified how many processes to use. This may not be useful
211 // for all communication methods.
212 if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) > 0 )
213 nprocs = atoi(argv[++i]);
214 else
215 param_error(argv[i],
216 "Please specify a positive number of processes", 0);
217 } else if ( ( strcmp(argv[i], "--commlib") == 0 ) ||
218 ( strcmp(argv[i], "-comm") == 0 ) ) {
219 // The user specified what kind of comm library to use
220 if ( (i + 1) < argc && argv[i+1][0] != '-' ) {
221 commtype = argv[++i];
222 startcomm = true;
223 } else {
224 param_error(argv[i], "Please use one of: ",
226 startcomm = false;
227 }
228
229 } else if ( strcmp(argv[i], "--nocomminit") == 0 ) {
230 // The user requested that we do not let the run-time system call
231 // whatever initialization routine it might have (like MPI_Init).
232 // This is in case another agency has already done the initialization.
233 comminit = false;
234 }
235 }
236
237 // create Communicate object now.
238 // dbgmsg << "Setting up parallel environment ..." << endl;
239 if (startcomm && nprocs != 0 && nprocs != 1) {
240 // dbgmsg << " commlibarg=" << commtype << endl;
241 // dbgmsg << ", nprocs=" << nprocs << endl;
242 Communicate *newcomm = CommCreator::create(commtype.c_str(),
243 argc, argv,
244 nprocs, comminit, mpicomm);
245
246 if (newcomm == 0) {
247 if (CommCreator::supported(commtype.c_str()))
248 param_error("--commlib", "Could not initialize this ",
249 "communication library.", commtype.c_str());
250 else if (CommCreator::known(commtype.c_str()))
251 param_error("--commlib", "This communication library is not ",
252 "available.", commtype.c_str());
253 else
254 param_error("--commlib", "Please use one of: ",
256 } else {
257 // success, we have a new comm object
258 NeedDeleteComm = true;
259 delete Comm;
260 Comm = newcomm;
261
262 // cache our node number and node count
263 MyNode = Comm->myNode();
264 TotalNodes = Comm->getNodes();
266
267 // advance the default random number generator
268 IpplRandom.AdvanceSeed(Comm->myNode());
269
270 // dbgmsg << " Comm creation successful." << endl;
271 // dbgmsg << *this << endl;
272 }
273 }
274
275 // dbgmsg << "After comm init: argc = " << argc << ", " << endl;
276 // for (unsigned int dbgi=0; dbgi < argc; ++dbgi)
277 // dbgmsg << " argv[" << dbgi << "] = '" << argv[dbgi] << "'" << endl;
278
279 // keep track of which arguments we do no use; these are returned
280 retargc = 1;
281 retargv = new char*[argc];
282 retargv[0] = argv[0]; // we always return arg 0 (the exec. name)
283
284 // if we're not stripping out arguments, just save all the args
285 if (!stripargs)
286 for (i=1; i < argc; ++i)
287 retargv[retargc++] = argv[i];
288
289
290 // Parse command-line options, looking for ippl options. When found,
291 // save their suggested values and use them at the end to create data, etc.
292 for (i=1; i < argc; ++i) {
293 if ( ( strcmp(argv[i], "--processes") == 0 ) ||
294 ( strcmp(argv[i], "-procs") == 0 ) ) {
295 // handled above
296 if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) > 0 )
297 ++i;
298
299 } else if ( ( strcmp(argv[i], "--nocomminit") == 0 ) ) {
300 // handled above, nothing to do here but skip the arg
301
302 } else if ( ( strcmp(argv[i], "--summary") == 0 ) ) {
303 // set flag to print out summary of Ippl library settings at the
304 // end of this constructor
305 printsummary = true;
306
307 } else if ( ( strcmp(argv[i], "--ipplversion") == 0 ) ) {
308 printVersion();
309 std::string options = compileOptions();
310 std::string header("Compile-time options: ");
311 while (options.length() > 58) {
312 std::string line = options.substr(0, 58);
313 size_t n = line.find_last_of(' ');
314 INFOMSG(header << line.substr(0, n) << "\n");
315
316 header = std::string(22, ' ');
317 options = options.substr(n + 1);
318 }
319 INFOMSG(header << options << endl);
320 exit(0);
321
322 } else if ( ( strcmp(argv[i], "--checksums") == 0 ) ||
323 ( strcmp(argv[i], "--checksum") == 0 ) ) {
324 UseChecksums = true;
325
326 } else if ( ( strcmp(argv[i], "--retransmit") == 0 ) ) {
327 Retransmit = true;
328
329 } else if ( ( strcmp(argv[i], "--ipplversionall") == 0 ) ||
330 ( strcmp(argv[i], "-vall") == 0 ) ) {
331 printVersion();
332 std::string options = compileOptions();
333 std::string header("Compile-time options: ");
334 while (options.length() > 58) {
335 std::string line = options.substr(0, 58);
336 size_t n = line.find_last_of(' ');
337 INFOMSG(header << line.substr(0, n) << "\n");
338
339 header = std::string(22, ' ');
340 options = options.substr(n + 1);
341 }
342 INFOMSG(header << options << endl);
343 exit(0);
344
345 } else if ( ( strcmp(argv[i], "--time") == 0 ) ||
346 ( strcmp(argv[i], "-time") == 0 ) ||
347 ( strcmp(argv[i], "--statistics") == 0 ) ||
348 ( strcmp(argv[i], "-stats") == 0 ) ) {
349 // The user specified that the program stats be printed at
350 // the end of the program.
351 PrintStats = true;
352
353 } else if ( ( strcmp(argv[i], "--info") == 0 ) ) {
354 // Set the output level for informative messages.
355 if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) >= 0 )
356 Info->setOutputLevel(atoi(argv[++i]));
357 else
358 param_error(argv[i],
359 "Please specify an output level from 0 to 5", 0);
360
361 } else if ( ( strcmp(argv[i], "--warn") == 0 ) ) {
362 // Set the output level for warning messages.
363 if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) >= 0 )
364 Warn->setOutputLevel(atoi(argv[++i]));
365 else
366 param_error(argv[i],
367 "Please specify an output level from 0 to 5", 0);
368
369 } else if ( ( strcmp(argv[i], "--error") == 0 ) ) {
370 // Set the output level for error messages.
371 if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) >= 0 )
372 Error->setOutputLevel(atoi(argv[++i]));
373 else
374 param_error(argv[i],
375 "Please specify an output level from 0 to 5", 0);
376
377 } else if ( ( strcmp(argv[i], "--debug") == 0 ) ) {
378 // Set the output level for debug messages.
379 if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) >= 0 )
380 Debug->setOutputLevel(atoi(argv[++i]));
381 else
382 param_error(argv[i],
383 "Please specify an output level from 0 to 5", 0);
384
385 } else if ( ( strcmp(argv[i], "--connect") == 0 ) ) {
386 // Set the default external connection method
387 if ( (i + 1) < argc && argv[i+1][0] != '-' )
388 connectoption = ++i;
389 else
390 param_error(argv[i], "Please use one of: ",
392
393 } else if ( ( strcmp(argv[i], "--connectnodes") == 0 ) ) {
394 // Set the number of nodes that are used in connections, by default
395 if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) > 0 )
397 else
398 param_error(argv[i],
399 "Please specify a number of nodes for connections > 0",
400 0);
401
402 } else if ( ( strcmp(argv[i], "--commlib") == 0 ) ||
403 ( strcmp(argv[i], "-comm") == 0 ) ) {
404 // handled above
405 if ( (i + 1) < argc && argv[i+1][0] != '-' )
406 ++i;
407
408 } else if ( strcmp(argv[i], "--profile") == 0 ) {
409 // handled above in
410 if ( (i + 1) < argc && argv[i+1][0] != '-' )
411 ++i;
412
413 } else if ( ( strcmp(argv[i], "--persmppario") == 0 ) ) {
414 // Turn on the ability to use per-smp parallel IO
415 PerSMPParallelIO = true;
416
417 } else if ( ( strcmp(argv[i], "--nopersmppario") == 0 ) ) {
418 // Turn off the ability to use per-smp parallel IO
419 PerSMPParallelIO = false;
420
421 } else if ( ( strcmp(argv[i], "--chunksize") == 0 ) ) {
422 // Set the I/O chunk size, used to limit how many items
423 // are read in or written to disk at one time.
424 if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) >= 0 ) {
425 ChunkSize = atoi(argv[++i]);
426 char units = static_cast<char>(toupper(argv[i][strlen(argv[i])-1]));
427 if (units == 'K')
428 ChunkSize *= 1024;
429 else if (units == 'M')
430 ChunkSize *= 1024*1024;
431 else if (units == 'G')
432 ChunkSize *= 1024*1024*1024;
433 } else {
434 param_error(argv[i],
435 "Please specify a timeout value (in seconds)", 0);
436 }
437 } else if ( ( strcmp(argv[i], "--defergcfill") == 0 ) ) {
438 // Turn on the defer guard cell fill optimization
439 deferGuardCellFills = true;
440
441 } else if ( ( strcmp(argv[i], "--offsetstorage") == 0 ) ) {
442 // Turn on the offset-storage modification to LFields
443 offsetStorage = true;
444
445 } else if ( ( strcmp(argv[i], "--extracompcheck") == 0 ) ) {
446 // Turn on the extra compression checks in expressions
447 extraCompressChecks = true;
448
449 } else if ( ( strcmp(argv[i], "--nofieldcompression") == 0 ) ) {
450 // Turn off compression in the Field classes
451 noFieldCompression = true;
452
453 } else if ( ( strcmp(argv[i], "--directio") == 0 ) ) {
454 // Turn on the use of Direct-IO, if possible
455 param_error(argv[i],
456 "Direct-IO is not available in this build of IPPL", 0);
457 } else if ( ( strcmp(argv[i], "--maxfftnodes") == 0 ) ) {
458 // Limit the number of nodes that can participate in FFT operations
459 if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) > 0 )
460 MaxFFTNodes = atoi(argv[++i]);
461 else
462 param_error(argv[i],
463 "Please specify a maximum number of FFT nodes > 0", 0);
464
465 } else if ( ( strcmp(argv[i], "--ipplhelp") == 0 ) ||
466 ( strcmp(argv[i], "-h") == 0 ) ||
467 ( strcmp(argv[i], "-?") == 0 ) ) {
468 // print out summary of command line switches and exit
469 INFOMSG("Usage: " << argv[0] << " [<option> <option> ...]\n");
470 INFOMSG(" The possible values for <option> are:\n");
471 printHelp();
472 INFOMSG(" --ipplversion : Print a brief version summary.\n");
473 INFOMSG(" --ipplversionall : Print a detailed version summary.\n");
474 INFOMSG(" --ipplhelp : Display this command-line summary.\n");
475 INFOMSG(endl);
476 exit(0);
477
478 } else {
479 // Unknown option; just ignore it.
480 if (stripargs)
481 retargv[retargc++] = argv[i];
482 }
483 }
484
485 // We can get on with creating and initializing all globally-used objects.
486
487 // Select the default connection method
488 if ( connectoption >= 0 ) {
489 if ( ! DataConnectCreator::setDefaultMethod(argv[connectoption]) ) {
490 if (DataConnectCreator::supported(argv[connectoption]))
491 param_error(argv[connectoption - 1], "Could not initialize this ",
492 "connection.", argv[connectoption]);
493 else if (DataConnectCreator::known(argv[connectoption]))
494 param_error(argv[connectoption - 1],"This connection method is not ",
495 "available.", argv[connectoption]);
496 else
497 param_error(argv[connectoption - 1], "Please use one of: ",
499 }
500 }
501
502 // indicate back to the caller which arguments are left
503 MyArgc = retargc;
504 MyArgv = retargv;
505 if (stripargs) {
506 argc = retargc;
507 argv = retargv;
508 }
509
510 // Inform dbgmsg("IpplInfo::IpplInfo", INFORM_ALL_NODES);
511 // dbgmsg << "Created IpplInfo. node = " << MyNode << " out of ";
512 // dbgmsg << TotalNodes << ", commlib = " << Comm->name() << endl;
513
514 // now, at end, start the timer running, and print out a summary if asked
515 Stats->getTime().stop();
516 Stats->getTime().clear();
517 Stats->getTime().start();
518 }
519
520 // indicate we've created one more Ippl object
521 CommInitialized = true;
522 NumCreated++;
523
524 // At the very end, print out a summary if requested
525 if (printsummary)
526 INFOMSG(*this << endl);
527}
528
529
531// Constructor 2: default constructor.
533 if (NumCreated == 0) {
534 Comm = new Communicate();
535 Stats = new IpplStats();
536 Info = new Inform("Ippl");
537 Warn = new Inform("Warning", std::cerr);
538 Error = new Inform("Error", std::cerr, INFORM_ALL_NODES);
539 Debug = new Inform("**DEBUG**", std::cerr, INFORM_ALL_NODES);
540 }
541
542 // just indicate we've also been created
543 NumCreated++;
544}
545
546
548// Constructor 3: copy constructor.
550 if (NumCreated == 0) {
551 Comm = new Communicate();
552 Stats = new IpplStats();
553 Info = new Inform("Ippl");
554 Warn = new Inform("Warning", std::cerr);
555 Error = new Inform("Error", std::cerr, INFORM_ALL_NODES);
556 Debug = new Inform("**DEBUG**", std::cerr, INFORM_ALL_NODES);
557 }
558
559 // just indicate we've also been created
560 NumCreated++;
561}
562
563
565// Destructor: need to delete comm library if this is the last IpplInfo
567 // indicate we have one less instance; if this is the last one,
568 // close communication and clean up
569 // Inform dbgmsg("IpplInfo::~IpplInfo", INFORM_ALL_NODES);
570 // dbgmsg << "In destructor: Current NumCreated = " << NumCreated << endl;
571
572 if ((--NumCreated) == 0) {
573 // at end of program, print statistics if requested to do so
574 if (PrintStats) {
575 Inform statsmsg("Stats", INFORM_ALL_NODES);
576 statsmsg << *this;
577 printStatistics(statsmsg);
578 }
579
580 // Delete the communications object, if necessary, to shut down parallel
581 // environment
582 if (NeedDeleteComm) {
583 // dbgmsg << " Deleting comm object, since now NumCreated = ";
584 // dbgmsg << NumCreated << endl;
585 delete Comm;
586 Comm = 0;
587 NeedDeleteComm = false;
588 }
589 CommInitialized = false;
590
591 // delete other dynamically-allocated static objects
592 delete [] MyArgv;
593 if (SMPIDList != 0) {
594 delete [] SMPIDList;
595 }
596 if (SMPNodeList != 0) {
597 delete [] SMPNodeList;
598 }
599 delete Stats;
600
601 MyArgv = 0;
602 SMPIDList = 0;
603 SMPNodeList = 0;
604 Stats = 0;
605 }
606}
607
608
610// equal operator
612 // nothing to do, we don't even need to indicate we've made another
613 return *this;
614}
615
616void IpplInfo::abort(const char *msg) {
617 // print out message, if one was provided
618 if (msg != 0) {
619 ERRORMSG(msg << endl);
620 }
621
622 // print out final stats, if necessary
623 if (PrintStats) {
624 Inform statsmsg("Stats", INFORM_ALL_NODES);
625 statsmsg << IpplInfo();
626 printStatistics(statsmsg);
627 }
628
629 // delete communication object, if necessary
630 if (NeedDeleteComm) {
631 NeedDeleteComm = false;
632 delete Comm;
633 Comm = 0;
634 }
635
636 // that's it, folks this error will be propperly catched in the main
637 throw std::runtime_error("Error form IpplInfo::abort");
638}
639
640
642// Signal to ALL the nodes that we should exit or abort. If we abort,
643// a core file will be produced. If we exit, no core file will be made.
644// The node which calls abortAllNodes will print out the given message;
645// the other nodes will print out that they are aborting due to a message
646// from this node.
647void IpplInfo::abortAllNodes(const char *msg) {
648 // print out message, if one was provided
649 if (msg != 0) {
650 ERRORMSG(msg << endl);
651 }
652
653 // print out final stats, if necessary
654 if (PrintStats) {
655 Inform statsmsg("Stats", INFORM_ALL_NODES);
656 statsmsg << IpplInfo();
657 printStatistics(statsmsg);
658 }
659
660 // broadcast out the kill message, if necessary
661 if (getNodes() > 1)
662 Comm->broadcast_others(new Message, IPPL_ABORT_TAG);
663
664 throw std::runtime_error("Error form IpplInfo::abortAllNodes");
665
666}
667
669// getNodes: return the number of 'Nodes' in use for the computation
671 return TotalNodes;
672}
673
674
676// getContexts: return the number of 'Contexts' for the given node
677int IpplInfo::getContexts(const int n) {
678 return Comm->getContexts(n);
679}
680
681
683// getProcesses: return the number of 'Processes' for the given Node and Context
684int IpplInfo::getProcesses(const int n, const int c) {
685 return Comm->getProcesses(n, c);
686}
687
688
690// myNode: return which Node we are running on right now
692 return MyNode;
693}
694
695
697// getSMPs: return number of SMP's (each of which may be running
698// several processes)
700 return NumSMPs;
701}
702
703
705// getSMPNodes: return number of nodes on the SMP with the given index
706int IpplInfo::getSMPNodes(int smpindx) {
707 int num = 0;
708 if (SMPIDList == 0) {
709 num = 1;
710 } else {
711 for (int i=0; i < TotalNodes; ++i)
712 if (SMPIDList[i] == smpindx)
713 num++;
714 }
715 return num;
716}
717
718
720// mySMP: return ID of my SMP (numbered 0 ... getSMPs() - 1)
722 return (SMPIDList != 0 ? SMPIDList[MyNode] : 0);
723}
724
725
727// mySMPNode: return relative node number within the nodes on our SMP
729 return (SMPNodeList != 0 ? SMPNodeList[MyNode] : 0);
730}
731
732
734// printVersion: print out a version summary. If the argument is true,
735// print out a detailed listing, otherwise a summary.
737 INFOMSG("IPPL Framework version " << version() << endl);
738 INFOMSG("Last build date: " << compileDate() << " by user ");
740 INFOMSG("Built for machine: " << compileMachine() << endl);
741}
742
743
745 INFOMSG(" --summary : Print IPPL lib summary at start.\n");
746 INFOMSG(" --processes <n> : Number of parallel nodes to use.\n");
747 INFOMSG(" --commlib <x> : Selects a parallel comm. library.\n");
748 INFOMSG(" <x> = ");
750 INFOMSG(" --nocomminit : IPPL does not do communication\n");
751 INFOMSG(" initialization, assume already done.\n");
752 INFOMSG(" --connect <x> : Select external connection method.\n");
753 INFOMSG(" <x> = ");
755 INFOMSG(" --time : Show total time used in execution.\n");
756 INFOMSG(" --notime : Do not show timing info (default).\n");
757 INFOMSG(" --info <n> : Set info message level. 0 = off.\n");
758 INFOMSG(" --warn <n> : Set warning message level. 0 = off.\n");
759 INFOMSG(" --error <n> : Set error message level. 0 = off.\n");
760 INFOMSG(" --debug <n> : Set debug message level. 0 = off.\n");
761 /*#ifdef PROFILING_ON
762 INFOMSG(" --profile <gr> : Enable profiling for groups (e.g., M+P+io) \n");
763 INFOMSG(" M - Message, P - Pete, V - Viz, A - Assign, I - IO\n");
764 INFOMSG(" F - Field, L - Layout, S - Sparse, D - Domainmap \n");
765 INFOMSG(" Ut - Utility, R - Region, Ff - FFT \n");
766 INFOMSG(" U - User, 1 - User1, 2 - User2, 3 - User3, 4 - User4\n");
767
768 #endif*/ //PROFILING_ON
769 INFOMSG(" --defergcfill : Turn on deferred guard cell fills.\n");
770 INFOMSG(" --nofieldcompression : Turn off compression in the Field classes.\n");
771 INFOMSG(" --offsetstorage : Turn on random LField storage offsets.\n");
772 INFOMSG(" --extracompcheck : Turn on extra compression checks in evaluator.\n");
773 INFOMSG(" --checksums : Turn on CRC checksums for messages.\n");
774 INFOMSG(" --retransmit : Resent messages if a CRC error occurs.\n");
775 INFOMSG(" --maxfftnodes <n> : Limit the nodes that work on FFT's.\n");
776 INFOMSG(" --chunksize <n> : Set I/O chunk size. Can end w/K,M,G.\n");
777 INFOMSG(" --persmppario : Enable on-SMP parallel IO option.\n");
778 INFOMSG(" --nopersmppario : Disable on-SMP parallel IO option (default).\n");
779}
780
782// here: as in stop in IpplInfo::here (in the debugger)
784{
785}
786
788// print out statistics to the given Inform stream
790
791
793// version: return the name of this version of Ippl, as a string
794// (from Versions.h)
795const char *IpplInfo::version() {
796 return ippl_version_name;
797}
798
799
800
802// compileArch: return the architecture on which this library was built
803// (from IpplVersions.h)
805 return ippl_compile_arch;
806}
807
808
810// compileDate: return the date on which this library was prepared for
811// compilation (from IpplVersions.h)
813 return ippl_compile_date;
814}
815
816
818// compileLine: return the compiler command used to compile each source file
819// (from IpplVersions.h)
821 return ippl_compile_line;
822}
823
824
826// compileMachine: return the machine on which this library was
827// compiled (from IpplVersions.h)
830}
831
832
834// compileOptions: return the option list used to compile this library
835// (from IpplVersions.h)
838}
839
840
842// compileUser: return the username of the user who compiled this
843// library (from IpplVersions.h)
845 return ippl_compile_user;
846}
847
848
850// param_error: print out an error message when an illegal cmd-line
851// parameter is encountered.
852// Arguments are: parameter, error message, bad value (if any)
853void IpplInfo::param_error(const char *param, const char *msg,
854 const char *bad) {
855 if ( param != 0 )
856 ERRORMSG(param << " ");
857 if ( bad != 0 )
858 ERRORMSG(bad << " ");
859 if ( msg != 0 )
860 ERRORMSG(": " << msg);
861 ERRORMSG(endl);
863}
864
865void IpplInfo::param_error(const char *param, const char *msg1,
866 const char *msg2, const char *bad) {
867 if ( param != 0 )
868 ERRORMSG(param << " ");
869 if ( bad != 0 )
870 ERRORMSG(bad << " ");
871 if ( msg1 != 0 )
872 ERRORMSG(": " << msg1);
873 if ( msg2 != 0 )
874 ERRORMSG(msg2);
875 ERRORMSG(endl);
877}
878
879
881// find out how many SMP's there are, and which processor we are on
882// our local SMP (e.g., if there are two SMP's with 4 nodes each,
883// the process will have a node number from 0 ... 7, and an SMP node
884// number from 0 ... 3
886 // Inform dbgmsg("IpplInfo::find_smp_nodes", INFORM_ALL_NODES);
887
888 // create a tag for use in sending info to/from other nodes
889 int tag = Comm->next_tag(IPPL_MAKE_HOST_MAP_TAG, IPPL_TAG_CYCLE);
890
891 // create arrays to store the Node -> SMP mapping, and the relative
892 // SMP node number
893 if (SMPIDList != 0)
894 delete [] SMPIDList;
895 if (SMPNodeList != 0)
896 delete [] SMPNodeList;
897 SMPIDList = new int[TotalNodes];
898 SMPNodeList = new int[TotalNodes];
899
900 // obtain the hostname and processor ID to send out
901 char name[1024];
902 if (gethostname(name, 1023) != 0) {
903 ERRORMSG("Could not get hostname ... using localhost." << endl);
904 strcpy(name, "localhost");
905 }
906 std::string NodeName(name,strlen(name));
907 // dbgmsg << "My hostname is " << NodeName << endl;
908
909 // all other nodes send their hostname to node 0; node 0 gets the names,
910 // maps pnode ID's -> SMP ID's, then broadcasts all the necessary info to
911 // all other nodes
912 if (MyNode != 0) {
913 // other nodes send their node name to node 0
914 Message *msg = new Message;
915 ::putMessage(*msg,NodeName);
916 // dbgmsg << "Sending my name to node 0." << endl;
917 Comm->send(msg, 0, tag);
918
919 // receive back the SMPIDList mapping
920 int node = 0;
921 msg = Comm->receive_block(node, tag);
922 PInsist(msg != 0 && node == 0,
923 "SPMDList map not received from master in IpplInfo::find_smp_nodes!!");
926 delete msg;
927 }
928 else {
929 // collect node names from everyone else, and then retransmit the collected
930 // list.
931 SMPIDList[0] = 0;
934 smpMap.insert(vmap<std::string,int>::value_type(NodeName, 0));
935 unsigned int unreceived = TotalNodes - 1;
936 while (unreceived-- > 0) {
937 // get the hostname from the remote node
938 int node = COMM_ANY_NODE;
939 Message *msg = Comm->receive_block(node, tag);
940 PInsist(msg != 0,
941 "Hostname not received by master in IpplInfo::find_smp_nodes!!");
942 std::string nodename;
943 ::getMessage(*msg,nodename);
944 delete msg;
945 // dbgmsg <<"Received name '"<< nodename <<"' from node "<< node<<endl;
946
947 // put it in the mapping from hostname -> SMP ID, if necessary
948 smpiter = smpMap.find(nodename);
949 if (smpiter == smpMap.end())
950 smpMap.insert(vmap<std::string,int>::value_type(nodename,smpMap.size()));
951
952 // from the hostname, get the SMP ID number and store it in SMPIDList
953 SMPIDList[node] = smpMap[nodename];
954 }
955
956 // convert from SMPID mapping -> relative node number
957 for (int smpindx = 0; (unsigned int) smpindx < smpMap.size(); ++smpindx) {
958 int smpnodes = 0;
959 for (int n=0; n < TotalNodes; ++n) {
960 if (SMPIDList[n] == smpindx)
961 SMPNodeList[n] = smpnodes++;
962 }
963 }
964
965 // broadcast SMP info to other nodes
966 if (TotalNodes > 1) {
967 Message *msg = new Message;
970 Comm->broadcast_others(msg, tag);
971 }
972 }
973
974 // compute number of SMP's ... necessary for all but node 0, but we'll do
975 // it for all
976 NumSMPs = 0;
977 for (int ns=0; ns < TotalNodes; ++ns)
978 if (SMPNodeList[ns] == 0)
979 NumSMPs++;
980
981 // dbgmsg << "Results of SMP mapping: NumSMPs = " << NumSMPs << endl;
982 // for (unsigned int n=0; n < TotalNodes; ++n) {
983 // dbgmsg << " n=" << n << ", SMPID=" << SMPIDList[n] << ", SMPNode=";
984 // dbgmsg << SMPNodeList[n] << endl;
985 // }
986}
987
990
991 StaticIpplInfo obj;
992
993 obj.Comm = Comm;
994 obj.Stats = Stats;
995 obj.Info = Info;
996 obj.Warn = Warn;
997 obj.Error = Error;
998 obj.Debug = Debug;
1004 obj.NumCreated = NumCreated;
1006 obj.PrintStats = PrintStats;
1009 obj.Retransmit = Retransmit;
1010 obj.MyArgc = MyArgc;
1011 obj.MyArgv = MyArgv;
1012 obj.MyNode = MyNode;
1013 obj.TotalNodes = TotalNodes;
1014 obj.NumSMPs = NumSMPs;
1015 obj.SMPIDList = SMPIDList;
1018 obj.ChunkSize = ChunkSize;
1020
1021 stashedStaticMembers.push(obj);
1022
1023 Comm = 0;
1024 Stats = 0;
1025 Info = 0;
1026 Warn = 0;
1027 Error = 0;
1028 Debug = 0;
1029
1030 deferGuardCellFills = false;
1031 noFieldCompression = false;
1032 offsetStorage = false;
1033 extraCompressChecks = false;
1034 communicator_m = MPI_COMM_WORLD;
1035 NumCreated = 0;
1036 CommInitialized = false;
1037 PrintStats = false;
1038 NeedDeleteComm = false;
1039 UseChecksums = false;
1040 Retransmit = false;
1041 MyArgc = 0;
1042 MyArgv = 0;
1043 MyNode = 0;
1044 TotalNodes = 1;
1045 NumSMPs = 1;
1046 SMPIDList = 0;
1047 SMPNodeList = 0;
1048 MaxFFTNodes = 0;
1049 ChunkSize = 512*1024; // 512K == 64K doubles
1050 PerSMPParallelIO = false;
1051}
1052
1055
1058 // Delete the communications object, if necessary, to shut down parallel
1059 // environment
1060 // Comm is deleted in destructor
1061 delete [] MyArgv;
1062 delete [] SMPIDList;
1063 delete [] SMPNodeList;
1064 delete Info;
1065 delete Warn;
1066 delete Error;
1067 delete Debug;
1068 delete Stats;
1069
1070 Comm = obj.Comm;
1071 Stats = obj.Stats;
1072 Info = obj.Info;
1073 Warn = obj.Warn;
1074 Error = obj.Error;
1075 Debug = obj.Debug;
1081 NumCreated = obj.NumCreated;
1083 PrintStats = obj.PrintStats;
1086 Retransmit = obj.Retransmit;
1087 MyArgc = obj.MyArgc;
1088 MyArgv = obj.MyArgv;
1089 MyNode = obj.MyNode;
1090 TotalNodes = obj.TotalNodes;
1091 NumSMPs = obj.NumSMPs;
1092 SMPIDList = obj.SMPIDList;
1095 ChunkSize = obj.ChunkSize;
1097}
void putMessage(Message &m, const T &t)
Definition: Message.h:549
void getMessage_iter(Message &m, OutputIterator o)
Definition: Message.h:595
void getMessage(Message &m, T &t)
Definition: Message.h:572
const int COMM_ANY_NODE
Definition: Communicate.h:40
#define IPPL_TAG_CYCLE
Definition: Tags.h:90
#define IPPL_MAKE_HOST_MAP_TAG
Definition: Tags.h:89
#define IPPL_ABORT_TAG
Definition: Tags.h:25
const char * ippl_compile_date
Definition: IpplVersions.h:10
const char * ippl_compile_user
Definition: IpplVersions.h:13
const char * ippl_compile_line
Definition: IpplVersions.h:9
const char * ippl_compile_options
Definition: IpplVersions.h:12
const char * ippl_version_name
Definition: IpplVersions.h:7
const char * ippl_compile_machine
Definition: IpplVersions.h:11
const char * ippl_compile_arch
Definition: IpplVersions.h:8
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
std::ostream & operator<<(std::ostream &o, const IpplInfo &)
Definition: IpplInfo.cpp:118
RandomNumberGen IpplRandom
#define INFORM_ALL_NODES
Definition: Inform.h:39
#define PInsist(c, m)
Definition: PAssert.h:120
#define PAssert_EQ(a, b)
Definition: PAssert.h:104
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
#define INFOMSG(msg)
Definition: IpplInfo.h:348
const std::string name
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
Definition: types.h:26
static void setDefaultNodes(int)
static bool supported(int)
static const char * getAllMethodNames()
static bool setDefaultMethod(int)
static bool known(int)
static const char * getAllLibraryNames()
Definition: CommCreator.cpp:53
static bool supported(int)
Definition: CommCreator.cpp:61
static Communicate * create(int, int &, char **&, int=(-1), bool=true, MPI_Comm mpicomm=MPI_COMM_WORLD)
Definition: CommCreator.cpp:95
static bool known(const char *nm)
Definition: CommCreator.h:69
virtual const char * name() const
Definition: Communicate.h:137
Definition: Inform.h:42
Inform & setOutputLevel(const int)
Definition: Inform.cpp:228
static bool NeedDeleteComm
Definition: IpplInfo.h:298
static void deleteGlobals()
Definition: IpplInfo.cpp:68
static bool noFieldCompression
Definition: IpplInfo.h:262
static int NumCreated
Definition: IpplInfo.h:287
static void printStatistics(Inform &)
Definition: IpplInfo.cpp:789
static void instantiateGlobals()
Definition: IpplInfo.cpp:53
static bool extraCompressChecks
Definition: IpplInfo.h:270
static void printVersion(void)
Definition: IpplInfo.cpp:736
static IpplStats * Stats
Definition: IpplInfo.h:87
static int * SMPIDList
Definition: IpplInfo.h:318
static MPI_Comm communicator_m
Definition: IpplInfo.h:283
static bool offsetStorage
Definition: IpplInfo.h:266
static Inform * Warn
Definition: IpplInfo.h:79
static bool perSMPParallelIO()
Definition: IpplInfo.h:211
static int chunkSize()
Definition: IpplInfo.h:206
static int TotalNodes
Definition: IpplInfo.h:313
static void printHelp()
Definition: IpplInfo.cpp:744
static void pop()
Definition: IpplInfo.cpp:1053
static int NumSMPs
Definition: IpplInfo.h:317
static const char * compileMachine()
Definition: IpplInfo.cpp:828
static int * SMPNodeList
Definition: IpplInfo.h:319
static int MyArgc
Definition: IpplInfo.h:307
static void stash()
Definition: IpplInfo.cpp:988
static int MyNode
Definition: IpplInfo.h:312
static Inform * Info
Definition: IpplInfo.h:78
static char ** MyArgv
Definition: IpplInfo.h:308
static bool Retransmit
Definition: IpplInfo.h:304
static Inform * Error
Definition: IpplInfo.h:80
static bool PerSMPParallelIO
Definition: IpplInfo.h:331
static void param_error(const char *, const char *, const char *)
Definition: IpplInfo.cpp:853
static void abort(const char *=0)
Definition: IpplInfo.cpp:616
static int getProcesses(int, int)
Definition: IpplInfo.cpp:684
static int getContexts(int)
Definition: IpplInfo.cpp:677
static int getSMPNodes(int)
Definition: IpplInfo.cpp:706
static const char * compileLine()
Definition: IpplInfo.cpp:820
static const char * compileArch()
Definition: IpplInfo.cpp:804
static bool retransmit()
Definition: IpplInfo.h:195
static void find_smp_nodes()
Definition: IpplInfo.cpp:885
static bool useChecksums()
Definition: IpplInfo.h:192
static int MaxFFTNodes
Definition: IpplInfo.h:323
static bool CommInitialized
Definition: IpplInfo.h:291
static int getSMPs()
Definition: IpplInfo.cpp:699
static const char * version()
Definition: IpplInfo.cpp:795
static void here()
Definition: IpplInfo.cpp:783
static void abortAllNodes(const char *=0)
Definition: IpplInfo.cpp:647
static int getNodes()
Definition: IpplInfo.cpp:670
static bool PrintStats
Definition: IpplInfo.h:295
static int mySMPNode()
Definition: IpplInfo.cpp:728
@ KEEP
Definition: IpplInfo.h:74
static std::stack< StaticIpplInfo > stashedStaticMembers
Definition: IpplInfo.h:333
static const char * compileUser()
Definition: IpplInfo.cpp:844
static bool deferGuardCellFills
Definition: IpplInfo.h:259
static bool UseChecksums
Definition: IpplInfo.h:301
static Inform * Debug
Definition: IpplInfo.h:81
static int myNode()
Definition: IpplInfo.cpp:691
static Communicate * Comm
Definition: IpplInfo.h:84
static int mySMP()
Definition: IpplInfo.cpp:721
static const char * compileDate()
Definition: IpplInfo.cpp:812
IpplInfo & operator=(const IpplInfo &)
Definition: IpplInfo.cpp:611
static const char * compileOptions()
Definition: IpplInfo.cpp:836
static int ChunkSize
Definition: IpplInfo.h:326
void print(Inform &)
Definition: IpplStats.cpp:105
Timer & getTime()
Definition: IpplStats.h:82
void AdvanceSeed(int adv=0)
Definition: RNGXDiv.h:147
Communicate * Comm
bool extraCompressChecks
bool deferGuardCellFills
MPI_Comm communicator_m
IpplStats * Stats
void start()
Definition: Timer.cpp:34
void stop()
Definition: Timer.cpp:39
void clear()
Definition: Timer.cpp:29
double clock_time()
Definition: Timer.cpp:50
double cpu_time()
Definition: Timer.cpp:65
Definition: vmap.h:59
rep_type::iterator iterator
Definition: vmap.h:98
size_type size() const
Definition: vmap.h:120
iterator end()
Definition: vmap.h:108
iterator find(const key_type &x)
Definition: vmap.hpp:214
std::pair< Key, T > value_type
Definition: vmap.h:64
std::pair< iterator, bool > insert(const value_type &x)
Definition: vmap.hpp:73