43 #include "Teuchos_CommHelpers.hpp"
44 #include "Teuchos_DefaultComm.hpp"
74 packStringsForSend (std::string& packedString,
75 Array<size_t>& offsets,
76 const Array<std::string>& strings)
82 const bool debug =
false;
85 offsets.resize (strings.size() + 1);
86 size_t totalLength = 0;
87 Array<size_t>::size_type offsetsIndex = 0;
88 for (Array<string>::const_iterator it = strings.begin();
89 it != strings.end(); ++it, ++offsetsIndex)
91 offsets[offsetsIndex] = totalLength;
92 totalLength += it->size();
94 offsets[offsetsIndex] = totalLength;
97 packedString.resize (totalLength);
98 string::iterator packedStringIter = packedString.begin();
99 for (Array<string>::const_iterator it = strings.begin();
100 it != strings.end(); ++it)
101 packedStringIter = std::copy (it->begin(), it->end(), packedStringIter);
105 std::ostringstream out;
107 out <<
"Proc " << pComm->getRank() <<
": in pack: offsets = [";
108 for (Array<size_t>::const_iterator it = offsets.begin();
109 it != offsets.end(); ++it)
112 if (it + 1 != offsets.end())
115 out <<
"], packedString = " << packedString << endl;
128 sendStrings (
const Comm<int>& comm,
129 const Array<std::string>& strings,
134 std::string packedString;
135 Array<size_t> offsets;
136 packStringsForSend (packedString, offsets, strings);
138 "packStringsForSend() returned a zero-length offsets "
139 "array on MPI Proc " << comm.getRank() <<
", to be "
140 "sent to Proc " << destRank <<
". The offsets array "
141 "should always have positive length. Please report "
142 "this bug to the Teuchos developers.");
145 send (comm, offsets.size(), destRank);
150 const int offsetsSendCount =
static_cast<int> (offsets.size());
151 send (comm, offsetsSendCount, &offsets[0], destRank);
158 const int stringSendCount =
static_cast<int> (packedString.size());
159 if (stringSendCount > 0)
160 send (comm, stringSendCount, &packedString[0], destRank);
164 unpackStringsAfterReceive (Array<std::string>& strings,
165 const std::string& packedString,
166 const Array<size_t> offsets)
168 const bool debug =
false;
174 std::ostringstream out;
176 out <<
"Proc " << pComm->getRank() <<
": in unpack: offsets = [";
177 for (Array<size_t>::const_iterator it = offsets.begin();
178 it != offsets.end(); ++it)
181 if (it + 1 != offsets.end())
184 out <<
"], packedString = " << packedString << endl;
188 "The offsets array has length zero, which does not "
189 "make sense. Even when sending / receiving zero "
190 "strings, the offsets array should have one entry "
192 const Array<size_t>::size_type numStrings = offsets.size() - 1;
193 strings.resize (numStrings);
194 for (Array<size_t>::size_type k = 0; k < numStrings; ++k)
197 const size_t start = offsets[k];
198 const size_t end = offsets[k+1];
199 strings[k] = packedString.substr (start, end - start);
206 receiveStrings (
const Comm<int>& comm,
207 const int sourceRank,
208 Array<std::string>& strings)
212 Array<size_t>::size_type numOffsets = 0;
213 receive (comm, sourceRank, &numOffsets);
215 "Invalid number of offsets numOffsets=" << numOffsets
216 <<
" received on MPI Rank " << comm.getRank()
217 <<
" from Rank " << sourceRank <<
". Please report "
218 "this bug to the Teuchos developers.");
221 Array<size_t> offsets (numOffsets);
222 const int offsetsRecvCount =
static_cast<int> (numOffsets);
223 receive (comm, sourceRank, offsetsRecvCount, &offsets[0]);
228 std::string packedString (offsets.back(),
' ');
229 const int stringRecvCount =
static_cast<int> (offsets.back());
230 if (stringRecvCount > 0)
232 receive (comm, sourceRank, stringRecvCount, &packedString[0]);
233 unpackStringsAfterReceive (strings, packedString, offsets);
239 broadcastStringsHelper (
const Comm<int>& comm,
243 Array<std::string>& globalNames)
255 const int mid = left + (right - left + 1) / 2;
261 sendStrings (comm, globalNames, mid);
262 else if (myRank == mid)
263 receiveStrings (comm, left, globalNames);
266 if (myRank >= left && myRank <= mid-1)
267 broadcastStringsHelper (comm, myRank, left, mid-1, globalNames);
268 else if (myRank >= mid && myRank <= right)
269 broadcastStringsHelper (comm, myRank, mid, right, globalNames);
277 broadcastStrings (
const Comm<int>& comm,
278 Array<std::string>& globalNames)
280 const int myRank = comm.getRank();
282 const int right = comm.getSize() - 1;
284 broadcastStringsHelper (comm, myRank, left, right, globalNames);
320 mergeCounterNamesPair (
const Comm<int>& comm,
324 Array<std::string>& globalNames,
331 const bool debug =
false;
336 Array<string> otherNames;
337 receiveStrings (comm, mid, otherNames);
344 std::ostringstream out;
345 out <<
"Proc " << myRank <<
": in mergePair: otherNames = [";
347 it != otherNames.end(); ++it)
349 out <<
"\"" << *it <<
"\"";
350 if (it + 1 != otherNames.end())
360 Array<string> newNames;
361 if ( std::is_sorted(globalNames.begin(), globalNames.end()) &&
362 std::is_sorted(otherNames.begin(), otherNames.end())) {
363 if (setOp == Intersection)
364 std::set_intersection (globalNames.begin(), globalNames.end(),
365 otherNames.begin(), otherNames.end(),
366 std::back_inserter (newNames));
367 else if (setOp == Union)
368 std::set_union (globalNames.begin(), globalNames.end(),
369 otherNames.begin(), otherNames.end(),
370 std::back_inserter (newNames));
374 "Invalid set operation enum value. Please "
375 "report this bug to the Teuchos developers.");
376 globalNames.swap (newNames);
381 else if (myRank == mid)
382 sendStrings (comm, globalNames, left);
386 "myRank=" << myRank <<
" is neither left=" << left
387 <<
" nor mid=" << mid <<
". Please report this "
388 "bug to the Teuchos developers.");
401 mergeCounterNamesHelper (
const Comm<int>& comm,
405 const Array<std::string>& localNames,
406 Array<std::string>& globalNames,
435 else if (left == right)
437 Array<string> newNames;
438 newNames.reserve (localNames.size());
439 std::copy (localNames.begin(), localNames.end(),
440 std::back_inserter (newNames));
441 globalNames.swap (newNames);
448 const int mid = left + (right - left + 1) / 2;
449 if (myRank >= left && myRank <= mid-1)
450 mergeCounterNamesHelper (comm, myRank, left, mid-1,
451 localNames, globalNames, setOp);
452 else if (myRank >= mid && myRank <= right)
453 mergeCounterNamesHelper (comm, myRank, mid, right,
454 localNames, globalNames, setOp);
459 if (myRank == left || myRank == mid)
460 mergeCounterNamesPair (comm, myRank, left, mid,
480 if (setOp == Union) {
481 for (
int i=0; i<localNames.
size();++i) {
484 for (
int j=0;j<globalNames.
size() && !found; ++j)
485 if (localNames[i] == globalNames[j])
490 }
else if (setOp == Intersection) {
491 for (
int i=0; i<globalNames.
size();++i) {
494 for (
int j=0;j<localNames.
size() && !found; ++j)
495 if (localNames[j] == globalNames[i])
505 "Invalid set operation enum value. Please "
506 "report this bug to the Teuchos developers.");
516 const int myRank = comm.
getRank();
518 const int right = comm.
getSize() - 1;
520 mergeCounterNamesHelper (comm, myRank, left, right,
521 localNames, theGlobalNames, setOp);
525 broadcastStrings (comm, theGlobalNames);
529 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.
Abstract interface for distributed-memory communication.
void push_back(const value_type &x)
ECounterSetOp
Set operation type for mergeCounterNames() to perform.