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 // 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 testReduceSum (bool& success, std::ostream& out,
22  const int root, const Teuchos::Comm<int>& comm)
23 {
24  using Teuchos::reduce;
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  out << "Testing Teuchos::reduce<int, " << TypeNameTraits<packet_type>::name ()
32  << "> with reductType = REDUCE_SUM and root = " << root << endl;
33 
34  const packet_type ZERO = Teuchos::ScalarTraits<packet_type>::zero ();
35  const packet_type ONE = Teuchos::ScalarTraits<packet_type>::one ();
36  const int count = 10;
37  packet_type sendBuf[10];
38  packet_type recvBuf[10];
39  for (int i = 0; i < count; ++i) {
40  sendBuf[i] = ONE;
41  recvBuf[i] = ZERO;
42  }
44  reduce<int, packet_type> (sendBuf, recvBuf, count, reductType, root, comm);
45 
46  // Don't trust that any other Teuchos communicator wrapper functions
47  // work here. Instead, if building with MPI, use raw MPI. If not
48  // building with MPI, first test that comm has only one process,
49  // then assume this in the test.
50 
51 #ifdef HAVE_TEUCHOS_MPI
52  using Teuchos::MpiComm;
53  int err = MPI_SUCCESS;
54 
55  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
57  (mpiComm == NULL, std::logic_error, "Building with MPI, but default "
58  "communicator is not a Teuchos::MpiComm!");
59  MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
60 
61  // Use a barrier to make sure that every process got this far.
62  err = MPI_Barrier (rawMpiComm);
64  (err != MPI_SUCCESS, std::logic_error, "MPI_Barrier failed!");
65 
66  // Recompute using MPI. Use an all-reduce to simplify the test.
67  packet_type sendBuf2[10];
68  packet_type recvBuf2[10];
69  for (int i = 0; i < count; ++i) {
70  sendBuf2[i] = ONE;
71  recvBuf2[i] = ZERO;
72  }
73  // FIXME (14 Jul 2015) Need to get the MPI_Datatype right for PacketType.
74  MPI_Datatype rawMpiType;
75  if (typeid (packet_type) == typeid (short)) {
76  rawMpiType = MPI_SHORT;
77  } else if (typeid (packet_type) == typeid (unsigned short)) {
78  rawMpiType = MPI_UNSIGNED_SHORT;
79  } else if (typeid (packet_type) == typeid (int)) {
80  rawMpiType = MPI_INT;
81  } else if (typeid (packet_type) == typeid (unsigned int)) {
82  rawMpiType = MPI_UNSIGNED;
83  } else if (typeid (packet_type) == typeid (long)) {
84  rawMpiType = MPI_LONG;
85  } else if (typeid (packet_type) == typeid (unsigned long)) {
86  rawMpiType = MPI_UNSIGNED_LONG;
87  } else if (typeid (packet_type) == typeid (long long)) {
88  rawMpiType = MPI_LONG_LONG;
89  } else if (typeid (packet_type) == typeid (unsigned long long)) {
90  rawMpiType = MPI_UNSIGNED_LONG_LONG;
91  } else if (typeid (packet_type) == typeid (float)) {
92  rawMpiType = MPI_FLOAT;
93  } else if (typeid (packet_type) == typeid (double)) {
94  rawMpiType = MPI_DOUBLE;
95  } else {
97  (true, std::logic_error, "Unimplemented conversion from PacketType = "
98  << TypeNameTraits<packet_type>::name () << " to MPI_Datatype.");
99  }
100 
101  err = MPI_Allreduce (sendBuf2, recvBuf2, count, rawMpiType, MPI_SUM, rawMpiComm);
103  (err != MPI_SUCCESS, std::logic_error, "MPI_Allreduce failed!");
104  if (root == comm.getRank ()) {
105  for (int i = 0; i < count; ++i) {
106  TEST_EQUALITY( recvBuf2[i], recvBuf[i] );
107  }
108  }
109 
110  int lclSuccess = success ? 1 : 0;
111  int gblSuccess = lclSuccess;
112  err = MPI_Allreduce (&lclSuccess, &gblSuccess, 1, MPI_INT, MPI_MIN, rawMpiComm);
114  (err != MPI_SUCCESS, std::logic_error, "MPI_Allreduce failed!");
115  success = gblSuccess == 1 ? true : false;
116 
117 #else // HAVE_TEUCHOS_MPI
119  (comm.getSize () != 1, std::logic_error, "Not building with MPI, but "
120  "communicator has size = " << comm.getSize () << " != 1. We don't know "
121  "how to test this case.");
122  for (int i = 0; i < count; ++i) {
123  TEST_EQUALITY( sendBuf[i], recvBuf[i] );
124  TEST_EQUALITY( recvBuf[i], ONE );
125  }
126 #endif // HAVE_TEUCHOS_MPI
127 
128  return success;
129 }
130 
131 
132 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( Comm, ReduceSum, PacketType )
133 {
134  using Teuchos::Comm;
135  using Teuchos::RCP;
136  using Teuchos::reduce;
137  typedef PacketType packet_type;
138 
139  RCP<const Comm<int> > comm = Teuchos::DefaultComm<int>::getComm ();
140  const int numProcs = comm->getSize ();
141 
142  // Make sure that it works for all possible root processes in the
143  // communicator, not just Process 0.
144  for (int root = 0; root < numProcs; ++root) {
145  const bool curSuccess = testReduceSum<packet_type> (success, out, root, *comm);
146  TEST_EQUALITY_CONST( curSuccess, true );
147  success = success && curSuccess;
148  }
149 }
150 
151 //
152 // mfh 14 Jul 2015: We only need to test int for now. See Bug 6375.
153 //
154 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.
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:21
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.