Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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
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)
The user parameters, debug, timing and memory profiling output objects, and error checking methods...
static const std::string fail
Gathering definitions used in software development.
Defines the Environment class.
#define Z2_THROW_OUTSIDE_ERROR(env)
Throw an error returned from outside the Zoltan2 library.
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.
AlltoAll communication methods.