Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
scatter.cpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Teuchos: Common Tools Package
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #include "Teuchos_ConfigDefs.hpp"
43 #include "Teuchos_DefaultComm.hpp"
44 #include "Teuchos_CommHelpers.hpp"
45 #ifdef HAVE_TEUCHOS_MPI
47 #endif // HAVE_TEUCHOS_MPI
49 
50 
51 template<class PacketType>
52 bool
53 testScatter (bool& success, std::ostream& out,
54  const int root, const Teuchos::Comm<int>& comm)
55 {
56 #ifdef HAVE_TEUCHOS_MPI
57  using Teuchos::MpiComm;
58 #endif // HAVE_TEUCHOS_MPI
59  using Teuchos::scatter;
61  using std::endl;
62  typedef PacketType packet_type;
63 
64  // Teuchos constructs the output stream such that it only prints on
65  // Process 0 anyway.
66  Teuchos::OSTab tab0 (out);
67  out << "Testing Teuchos::scatter<int, "
68  << TypeNameTraits<packet_type>::name ()
69  << "> with root = " << root << endl;
70  Teuchos::OSTab tab1 (out);
71 
72  int lclSuccess = 1;
73  int gblSuccess = lclSuccess;
74 
75 #ifdef HAVE_TEUCHOS_MPI
76  using Teuchos::MpiComm;
77  int errCode = MPI_SUCCESS;
78 
79  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
81  (mpiComm == NULL, std::logic_error, "Building with MPI, but default "
82  "communicator is not a Teuchos::MpiComm!");
83  MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
84 #endif // HAVE_TEUCHOS_MPI
85 
86  const packet_type ZERO = Teuchos::ScalarTraits<packet_type>::zero ();
87  const packet_type ONE = Teuchos::ScalarTraits<packet_type>::one ();
88  const int myRank = comm.getRank ();
89  const int numProcs = comm.getSize ();
90  const int sendCount = 10;
91  const int recvCount = 10;
92 
93  out << "Initializing receive buffer (on all processes)" << endl;
94 
95  // Set up the receive buffer on each process.
96  Teuchos::Array<packet_type> recvBuf (recvCount);
97  for (int i = 0; i < recvCount; ++i) {
98  recvBuf[i] = ZERO;
99  }
100 
101  out << "Filling send buffer (on root process only)" << endl;
102 
103  // The send buffer is only needed on the root process. It exists
104  // elsewhere for syntax's sake, but is only allocated with nonzero
105  // size on the root process.
107  if (myRank == root) {
108  sendBuf.resize (sendCount * numProcs);
109  try {
110  // Fill the send buffer. The root process will send (p+1)*1, (p+1)*2,
111  // ..., (p+1)*sendCount to Process p. This helps us test whether the
112  // scatter worked correctly.
113  for (int p = 0; p < numProcs; ++p) {
114  for (int k = 0; k < sendCount; ++k) {
115  const packet_type val = static_cast<packet_type> (p+1) *
116  (ONE + static_cast<packet_type> (k));
117  sendBuf[p*sendCount + k] = val;
118  }
119  }
120  } catch (std::exception& e) {
121  std::cerr << "Root process " << root << " threw an exception: "
122  << e.what () << endl;
123  lclSuccess = 0;
124  }
125  }
126 
127 #ifdef HAVE_TEUCHOS_MPI
128  // Make sure that the root process didn't throw an exception when
129  // filling the send buffer, by broadcasting from it to all the other
130  // processes.
131  gblSuccess = lclSuccess;
132  errCode = MPI_Bcast (&gblSuccess, 1, MPI_INT, root, rawMpiComm);
134  (errCode != MPI_SUCCESS, std::logic_error, "MPI_Bcast failed!");
136  (gblSuccess != 1, std::logic_error, "Filling the send buffer failed on "
137  "the root (" << root << ") process! This probably indicates a bug in "
138  "the test.");
139 #endif // HAVE_TEUCHOS_MPI
140 
141  // Invoke the function to test.
142  out << "About to invoke scatter" << endl;
143  scatter<int, packet_type> (sendBuf.getRawPtr (), sendCount,
144  recvBuf.getRawPtr (), recvCount,
145  root, comm);
146  out << "Done with scatter" << endl;
147 
148  // Test whether each process got the expected results.
149  for (int k = 0; k < recvCount; ++k) {
150  const packet_type expectedVal = static_cast<packet_type> (myRank+1) *
151  (ONE + static_cast<packet_type> (k));
152  TEST_EQUALITY( recvBuf[k], expectedVal );
153  }
154  lclSuccess = success ? 1 : 0;
155  gblSuccess = lclSuccess;
156 
157  // Use an all-reduce to check whether all processes got what they
158  // should have gotten.
159  //
160  // Don't trust that any other Teuchos communicator wrapper functions
161  // work here. Instead, if building with MPI, use raw MPI. If not
162  // building with MPI, first test that comm has only one process,
163  // then assume this in the test.
164 
165 #ifdef HAVE_TEUCHOS_MPI
166  errCode = MPI_Allreduce (&lclSuccess, &gblSuccess, 1,
167  MPI_INT, MPI_MIN, rawMpiComm);
169  (errCode != MPI_SUCCESS, std::logic_error, "MPI_Allreduce failed!");
170 #else // HAVE_TEUCHOS_MPI
172  (comm.getSize () != 1, std::logic_error, "Not building with MPI, but "
173  "communicator has size = " << comm.getSize () << " != 1. We don't know "
174  "how to test this case.");
176  (comm.getRank () != root, std::logic_error, "Not building with MPI, but "
177  "the one process of rank " << comm.getRank () << " is not the root "
178  "process of rank " << root << ". We don't know how to test this case.");
179 #endif // HAVE_TEUCHOS_MPI
180 
181  return gblSuccess == 1;
182 }
183 
184 
185 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( Comm, Scatter, PacketType )
186 {
187  using Teuchos::Comm;
188  using Teuchos::RCP;
189  using std::endl;
190  typedef PacketType packet_type;
191 
192  Teuchos::OSTab tab0 (out);
193  out << "Testing Teuchos::scatter" << endl;
194  Teuchos::OSTab tab1 (out);
195 
196  RCP<const Comm<int> > comm = Teuchos::DefaultComm<int>::getComm ();
197  const int numProcs = comm->getSize ();
198 
199  // Make sure that it works for all possible root processes in the
200  // communicator, not just Process 0.
201  for (int root = 0; root < numProcs; ++root) {
202  out << "Test for root = " << root << endl;
203  const bool curSuccess = testScatter<packet_type> (success, out, root, *comm);
204  TEST_EQUALITY_CONST( curSuccess, true );
205  success = success && curSuccess;
206  }
207 
208  comm->barrier (); // make sure that everybody finished
209  out << "Done with test!" << endl;
210 }
211 
212 //
213 // mfh 14 Jul 2015: We only need to test int for now. See Bug 6375.
214 //
215 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( Comm, Scatter, int )
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
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:53
virtual int getRank() const =0
Returns the rank of this process.
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())
Abstract interface for distributed-memory communication.
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.
TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(Comm, Scatter, PacketType)
Definition: scatter.cpp:185
static T one()
Returns representation of one for this scalar type.
virtual int getSize() const =0
Returns the number of processes that make up this communicator.
Replacement for std::vector that is compatible with the Teuchos Memory Management classes...