Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
scatter.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Teuchos: Common Tools Package
4 //
5 // Copyright 2004 NTESS and the Teuchos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #include "Teuchos_ConfigDefs.hpp"
11 #include "Teuchos_DefaultComm.hpp"
12 #include "Teuchos_CommHelpers.hpp"
13 #ifdef HAVE_TEUCHOS_MPI
15 #endif // HAVE_TEUCHOS_MPI
17 
18 
19 template<class PacketType>
20 bool
21 testScatter (bool& success, std::ostream& out,
22  const int root, const Teuchos::Comm<int>& comm)
23 {
24  using Teuchos::scatter;
26  using std::endl;
27  typedef PacketType packet_type;
28 
29  // Teuchos constructs the output stream such that it only prints on
30  // Process 0 anyway.
31  Teuchos::OSTab tab0 (out);
32  out << "Testing Teuchos::scatter<int, "
33  << TypeNameTraits<packet_type>::name ()
34  << "> with root = " << root << endl;
35  Teuchos::OSTab tab1 (out);
36 
37  int lclSuccess = 1;
38  int gblSuccess = lclSuccess;
39 
40 #ifdef HAVE_TEUCHOS_MPI
41  using Teuchos::MpiComm;
42  int errCode = MPI_SUCCESS;
43 
44  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
46  (mpiComm == NULL, std::logic_error, "Building with MPI, but default "
47  "communicator is not a Teuchos::MpiComm!");
48  MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
49 #endif // HAVE_TEUCHOS_MPI
50 
51  const packet_type ZERO = Teuchos::ScalarTraits<packet_type>::zero ();
52  const packet_type ONE = Teuchos::ScalarTraits<packet_type>::one ();
53  const int myRank = comm.getRank ();
54  const int numProcs = comm.getSize ();
55  const int sendCount = 10;
56  const int recvCount = 10;
57 
58  out << "Initializing receive buffer (on all processes)" << endl;
59 
60  // Set up the receive buffer on each process.
61  Teuchos::Array<packet_type> recvBuf (recvCount);
62  for (int i = 0; i < recvCount; ++i) {
63  recvBuf[i] = ZERO;
64  }
65 
66  out << "Filling send buffer (on root process only)" << endl;
67 
68  // The send buffer is only needed on the root process. It exists
69  // elsewhere for syntax's sake, but is only allocated with nonzero
70  // size on the root process.
72  if (myRank == root) {
73  sendBuf.resize (sendCount * numProcs);
74  try {
75  // Fill the send buffer. The root process will send (p+1)*1, (p+1)*2,
76  // ..., (p+1)*sendCount to Process p. This helps us test whether the
77  // scatter worked correctly.
78  for (int p = 0; p < numProcs; ++p) {
79  for (int k = 0; k < sendCount; ++k) {
80  const packet_type val = static_cast<packet_type> (p+1) *
81  (ONE + static_cast<packet_type> (k));
82  sendBuf[p*sendCount + k] = val;
83  }
84  }
85  } catch (std::exception& e) {
86  std::cerr << "Root process " << root << " threw an exception: "
87  << e.what () << endl;
88  lclSuccess = 0;
89  }
90  }
91 
92 #ifdef HAVE_TEUCHOS_MPI
93  // Make sure that the root process didn't throw an exception when
94  // filling the send buffer, by broadcasting from it to all the other
95  // processes.
96  gblSuccess = lclSuccess;
97  errCode = MPI_Bcast (&gblSuccess, 1, MPI_INT, root, rawMpiComm);
99  (errCode != MPI_SUCCESS, std::logic_error, "MPI_Bcast failed!");
101  (gblSuccess != 1, std::logic_error, "Filling the send buffer failed on "
102  "the root (" << root << ") process! This probably indicates a bug in "
103  "the test.");
104 #endif // HAVE_TEUCHOS_MPI
105 
106  // Invoke the function to test.
107  out << "About to invoke scatter" << endl;
108  scatter<int, packet_type> (sendBuf.getRawPtr (), sendCount,
109  recvBuf.getRawPtr (), recvCount,
110  root, comm);
111  out << "Done with scatter" << endl;
112 
113  // Test whether each process got the expected results.
114  for (int k = 0; k < recvCount; ++k) {
115  const packet_type expectedVal = static_cast<packet_type> (myRank+1) *
116  (ONE + static_cast<packet_type> (k));
117  TEST_EQUALITY( recvBuf[k], expectedVal );
118  }
119  lclSuccess = success ? 1 : 0;
120  gblSuccess = lclSuccess;
121 
122  // Use an all-reduce to check whether all processes got what they
123  // should have gotten.
124  //
125  // Don't trust that any other Teuchos communicator wrapper functions
126  // work here. Instead, if building with MPI, use raw MPI. If not
127  // building with MPI, first test that comm has only one process,
128  // then assume this in the test.
129 
130 #ifdef HAVE_TEUCHOS_MPI
131  errCode = MPI_Allreduce (&lclSuccess, &gblSuccess, 1,
132  MPI_INT, MPI_MIN, rawMpiComm);
134  (errCode != MPI_SUCCESS, std::logic_error, "MPI_Allreduce failed!");
135 #else // HAVE_TEUCHOS_MPI
137  (comm.getSize () != 1, std::logic_error, "Not building with MPI, but "
138  "communicator has size = " << comm.getSize () << " != 1. We don't know "
139  "how to test this case.");
141  (comm.getRank () != root, std::logic_error, "Not building with MPI, but "
142  "the one process of rank " << comm.getRank () << " is not the root "
143  "process of rank " << root << ". We don't know how to test this case.");
144 #endif // HAVE_TEUCHOS_MPI
145 
146  return gblSuccess == 1;
147 }
148 
149 
150 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( Comm, Scatter, PacketType )
151 {
152  using Teuchos::Comm;
153  using Teuchos::RCP;
154  using std::endl;
155  typedef PacketType packet_type;
156 
157  Teuchos::OSTab tab0 (out);
158  out << "Testing Teuchos::scatter" << endl;
159  Teuchos::OSTab tab1 (out);
160 
161  RCP<const Comm<int> > comm = Teuchos::DefaultComm<int>::getComm ();
162  const int numProcs = comm->getSize ();
163 
164  // Make sure that it works for all possible root processes in the
165  // communicator, not just Process 0.
166  for (int root = 0; root < numProcs; ++root) {
167  out << "Test for root = " << root << endl;
168  const bool curSuccess = testScatter<packet_type> (success, out, root, *comm);
169  TEST_EQUALITY_CONST( curSuccess, true );
170  success = success && curSuccess;
171  }
172 
173  comm->barrier (); // make sure that everybody finished
174  out << "Done with test!" << endl;
175 }
176 
177 //
178 // mfh 14 Jul 2015: We only need to test int for now. See Bug 6375.
179 //
180 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( Comm, Scatter, int )
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.
#define TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(TEST_GROUP, TEST_NAME, TYPE)
Macro for defining a templated unit test with one template parameter.
Teuchos header file which uses auto-configuration information to include necessary C++ headers...
#define TEST_EQUALITY(v1, v2)
Assert the equality of v1 and v2.
T * getRawPtr()
Return a raw pointer to beginning of array or NULL if unsized.
static Teuchos::RCP< const Comm< OrdinalType > > getComm()
Return the default global communicator.
Tabbing class for helping to create formated, indented output for a basic_FancyOStream object...
bool testScatter(bool &success, std::ostream &out, const int root, const Teuchos::Comm< int > &comm)
Definition: scatter.cpp:21
Unit testing support.
Implementation of Teuchos wrappers for MPI.
#define TEST_EQUALITY_CONST(v1, v2)
Assert the equality of v1 and constant v2.
void resize(size_type new_size, const value_type &x=value_type())
Default traits class that just returns typeid(T).name().
static T zero()
Returns representation of zero for this scalar type.
TEUCHOSCOMM_LIB_DLL_EXPORT void scatter(const int sendBuf[], const int sendCount, int recvBuf[], const int recvCount, const int root, const Comm< int > &comm)
#define TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT(TEST_GROUP, TEST_NAME, TYPE)
Instantiate a templated unit test with one template parameter.
Smart reference counting pointer class for automatic garbage collection.
static T one()
Returns representation of one for this scalar type.
Replacement for std::vector that is compatible with the Teuchos Memory Management classes...