CMS 3D CMS Logo

MPIService.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 #include <cstdlib>
3 #include <string>
4 
5 #include <mpi.h>
6 
14 
15 namespace {
16 
17  // list the MPI thread support levels
18  const char* const mpi_thread_support_level[] = {
19  "MPI_THREAD_SINGLE", // only one thread will execute (the process is single-threaded)
20  "MPI_THREAD_FUNNELED", // only the thread that called MPI_Init_thread will make MPI calls
21  "MPI_THREAD_SERIALIZED", // only one thread will make MPI library calls at one time
22  "MPI_THREAD_MULTIPLE" // multiple threads may call MPI at once with no restrictions
23  };
24 
25 } // namespace
26 
28  /* As of Open MPI 4.1.0, `MPI_THREAD_MULTIPLE` is supported by the following transports:
29  * - the `ob1` PML, with the following BTLs:
30  * - `self`
31  * - `sm`
32  * - `smcuda`
33  * - `tcp`
34  * - `ugni`
35  * - `usnic`
36  * - the `cm` PML, with the following MTLs:
37  * - `ofi` (Libfabric)
38  * - `portals4`
39  * - the `ucx` PML
40  *
41  * MPI File operations are not thread safe even if MPI is initialized for `MPI_THREAD_MULTIPLE` support.
42  *
43  * See https://github.com/open-mpi/ompi/blob/v4.1.0/README .
44  */
45 
46  // set the pmix_server_uri MCA parameter if specified in the configuration and not already set in the environment
47  if (config.existsAs<std::string>("pmix_server_uri", false)) {
48  std::string uri = config.getUntrackedParameter<std::string>("pmix_server_uri");
49  // do not overwrite the environment variable if it is already set
50  setenv("OMPI_MCA_pmix_server_uri", uri.c_str(), false);
51  }
52 
53  // initializes the MPI execution environment, requesting multi-threading support
54  int provided;
55  MPI_Init_thread(nullptr, nullptr, MPI_THREAD_MULTIPLE, &provided);
56  if (provided < MPI_THREAD_MULTIPLE) {
57  throw cms::Exception("UnsupportedFeature")
58  << "CMSSW requires the " << mpi_thread_support_level[MPI_THREAD_MULTIPLE]
59  << " multithreading support level, but the MPI library provides only the " << mpi_thread_support_level[provided]
60  << " level.";
61  } else {
62  edm::LogInfo log("MPIService");
63  log << "The MPI library provides the " << mpi_thread_support_level[provided] << " multithreading support level\n";
64 
65  // get the number of processes
66  int world_size;
67  MPI_Comm_size(MPI_COMM_WORLD, &world_size);
68  log << "MPI_COMM_WORLD size: " << world_size << '\n';
69 
70  // get the rank of the process
71  int world_rank;
72  MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
73  log << "MPI_COMM_WORLD rank: " << world_rank << '\n';
74 
75  // get the name of the processor
76  char processor_name[MPI_MAX_PROCESSOR_NAME];
77  int name_len;
78  MPI_Get_processor_name(processor_name, &name_len);
79  log << "MPI processor name: " << processor_name << '\n';
80 
81  // initialisation done
82  log << '\n';
83  log << "MPI successfully initialised";
84  }
85 }
86 
88  // terminate the MPI execution environment
89  MPI_Finalize();
90 }
91 
94  desc.addOptionalUntracked<std::string>("pmix_server_uri")
95  ->setComment("Set the OpenMPI MCA pmix_server_uri parameter if not already set in the environment");
96  descriptions.add("MPIService", desc);
97  descriptions.setComment(R"(This Service provides a common interface to MPI configuration for the CMSSW job.)");
98 }
99 
102  if (not s.isAvailable()) {
103  throw cms::Exception("Configuration") << R"(The MPIService is required by this module.
104 Please add it to the configuration, for example via
105 
106 process.load("HeterogeneousCore.MPIServices.MPIService_cfi")
107 )";
108  }
109 }
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
Definition: MPIService.cc:92
Definition: config.py:1
void setComment(std::string const &value)
static void required()
Definition: MPIService.cc:100
MPIService(edm::ParameterSet const &config)
Definition: MPIService.cc:27
void add(std::string const &label, ParameterSetDescription const &psetDescription)