Zoltan2
Zoltan2_AlltoAll.cpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Zoltan2: A package of combinatorial algorithms for scientific computing
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Karen Devine (kddevin@sandia.gov)
39 // Erik Boman (egboman@sandia.gov)
40 // Siva Rajamanickam (srajama@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
45 
51 #include <Zoltan2_AlltoAll.hpp>
52 #include <Zoltan2_Standards.hpp>
53 #include <Zoltan2_Environment.hpp>
54 
55 #include <vector>
56 #include <climits>
57 
58 namespace Zoltan2
59 {
60 
73  const Comm<int> &comm, // Communicator to use for AlltoAll
74  const Environment &env, // Needed only for error handling
75  const ArrayView<const int> &sendCount, // Input: # of data items to
76  // send to each process
77  const ArrayView<int> &recvCount // Output: # of data itmes to
78  // receive from each process
79 )
80 {
81  int nprocs = comm.getSize();
82  int rank = comm.getRank();
83 
84  recvCount[rank] = sendCount[rank];
85 
86  if (nprocs > 1) {
87 
88  // Post receives
89  RCP<CommRequest<int> > *requests = new RCP<CommRequest<int> > [nprocs];
90  for (int cnt = 0, i = 0; i < nprocs; i++) {
91  if (i != rank) {
92  try {
93  requests[cnt++] = Teuchos::ireceive<int,int>(comm,
94  rcp(&(recvCount[i]),false),
95  i);
96  }
98  }
99  }
100 
101  Teuchos::barrier<int>(comm);
102 
103  // Send data; can use readySend since receives are posted.
104  for (int i = 0; i < nprocs; i++) {
105  if (i != rank) {
106  try {
107  Teuchos::readySend<int,int>(comm, sendCount[i], i);
108  }
110  }
111  }
112 
113  // Wait for messages to return.
114  try {
115  Teuchos::waitAll<int>(comm, arrayView(requests, nprocs-1));
116  }
118 
119  delete [] requests;
120  }
121 }
122 
123 /* \brief Specialization for std::string.
124 
125  For string of char. Number of chars in a string limited to SCHAR_MAX.
126  Send as chars: 1 char for length of string, then chars in string,
127  1 char for length of next string, and so on.
128  \todo error checking
129  */
130 template <>
131 void AlltoAllv(const Comm<int> &comm,
132  const Environment &env,
133  const ArrayView<const std::string> &sendBuf,
134  const ArrayView<const int> &sendCount,
135  ArrayRCP<std::string> &recvBuf,
136  const ArrayView<int> &recvCount
137 )
138 {
139  int nprocs = comm.getSize();
140  int *newCount = new int [nprocs];
141  memset(newCount, 0, sizeof(int) * nprocs);
142  ArrayView<const int> newSendCount(newCount, nprocs);
143 
144  size_t numStrings = sendBuf.size();
145  size_t numChars = 0;
146  bool fail=false;
147 
148  for (int p=0, i=0; !fail && p < nprocs; p++){
149  for (int c=0; !fail && c < sendCount[p]; c++, i++){
150  size_t nchars = sendBuf[i].size();
151  if (nchars > SCHAR_MAX)
152  fail = true;
153  else
154  newCount[p] += nchars;
155  }
156  newCount[p] += sendCount[p];
157  numChars += newCount[p];
158  }
159 
160  if (fail)
161  throw std::runtime_error("id string length exceeds SCHAR_MAX");
162 
163  char *sbuf = NULL;
164  if (numChars > 0)
165  sbuf = new char [numChars];
166  char *sbufptr = sbuf;
167 
168  ArrayView<const char> newSendBuf(sbuf, numChars);
169 
170  for (size_t i=0; i < numStrings; i++){
171  size_t nchars = sendBuf[i].size();
172  *sbufptr++ = static_cast<char>(nchars);
173  for (size_t j=0; j < nchars; j++)
174  *sbufptr++ = sendBuf[i][j];
175  }
176 
177  ArrayRCP<char> newRecvBuf;
178  Array<int> newRecvCount(nprocs, 0);
179 
180  AlltoAllv<char>(comm, env, newSendBuf, newSendCount,
181  newRecvBuf, newRecvCount());
182 
183  delete [] sbuf;
184  delete [] newCount;
185 
186  char *inBuf = newRecvBuf.getRawPtr();
187 
188  int numNewStrings = 0;
189  char *buf = inBuf;
190  char *endChar = inBuf + newRecvBuf.size();
191  while (buf < endChar){
192  int slen = static_cast<int>(*buf++);
193  buf += slen;
194  numNewStrings++;
195  }
196 
197  // Data to return
198  std::string *newStrings = new std::string [numNewStrings];
199 
200  buf = inBuf;
201  int next = 0;
202 
203  for (int p=0; p < nprocs; p++){
204  int nchars = newRecvCount[p];
205  endChar = buf + nchars;
206  while (buf < endChar){
207  int slen = *buf++;
208  std::string nextString;
209  for (int i=0; i < slen; i++)
210  nextString.push_back(*buf++);
211  newStrings[next++] = nextString;
212  recvCount[p]++;
213  }
214  }
215 
216  recvBuf = arcp<std::string>(newStrings, 0, numNewStrings, true);
217 }
218 
219 
220 
221 /* \brief Specialization for unsigned long long
222  */
223 #ifdef HAVE_TPETRA_INT_LONG_LONG
224 template <>
225 void AlltoAllv(const Comm<int> &comm,
226  const Environment &env,
227  const ArrayView<const unsigned long long> &sendBuf,
228  const ArrayView<const int> &sendCount,
229  ArrayRCP<unsigned long long> &recvBuf, // output, allocated here
230  const ArrayView<int> &recvCount // output
231 )
232 {
233  const long long *sbuf =
234  reinterpret_cast<const long long *>(sendBuf.getRawPtr());
235  ArrayView<const long long> newSendBuf(sbuf, sendBuf.size());
236  ArrayRCP<long long> newRecvBuf;
237 
238  AlltoAllv<long long>(comm, env, newSendBuf, sendCount,
239  newRecvBuf, recvCount);
240 
241  recvBuf = arcp_reinterpret_cast<unsigned long long>(newRecvBuf);
242 }
243 #endif
244 
245 
246 /* \brief Specialization for unsigned short
247  */
248 template <>
249 void AlltoAllv(const Comm<int> &comm,
250  const Environment &env,
251  const ArrayView<const unsigned short> &sendBuf,
252  const ArrayView<const int> &sendCount,
253  ArrayRCP<unsigned short> &recvBuf, // output, allocated here
254  const ArrayView<int> &recvCount // output
255 )
256 {
257  const short *sbuf = reinterpret_cast<const short *>(sendBuf.getRawPtr());
258  ArrayView<const short> newSendBuf(sbuf, sendBuf.size());
259  ArrayRCP<short> newRecvBuf;
260 
261  AlltoAllv<short>(comm, env, newSendBuf, sendCount,
262  newRecvBuf, recvCount);
263 
264  recvBuf = arcp_reinterpret_cast<unsigned short>(newRecvBuf);
265 }
266 
267 
268 /* \brief For data type unsigned char (no Teuchos::DirectSerializationTraits)
269  */
270 template <>
271 void AlltoAllv(const Comm<int> &comm,
272  const Environment &env,
273  const ArrayView<const unsigned char> &sendBuf,
274  const ArrayView<const int> &sendCount,
275  ArrayRCP<unsigned char> &recvBuf, // output, allocated here
276  const ArrayView<int> &recvCount // output
277 )
278 {
279  const char *sbuf = reinterpret_cast<const char *>(sendBuf.getRawPtr());
280  ArrayView<const char> newSendBuf(sbuf, sendBuf.size());
281  ArrayRCP<char> newRecvBuf;
282 
283  AlltoAllv<char>(comm, env, newSendBuf, sendCount,
284  newRecvBuf, recvCount);
285 
286  recvBuf = arcp_reinterpret_cast<unsigned char>(newRecvBuf);
287 }
288 
289 } // namespace Z2
AlltoAll communication methods.
Defines the Environment class.
#define Z2_THROW_OUTSIDE_ERROR(env)
Throw an error returned from outside the Zoltan2 library.
Gathering definitions used in software development.
The user parameters, debug, timing and memory profiling output objects, and error checking methods.
Created by mbenlioglu on Aug 31, 2020.
static const std::string fail
void AlltoAllCount(const Comm< int > &comm, const Environment &env, const ArrayView< const int > &sendCount, const ArrayView< int > &recvCount)
Each process sends a value to every process, an all-to-all.
void AlltoAllv(const Comm< int > &comm, const Environment &env, const ArrayView< const std::string > &sendBuf, const ArrayView< const int > &sendCount, ArrayRCP< std::string > &recvBuf, const ArrayView< int > &recvCount)