OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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
32void serialize(Param_t params, std::ostringstream &os) {
33
34 boost::archive::text_oarchive oa(os);
35 oa << params;
36}
37
38void serialize(reqVarContainer_t reqvars, std::ostringstream &os) {
39
40 boost::archive::text_oarchive oa(os);
41 oa << reqvars;
42}
43
44void 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
52void 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
60void 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
87void 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
105std::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
128void 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
146void 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
165void 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
#define MPI_EXCHANGE_SERIALIZED_DATA_TAG
tag for exchanging serialized data
Definition: MPIHelper.h:67
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
std::map< std::string, reqVarInfo_t > reqVarContainer_t
Definition: Types.h:79
namedVariableCollection_t Param_t
Definition: Types.h:48