CEPS  24.01
Cardiac ElectroPhysiology Simulator
CepsContainerCommunication.cpp
Go to the documentation of this file.
1 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2  This file is part of CEPS.
3 
4  CEPS is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  CEPS is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with CEPS (see file LICENSE at root of project).
16  If not, see <https://www.gnu.org/licenses/>.
17 
18 
19  Copyright 2019-2024 Inria, Universite de Bordeaux
20 
21  Authors, in alphabetical order:
22 
23  Pierre-Elliott BECUE, Florian CARO, Yves COUDIERE(*), Andjela DAVIDOVIC,
24  Charlie DOUANLA-LONTSI, Marc FUENTES, Mehdi JUHOOR, Michael LEGUEBE(*),
25  Pauline MIGERDITICHAN, Valentin PANNETIER(*), Nejib ZEMZEMI.
26  * : currently active authors
27 
28 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
33 
34 int
36  const std::unordered_map<CepsUInt,CepsUInt>& orig,
37  std::unordered_map<CepsUInt,CepsUInt>& dest
38 )
39 {
40  auto gridSize = ceps::getGridSize();
41 
42  CepsVector<int> localSizes(gridSize ,0);
43  CepsVector<int> displs (gridSize+1,0);
44 
45  CepsVector<CepsUInt> keysOrig;
46  CepsVector<CepsUInt> valuesOrig;
47 
48  keysOrig .reserve(orig.size());
49  valuesOrig.reserve(orig.size());
50  for (auto &[key, value] : orig)
51  {
52  keysOrig .push_back(key);
53  valuesOrig.push_back(value);
54  }
55 
56  int origSize = (int)orig.size();
57  int res = MPI_Allgather(&origSize,1,MPI_INT,localSizes.data(),1,MPI_INT,ceps::getCommunicator());
58  if (res != 0)
59  return res;
60 
61  for (CepsUInt i = 1U; i < gridSize + 1; i++)
62  displs[i] = displs[i-1] + localSizes[i-1];
63 
64  CepsVector<CepsUInt> keysDest;
65  CepsVector<CepsUInt> valuesDest;
66 
67  keysDest .resize(displs[gridSize]);
68  valuesDest.resize(displs[gridSize]);
69 
70  int res1 = MPI_Allgatherv(keysOrig.data(),orig.size(),CEPS_MPI_UINT,
71  keysDest.data(),localSizes.data(),displs.data(),
73  if (res1 != 0)
74  return res1;
75 
76  int res2 = MPI_Allgatherv(valuesOrig.data(),orig.size(),CEPS_MPI_UINT,
77  valuesDest.data(),localSizes.data(),displs.data(),
79 
80  if (res2 != 0)
81  return res2;
82 
83  for (CepsUInt i=0U; i<keysDest.size(); ++i)
84  dest[keysDest[i]] = valuesDest[i];
85 
86  return MPI_SUCCESS;
87 }
88 
89 // Specialization for CepsHash3
90 template <>
91 void ceps::
92 sendRecvWithMatrix(const Eigen::Matrix<CepsUInt, Eigen::Dynamic, Eigen::Dynamic> &commMat,
93  CepsVector<CepsVector<CepsHash3>> &sendBuffers,
94  CepsVector<CepsVector<CepsHash3>> &recvBuffers)
95 {
96  auto gridSize = ceps::getGridSize ();
97  auto comm = ceps::getCommunicator();
98  auto rank = ceps::getRank ();
99 
100  CepsBool badShape = (CepsUInt)commMat.rows() > gridSize or (CepsUInt)commMat.cols() > gridSize;
101  CEPS_ABORT_IF(badShape,
102  "given comm Matrix has wrong shape " << commMat.rows() << " " << commMat.cols()
103  );
104 
105  std::map<CepsUInt, CepsUInt> connectivity;
108 
109  CepsUInt ns = sendBuffers.size();
110  for (CepsUInt i=0; i<3; i++)
111  {
112  sBuffers[i].resize(ns);
113  for (CepsUInt j=0; j<ns; j++)
114  sBuffers[i][j].resize(sendBuffers[j].size());
115  }
116  for (CepsUInt j=0; j<ns; j++)
117  for (CepsUInt k=0;k<sendBuffers[j].size();k++)
118  {
119  sBuffers[0][j][k] = sendBuffers[j][k].h1;
120  sBuffers[1][j][k] = sendBuffers[j][k].h2;
121  sBuffers[2][j][k] = sendBuffers[j][k].h3;
122  }
123 
124  for (CepsUInt dim=0; dim<3; dim++)
125  {
126 
127  rBuffers[dim].resize(gridSize);
128 
129  MPI_Status status;
130  MPI_Request request;
131  // Try with slow blocking communications
132  for (CepsUInt sndr=0u; sndr<gridSize; sndr++)
133  for (CepsUInt rcvr=0u; rcvr<gridSize; rcvr++)
134  {
135  CepsInt tag = dim+3*(sndr*gridSize+rcvr);
136  CepsInt dataSize = commMat(sndr,rcvr);
137  if (rank==sndr)
138  MPI_Isend(sBuffers[dim][rcvr].data(),dataSize,CEPS_MPI_SHASH,rcvr,tag,comm,&request);
139  if (rank==rcvr)
140  {
141  rBuffers[dim][sndr].resize(dataSize);
142  MPI_Recv(rBuffers[dim][sndr].data(),dataSize,CEPS_MPI_SHASH,sndr,tag,comm,&status);
143  }
144 
145  }
146 
147 // connectivity.clear();
148 // for (CepsUInt i=0U; i<gridSize; ++i)
149 // connectivity[i] = commMat(rank,i);
150 
151 // CepsUInt i = 0;
152 // MPI_Request* sendRequests = new MPI_Request[connectivity.size()];
153 
154 // for (auto &[destination,dataSize] : connectivity)
155 // {
156 // MPI_Isend(sBuffers[dim][destination].data(),dataSize,CEPS_MPI_SHASH,
157 // destination,dim+3*(rank*gridSize+destination),comm,&sendRequests[i++]);
158 // }
159 
160 // // do all the receives (blocking)
161 // connectivity.clear();
162 // for (CepsUInt j=0U; j<gridSize; ++j)
163 // connectivity[j] = commMat(j,rank);
164 
165 // i = 0;
166 // MPI_Status* receiveStatus = new MPI_Status[connectivity.size()];
167 
168 // rBuffers[dim].resize(gridSize);
169 // for (auto &[sender,dataSize] : connectivity)
170 // {
171 // rBuffers[dim][sender].resize(dataSize);
172 // MPI_Recv(rBuffers[dim][sender].data(),dataSize,CEPS_MPI_SHASH,
173 // sender,dim+3*(sender*gridSize+rank),comm,&receiveStatus[i++]);
174 // }
175 
176  // ceps::destroyTabular(receiveRequests);
177  // ceps::destroyTabular(receiveStatus);
178  // ceps::destroyTabular(sendRequests);
179  }
180 
181  CepsUInt rs = rBuffers[0].size();
182  recvBuffers.resize(rs);
183  for (CepsUInt j=0; j<rs; j++)
184  {
185  CepsUInt rss = rBuffers[0][j].size();
186  recvBuffers[j].resize(rss);
187  for (CepsUInt k=0;k<rss;k++)
188  {
189  recvBuffers[j][k].h1 = rBuffers[0][j][k];
190  recvBuffers[j][k].h2 = rBuffers[1][j][k];
191  recvBuffers[j][k].h3 = rBuffers[2][j][k];
192  }
193  }
194 
195 
196  return;
197 }
#define CEPS_ABORT_IF(condition, message)
Stops the execution with a message if condition is true. If testing is enabled, only throws a runtime...
std::vector< _Type, _Alloc > CepsVector
C++ vector.
Definition: CepsTypes.hpp:155
#define CEPS_MPI_SHASH
Definition: CepsTypes.hpp:365
bool CepsBool
Booleans.
Definition: CepsTypes.hpp:124
std::make_unsigned_t< CepsInt > CepsUInt
Unsigned version on CepsInt.
Definition: CepsTypes.hpp:109
CepsArray< _Type, 3U > CepsArray3
C++ array, 3 elements.
Definition: CepsTypes.hpp:165
int32_t CepsInt
Need 32 bit integer.
Definition: CepsTypes.hpp:106
#define CEPS_MPI_UINT
Definition: CepsTypes.hpp:325
CepsUInt getRank()
Returns current processor rank.
void sendRecvWithMatrix(const Eigen::Matrix< CepsUInt, Eigen::Dynamic, Eigen::Dynamic > &commMat, CepsVector< CepsVector< T >> &sendBuffers, CepsVector< CepsVector< T >> &recvBuffers)
Pair to pair communication (using matrix)
MPI_Comm getCommunicator()
Get the communicator.
CepsUInt getGridSize()
Returns the number of process on the computing grid.
int allGatherv(const CepsVector< T > &localTab, int localSize, CepsVector< T > &globalTab, CepsBool masterOnly=false)
Gather all the local orig vector in the global dest vector.