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 // Zoltan2: A package of combinatorial algorithms for scientific computing
4 //
5 // Copyright 2012 NTESS and the Zoltan2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
15 #include <Zoltan2_AlltoAll.hpp>
16 #include <Zoltan2_Standards.hpp>
17 #include <Zoltan2_Environment.hpp>
18 
19 #include <vector>
20 #include <climits>
21 
22 namespace Zoltan2
23 {
24 
37  const Comm<int> &comm, // Communicator to use for AlltoAll
38  const Environment &env, // Needed only for error handling
39  const ArrayView<const int> &sendCount, // Input: # of data items to
40  // send to each process
41  const ArrayView<int> &recvCount // Output: # of data itmes to
42  // receive from each process
43 )
44 {
45  int nprocs = comm.getSize();
46  int rank = comm.getRank();
47 
48  recvCount[rank] = sendCount[rank];
49 
50  if (nprocs > 1) {
51 
52  // Post receives
53  RCP<CommRequest<int> > *requests = new RCP<CommRequest<int> > [nprocs];
54  for (int cnt = 0, i = 0; i < nprocs; i++) {
55  if (i != rank) {
56  try {
57  requests[cnt++] = Teuchos::ireceive<int,int>(comm,
58  rcp(&(recvCount[i]),false),
59  i);
60  }
62  }
63  }
64 
65  Teuchos::barrier<int>(comm);
66 
67  // Send data; can use readySend since receives are posted.
68  for (int i = 0; i < nprocs; i++) {
69  if (i != rank) {
70  try {
71  Teuchos::readySend<int,int>(comm, sendCount[i], i);
72  }
74  }
75  }
76 
77  // Wait for messages to return.
78  try {
79  Teuchos::waitAll<int>(comm, arrayView(requests, nprocs-1));
80  }
82 
83  delete [] requests;
84  }
85 }
86 
87 /* \brief Specialization for std::string.
88 
89  For string of char. Number of chars in a string limited to SCHAR_MAX.
90  Send as chars: 1 char for length of string, then chars in string,
91  1 char for length of next string, and so on.
92  \todo error checking
93  */
94 template <>
95 void AlltoAllv(const Comm<int> &comm,
96  const Environment &env,
97  const ArrayView<const std::string> &sendBuf,
98  const ArrayView<const int> &sendCount,
99  ArrayRCP<std::string> &recvBuf,
100  const ArrayView<int> &recvCount
101 )
102 {
103  int nprocs = comm.getSize();
104  int *newCount = new int [nprocs];
105  memset(newCount, 0, sizeof(int) * nprocs);
106  ArrayView<const int> newSendCount(newCount, nprocs);
107 
108  size_t numStrings = sendBuf.size();
109  size_t numChars = 0;
110  bool fail=false;
111 
112  for (int p=0, i=0; !fail && p < nprocs; p++){
113  for (int c=0; !fail && c < sendCount[p]; c++, i++){
114  size_t nchars = sendBuf[i].size();
115  if (nchars > SCHAR_MAX)
116  fail = true;
117  else
118  newCount[p] += nchars;
119  }
120  newCount[p] += sendCount[p];
121  numChars += newCount[p];
122  }
123 
124  if (fail)
125  throw std::runtime_error("id string length exceeds SCHAR_MAX");
126 
127  char *sbuf = NULL;
128  if (numChars > 0)
129  sbuf = new char [numChars];
130  char *sbufptr = sbuf;
131 
132  ArrayView<const char> newSendBuf(sbuf, numChars);
133 
134  for (size_t i=0; i < numStrings; i++){
135  size_t nchars = sendBuf[i].size();
136  *sbufptr++ = static_cast<char>(nchars);
137  for (size_t j=0; j < nchars; j++)
138  *sbufptr++ = sendBuf[i][j];
139  }
140 
141  ArrayRCP<char> newRecvBuf;
142  Array<int> newRecvCount(nprocs, 0);
143 
144  AlltoAllv<char>(comm, env, newSendBuf, newSendCount,
145  newRecvBuf, newRecvCount());
146 
147  delete [] sbuf;
148  delete [] newCount;
149 
150  char *inBuf = newRecvBuf.getRawPtr();
151 
152  int numNewStrings = 0;
153  char *buf = inBuf;
154  char *endChar = inBuf + newRecvBuf.size();
155  while (buf < endChar){
156  int slen = static_cast<int>(*buf++);
157  buf += slen;
158  numNewStrings++;
159  }
160 
161  // Data to return
162  std::string *newStrings = new std::string [numNewStrings];
163 
164  buf = inBuf;
165  int next = 0;
166 
167  for (int p=0; p < nprocs; p++){
168  int nchars = newRecvCount[p];
169  endChar = buf + nchars;
170  while (buf < endChar){
171  int slen = *buf++;
172  std::string nextString;
173  for (int i=0; i < slen; i++)
174  nextString.push_back(*buf++);
175  newStrings[next++] = nextString;
176  recvCount[p]++;
177  }
178  }
179 
180  recvBuf = arcp<std::string>(newStrings, 0, numNewStrings, true);
181 }
182 
183 
184 
185 /* \brief Specialization for unsigned long long
186  */
187 #ifdef HAVE_TPETRA_INT_LONG_LONG
188 template <>
189 void AlltoAllv(const Comm<int> &comm,
190  const Environment &env,
191  const ArrayView<const unsigned long long> &sendBuf,
192  const ArrayView<const int> &sendCount,
193  ArrayRCP<unsigned long long> &recvBuf, // output, allocated here
194  const ArrayView<int> &recvCount // output
195 )
196 {
197  const long long *sbuf =
198  reinterpret_cast<const long long *>(sendBuf.getRawPtr());
199  ArrayView<const long long> newSendBuf(sbuf, sendBuf.size());
200  ArrayRCP<long long> newRecvBuf;
201 
202  AlltoAllv<long long>(comm, env, newSendBuf, sendCount,
203  newRecvBuf, recvCount);
204 
205  recvBuf = arcp_reinterpret_cast<unsigned long long>(newRecvBuf);
206 }
207 #endif
208 
209 
210 /* \brief Specialization for unsigned short
211  */
212 template <>
213 void AlltoAllv(const Comm<int> &comm,
214  const Environment &env,
215  const ArrayView<const unsigned short> &sendBuf,
216  const ArrayView<const int> &sendCount,
217  ArrayRCP<unsigned short> &recvBuf, // output, allocated here
218  const ArrayView<int> &recvCount // output
219 )
220 {
221  const short *sbuf = reinterpret_cast<const short *>(sendBuf.getRawPtr());
222  ArrayView<const short> newSendBuf(sbuf, sendBuf.size());
223  ArrayRCP<short> newRecvBuf;
224 
225  AlltoAllv<short>(comm, env, newSendBuf, sendCount,
226  newRecvBuf, recvCount);
227 
228  recvBuf = arcp_reinterpret_cast<unsigned short>(newRecvBuf);
229 }
230 
231 
232 /* \brief For data type unsigned char (no Teuchos::DirectSerializationTraits)
233  */
234 template <>
235 void AlltoAllv(const Comm<int> &comm,
236  const Environment &env,
237  const ArrayView<const unsigned char> &sendBuf,
238  const ArrayView<const int> &sendCount,
239  ArrayRCP<unsigned char> &recvBuf, // output, allocated here
240  const ArrayView<int> &recvCount // output
241 )
242 {
243  const char *sbuf = reinterpret_cast<const char *>(sendBuf.getRawPtr());
244  ArrayView<const char> newSendBuf(sbuf, sendBuf.size());
245  ArrayRCP<char> newRecvBuf;
246 
247  AlltoAllv<char>(comm, env, newSendBuf, sendCount,
248  newRecvBuf, recvCount);
249 
250  recvBuf = arcp_reinterpret_cast<unsigned char>(newRecvBuf);
251 }
252 
253 } // 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.