OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
MPIHelper.cpp
Go to the documentation of this file.
1 //
2 // Global functions MPIHelper
3 //
4 // Copyright (c) 2010 - 2013, Yves Ineichen, ETH Zürich
5 // All rights reserved
6 //
7 // Implemented as part of the PhD thesis
8 // "Toward massively parallel multi-objective optimization with application to
9 // particle accelerators" (https://doi.org/10.3929/ethz-a-009792359)
10 //
11 // This file is part of OPAL.
12 //
13 // OPAL is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
20 //
21 #include <string.h>
22 
23 #include <boost/static_assert.hpp>
24 #include <boost/serialization/map.hpp>
25 #include <boost/serialization/vector.hpp>
26 
27 #include <boost/archive/text_oarchive.hpp>
28 #include <boost/archive/text_iarchive.hpp>
29 
30 #include "Util/MPIHelper.h"
31 
32 void serialize(Param_t params, std::ostringstream &os) {
33 
34  boost::archive::text_oarchive oa(os);
35  oa << params;
36 }
37 
38 void serialize(reqVarContainer_t reqvars, std::ostringstream &os) {
39 
40  boost::archive::text_oarchive oa(os);
41  oa << reqvars;
42 }
43 
44 void deserialize(char *buffer, Param_t &params) {
45 
46  params.clear();
47  std::istringstream is(buffer);
48  boost::archive::text_iarchive ia(is);
49  ia >> params;
50 }
51 
52 void deserialize(char *buffer, reqVarContainer_t &reqvars) {
53 
54  reqvars.clear();
55  std::istringstream is(buffer);
56  boost::archive::text_iarchive ia(is);
57  ia >> reqvars;
58 }
59 
60 void MPI_Bcast_params(Param_t &params, size_t root, MPI_Comm comm) {
61 
62  int pid = 0;
63  size_t my_pid = 0;
64  MPI_Comm_rank(comm, &pid);
65  my_pid = static_cast<size_t>(pid);
66 
67  size_t buf_size = 0;
68  std::ostringstream os;
69 
70  if(my_pid == root) {
71  serialize(params, os);
72  buf_size = os.str().length() + 1; // +1 for null-termination
73  }
74 
75  MPI_Bcast(&buf_size, 1, MPI_UNSIGNED_LONG, root, comm);
76 
77  char *buffer = new char[buf_size];
78  if(my_pid == root) memcpy(buffer, os.str().c_str(), buf_size);
79 
80  MPI_Bcast(buffer, buf_size, MPI_CHAR, root, comm);
81  if(my_pid != root) deserialize(buffer, params);
82 
83  delete[] buffer;
84 }
85 
86 
87 void MPI_Send_params(Param_t params, size_t pid, MPI_Comm comm) {
88 
89  std::ostringstream os;
90  serialize(params, os);
91  size_t buf_size = os.str().length() + 1; // +1 for null-termination
92 
93  MPI_Send(&buf_size, 1, MPI_UNSIGNED_LONG, pid,
95 
96  char *buffer = new char[buf_size];
97  memcpy(buffer, os.str().c_str(), buf_size);
98 
99  MPI_Send(buffer, buf_size, MPI_CHAR, pid,
101 
102  delete[] buffer;
103 }
104 
105 std::pair<size_t*, char*> MPI_ISend_params(Param_t params, size_t pid,
106  MPI_Comm comm, MPI_Request *req) {
107 
108  std::ostringstream os;
109  serialize(params, os);
110  size_t* buf_size = new size_t();
111  *buf_size = os.str().length() + 1; // +1 for null-termination
112 
113  MPI_Isend(buf_size, 1, MPI_UNSIGNED_LONG, pid,
115 
116  char *buffer = new char[*buf_size];
117  memcpy(buffer, os.str().c_str(), *buf_size);
118 
119  MPI_Isend(buffer, *buf_size, MPI_CHAR, pid,
121 
122  std::pair<size_t*, char*> p(buf_size, buffer);
123 
124  return p;
125 }
126 
127 
128 void MPI_Recv_params(Param_t &params, size_t pid, MPI_Comm comm) {
129 
130  MPI_Status status;
131  size_t buf_size = 0;
132  MPI_Recv(&buf_size, 1, MPI_UNSIGNED_LONG, pid,
133  MPI_EXCHANGE_SERIALIZED_DATA_TAG, comm, &status);
134 
135  char *buffer = new char[buf_size]();
136 
137  MPI_Recv(buffer, buf_size, MPI_CHAR, pid,
138  MPI_EXCHANGE_SERIALIZED_DATA_TAG, comm, &status);
139 
140  deserialize(buffer, params);
141 
142  delete[] buffer;
143 }
144 
145 
146 void MPI_Send_reqvars(reqVarContainer_t reqvars, size_t pid, MPI_Comm comm) {
147 
148  std::ostringstream os;
149  serialize(reqvars, os);
150  size_t buf_size = os.str().length() + 1; // +1 for null-termination
151 
152  MPI_Send(&buf_size, 1, MPI_UNSIGNED_LONG, pid,
154 
155  char *buffer = new char[buf_size];
156  memcpy(buffer, os.str().c_str(), buf_size);
157 
158  MPI_Send(buffer, buf_size, MPI_CHAR, pid,
160 
161  delete[] buffer;
162 }
163 
164 
165 void MPI_Recv_reqvars(reqVarContainer_t &reqvars, size_t pid, MPI_Comm comm) {
166 
167  MPI_Status status;
168  size_t buf_size = 0;
169  MPI_Recv(&buf_size, 1, MPI_UNSIGNED_LONG, pid,
170  MPI_EXCHANGE_SERIALIZED_DATA_TAG, comm, &status);
171 
172  char *buffer = new char[buf_size]();
173 
174  MPI_Recv(buffer, buf_size, MPI_CHAR, pid,
175  MPI_EXCHANGE_SERIALIZED_DATA_TAG, comm, &status);
176 
177  deserialize(buffer, reqvars);
178 
179  delete[] buffer;
180 }
181 
void MPI_Send_reqvars(reqVarContainer_t reqvars, size_t pid, MPI_Comm comm)
Definition: MPIHelper.cpp:146
void MPI_Bcast_params(Param_t &params, size_t root, MPI_Comm comm)
broadcast params to all entities in comm
Definition: MPIHelper.cpp:60
void MPI_Send_params(Param_t params, size_t pid, MPI_Comm comm)
Definition: MPIHelper.cpp:87
void MPI_Recv_reqvars(reqVarContainer_t &reqvars, size_t pid, MPI_Comm comm)
Definition: MPIHelper.cpp:165
void serialize(Param_t params, std::ostringstream &os)
serializes params using Boost archive
Definition: MPIHelper.cpp:32
std::pair< size_t *, char * > MPI_ISend_params(Param_t params, size_t pid, MPI_Comm comm, MPI_Request *req)
Definition: MPIHelper.cpp:105
void deserialize(char *buffer, Param_t &params)
deserializes params using Boost archive
Definition: MPIHelper.cpp:44
void MPI_Recv_params(Param_t &params, size_t pid, MPI_Comm comm)
Definition: MPIHelper.cpp:128
#define MPI_EXCHANGE_SERIALIZED_DATA_TAG
tag for exchanging serialized data
Definition: MPIHelper.h:67
std::map< std::string, reqVarInfo_t > reqVarContainer_t
Definition: Types.h:79
namedVariableCollection_t Param_t
Definition: Types.h:48