Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
reduce.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 testReduceSum (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::reduce;
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  out << "Testing Teuchos::reduce<int, " << TypeNameTraits<packet_type>::name ()
67  << "> with reductType = REDUCE_SUM and root = " << root << endl;
68 
69  const packet_type ZERO = Teuchos::ScalarTraits<packet_type>::zero ();
70  const packet_type ONE = Teuchos::ScalarTraits<packet_type>::one ();
71  const int count = 10;
72  packet_type sendBuf[10];
73  packet_type recvBuf[10];
74  for (int i = 0; i < count; ++i) {
75  sendBuf[i] = ONE;
76  recvBuf[i] = ZERO;
77  }
79  reduce<int, packet_type> (sendBuf, recvBuf, count, reductType, root, comm);
80 
81  // Don't trust that any other Teuchos communicator wrapper functions
82  // work here. Instead, if building with MPI, use raw MPI. If not
83  // building with MPI, first test that comm has only one process,
84  // then assume this in the test.
85 
86 #ifdef HAVE_TEUCHOS_MPI
87  using Teuchos::MpiComm;
88  int err = MPI_SUCCESS;
89 
90  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
92  (mpiComm == NULL, std::logic_error, "Building with MPI, but default "
93  "communicator is not a Teuchos::MpiComm!");
94  MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
95 
96  // Use a barrier to make sure that every process got this far.
97  err = MPI_Barrier (rawMpiComm);
99  (err != MPI_SUCCESS, std::logic_error, "MPI_Barrier failed!");
100 
101  // Recompute using MPI. Use an all-reduce to simplify the test.
102  packet_type sendBuf2[10];
103  packet_type recvBuf2[10];
104  for (int i = 0; i < count; ++i) {
105  sendBuf2[i] = ONE;
106  recvBuf2[i] = ZERO;
107  }
108  // FIXME (14 Jul 2015) Need to get the MPI_Datatype right for PacketType.
109  MPI_Datatype rawMpiType;
110  if (typeid (packet_type) == typeid (short)) {
111  rawMpiType = MPI_SHORT;
112  } else if (typeid (packet_type) == typeid (unsigned short)) {
113  rawMpiType = MPI_UNSIGNED_SHORT;
114  } else if (typeid (packet_type) == typeid (int)) {
115  rawMpiType = MPI_INT;
116  } else if (typeid (packet_type) == typeid (unsigned int)) {
117  rawMpiType = MPI_UNSIGNED;
118  } else if (typeid (packet_type) == typeid (long)) {
119  rawMpiType = MPI_LONG;
120  } else if (typeid (packet_type) == typeid (unsigned long)) {
121  rawMpiType = MPI_UNSIGNED_LONG;
122  } else if (typeid (packet_type) == typeid (long long)) {
123  rawMpiType = MPI_LONG_LONG;
124  } else if (typeid (packet_type) == typeid (unsigned long long)) {
125  rawMpiType = MPI_UNSIGNED_LONG_LONG;
126  } else if (typeid (packet_type) == typeid (float)) {
127  rawMpiType = MPI_FLOAT;
128  } else if (typeid (packet_type) == typeid (double)) {
129  rawMpiType = MPI_DOUBLE;
130  } else {
132  (true, std::logic_error, "Unimplemented conversion from PacketType = "
133  << TypeNameTraits<packet_type>::name () << " to MPI_Datatype.");
134  }
135 
136  err = MPI_Allreduce (sendBuf2, recvBuf2, count, rawMpiType, MPI_SUM, rawMpiComm);
138  (err != MPI_SUCCESS, std::logic_error, "MPI_Allreduce failed!");
139  if (root == comm.getRank ()) {
140  for (int i = 0; i < count; ++i) {
141  TEST_EQUALITY( recvBuf2[i], recvBuf[i] );
142  }
143  }
144 
145  int lclSuccess = success ? 1 : 0;
146  int gblSuccess = lclSuccess;
147  err = MPI_Allreduce (&lclSuccess, &gblSuccess, 1, MPI_INT, MPI_MIN, rawMpiComm);
149  (err != MPI_SUCCESS, std::logic_error, "MPI_Allreduce failed!");
150  success = gblSuccess == 1 ? true : false;
151 
152 #else // HAVE_TEUCHOS_MPI
154  (comm.getSize () != 1, std::logic_error, "Not building with MPI, but "
155  "communicator has size = " << comm.getSize () << " != 1. We don't know "
156  "how to test this case.");
157  for (int i = 0; i < count; ++i) {
158  TEST_EQUALITY( sendBuf[i], recvBuf[i] );
159  TEST_EQUALITY( recvBuf[i], ONE );
160  }
161 #endif // HAVE_TEUCHOS_MPI
162 
163  return success;
164 }
165 
166 
167 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( Comm, ReduceSum, PacketType )
168 {
169  using Teuchos::Comm;
170  using Teuchos::RCP;
171  using Teuchos::reduce;
172  typedef PacketType packet_type;
173 
174  RCP<const Comm<int> > comm = Teuchos::DefaultComm<int>::getComm ();
175  const int numProcs = comm->getSize ();
176 
177  // Make sure that it works for all possible root processes in the
178  // communicator, not just Process 0.
179  for (int root = 0; root < numProcs; ++root) {
180  const bool curSuccess = testReduceSum<packet_type> (success, out, root, *comm);
181  TEST_EQUALITY_CONST( curSuccess, true );
182  success = success && curSuccess;
183  }
184 }
185 
186 //
187 // mfh 14 Jul 2015: We only need to test int for now. See Bug 6375.
188 //
189 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( Comm, ReduceSum, int )
virtual int getSize() const =0
Returns the number of processes that make up this communicator.
EReductionType
Predefined reduction operations that Teuchos::Comm understands.
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.
static Teuchos::RCP< const Comm< OrdinalType > > getComm()
Return the default global communicator.
Unit testing support.
Implementation of Teuchos wrappers for MPI.
#define TEST_EQUALITY_CONST(v1, v2)
Assert the equality of v1 and constant v2.
Abstract interface for distributed-memory communication.
Default traits class that just returns typeid(T).name().
bool testReduceSum(bool &success, std::ostream &out, const int root, const Teuchos::Comm< int > &comm)
Definition: reduce.cpp:53
static T zero()
Returns representation of zero for this scalar type.
#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.