11 #include "Teuchos_CommHelpers.hpp"
12 #include "Teuchos_DefaultComm.hpp"
42 packStringsForSend (std::string& packedString,
43 Array<size_t>& offsets,
44 const Array<std::string>& strings)
50 const bool debug =
false;
53 offsets.resize (strings.size() + 1);
54 size_t totalLength = 0;
55 Array<size_t>::size_type offsetsIndex = 0;
56 for (Array<string>::const_iterator it = strings.begin();
57 it != strings.end(); ++it, ++offsetsIndex)
59 offsets[offsetsIndex] = totalLength;
60 totalLength += it->size();
62 offsets[offsetsIndex] = totalLength;
65 packedString.resize (totalLength);
66 string::iterator packedStringIter = packedString.begin();
67 for (Array<string>::const_iterator it = strings.begin();
68 it != strings.end(); ++it)
69 packedStringIter = std::copy (it->begin(), it->end(), packedStringIter);
73 std::ostringstream out;
75 out <<
"Proc " << pComm->getRank() <<
": in pack: offsets = [";
76 for (Array<size_t>::const_iterator it = offsets.begin();
77 it != offsets.end(); ++it)
80 if (it + 1 != offsets.end())
83 out <<
"], packedString = " << packedString << endl;
96 sendStrings (
const Comm<int>& comm,
97 const Array<std::string>& strings,
102 std::string packedString;
103 Array<size_t> offsets;
104 packStringsForSend (packedString, offsets, strings);
106 "packStringsForSend() returned a zero-length offsets "
107 "array on MPI Proc " << comm.getRank() <<
", to be "
108 "sent to Proc " << destRank <<
". The offsets array "
109 "should always have positive length. Please report "
110 "this bug to the Teuchos developers.");
113 send (comm, offsets.size(), destRank);
118 const int offsetsSendCount =
static_cast<int> (offsets.size());
119 send (comm, offsetsSendCount, &offsets[0], destRank);
126 const int stringSendCount =
static_cast<int> (packedString.size());
127 if (stringSendCount > 0)
128 send (comm, stringSendCount, &packedString[0], destRank);
132 unpackStringsAfterReceive (Array<std::string>& strings,
133 const std::string& packedString,
134 const Array<size_t> offsets)
136 const bool debug =
false;
142 std::ostringstream out;
144 out <<
"Proc " << pComm->getRank() <<
": in unpack: offsets = [";
145 for (Array<size_t>::const_iterator it = offsets.begin();
146 it != offsets.end(); ++it)
149 if (it + 1 != offsets.end())
152 out <<
"], packedString = " << packedString << endl;
156 "The offsets array has length zero, which does not "
157 "make sense. Even when sending / receiving zero "
158 "strings, the offsets array should have one entry "
160 const Array<size_t>::size_type numStrings = offsets.size() - 1;
161 strings.resize (numStrings);
162 for (Array<size_t>::size_type k = 0; k < numStrings; ++k)
165 const size_t start = offsets[k];
166 const size_t end = offsets[k+1];
167 strings[k] = packedString.substr (start, end - start);
174 receiveStrings (
const Comm<int>& comm,
175 const int sourceRank,
176 Array<std::string>& strings)
180 Array<size_t>::size_type numOffsets = 0;
181 receive (comm, sourceRank, &numOffsets);
183 "Invalid number of offsets numOffsets=" << numOffsets
184 <<
" received on MPI Rank " << comm.getRank()
185 <<
" from Rank " << sourceRank <<
". Please report "
186 "this bug to the Teuchos developers.");
189 Array<size_t> offsets (numOffsets);
190 const int offsetsRecvCount =
static_cast<int> (numOffsets);
191 receive (comm, sourceRank, offsetsRecvCount, &offsets[0]);
196 std::string packedString (offsets.back(),
' ');
197 const int stringRecvCount =
static_cast<int> (offsets.back());
198 if (stringRecvCount > 0)
200 receive (comm, sourceRank, stringRecvCount, &packedString[0]);
201 unpackStringsAfterReceive (strings, packedString, offsets);
207 broadcastStringsHelper (
const Comm<int>& comm,
211 Array<std::string>& globalNames)
223 const int mid = left + (right - left + 1) / 2;
229 sendStrings (comm, globalNames, mid);
230 else if (myRank == mid)
231 receiveStrings (comm, left, globalNames);
234 if (myRank >= left && myRank <= mid-1)
235 broadcastStringsHelper (comm, myRank, left, mid-1, globalNames);
236 else if (myRank >= mid && myRank <= right)
237 broadcastStringsHelper (comm, myRank, mid, right, globalNames);
245 broadcastStrings (
const Comm<int>& comm,
246 Array<std::string>& globalNames)
248 const int myRank = comm.getRank();
250 const int right = comm.getSize() - 1;
252 broadcastStringsHelper (comm, myRank, left, right, globalNames);
288 mergeCounterNamesPair (
const Comm<int>& comm,
292 Array<std::string>& globalNames,
299 const bool debug =
false;
304 Array<string> otherNames;
305 receiveStrings (comm, mid, otherNames);
312 std::ostringstream out;
313 out <<
"Proc " << myRank <<
": in mergePair: otherNames = [";
315 it != otherNames.end(); ++it)
317 out <<
"\"" << *it <<
"\"";
318 if (it + 1 != otherNames.end())
328 Array<string> newNames;
329 if ( std::is_sorted(globalNames.begin(), globalNames.end()) &&
330 std::is_sorted(otherNames.begin(), otherNames.end())) {
331 if (setOp == Intersection)
332 std::set_intersection (globalNames.begin(), globalNames.end(),
333 otherNames.begin(), otherNames.end(),
334 std::back_inserter (newNames));
335 else if (setOp == Union)
336 std::set_union (globalNames.begin(), globalNames.end(),
337 otherNames.begin(), otherNames.end(),
338 std::back_inserter (newNames));
342 "Invalid set operation enum value. Please "
343 "report this bug to the Teuchos developers.");
344 globalNames.swap (newNames);
349 else if (myRank == mid)
350 sendStrings (comm, globalNames, left);
354 "myRank=" << myRank <<
" is neither left=" << left
355 <<
" nor mid=" << mid <<
". Please report this "
356 "bug to the Teuchos developers.");
369 mergeCounterNamesHelper (
const Comm<int>& comm,
373 const Array<std::string>& localNames,
374 Array<std::string>& globalNames,
403 else if (left == right)
405 Array<string> newNames;
406 newNames.reserve (localNames.size());
407 std::copy (localNames.begin(), localNames.end(),
408 std::back_inserter (newNames));
409 globalNames.swap (newNames);
416 const int mid = left + (right - left + 1) / 2;
417 if (myRank >= left && myRank <= mid-1)
418 mergeCounterNamesHelper (comm, myRank, left, mid-1,
419 localNames, globalNames, setOp);
420 else if (myRank >= mid && myRank <= right)
421 mergeCounterNamesHelper (comm, myRank, mid, right,
422 localNames, globalNames, setOp);
427 if (myRank == left || myRank == mid)
428 mergeCounterNamesPair (comm, myRank, left, mid,
448 if (setOp == Union) {
449 for (
int i=0; i<localNames.
size();++i) {
452 for (
int j=0;j<globalNames.
size() && !found; ++j)
453 if (localNames[i] == globalNames[j])
458 }
else if (setOp == Intersection) {
459 for (
int i=0; i<globalNames.
size();++i) {
462 for (
int j=0;j<localNames.
size() && !found; ++j)
463 if (localNames[j] == globalNames[i])
473 "Invalid set operation enum value. Please "
474 "report this bug to the Teuchos developers.");
484 const int myRank = comm.
getRank();
486 const int right = comm.
getSize() - 1;
488 mergeCounterNamesHelper (comm, myRank, left, right,
489 localNames, theGlobalNames, setOp);
493 broadcastStrings (comm, theGlobalNames);
497 globalNames.
swap (theGlobalNames);
void remove(int i)
Remove the i-th element from the array, with optional boundschecking.
virtual int getSize() const =0
Returns the number of processes that make up this communicator.
virtual int getRank() const =0
Returns the rank of this process.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
static Teuchos::RCP< const Comm< OrdinalType > > getComm()
Return the default global communicator.
void send(const Packet sendBuffer[], const Ordinal count, const int destRank, const int tag, const Comm< Ordinal > &comm)
Variant of send() that takes a tag (and restores the correct order of arguments). ...
void mergeCounterNames(const Comm< int > &comm, const Array< std::string > &localNames, Array< std::string > &globalNames, const ECounterSetOp setOp)
Merge counter names over all processors.
friend void swap(Array< T2 > &a1, Array< T2 > &a2)
void unsortedMergePair(const Array< std::string > &localNames, Array< std::string > &globalNames, const ECounterSetOp setOp)
std::vector< std::string >::const_iterator const_iterator
The type of a const forward iterator.
void push_back(const value_type &x)
ECounterSetOp
Set operation type for mergeCounterNames() to perform.