Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
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  }
78  const Teuchos::EReductionType reductType = Teuchos::REDUCE_SUM;
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 )
Teuchos_DefaultComm.hpp
Teuchos::ScalarTraits::zero
static T zero()
Returns representation of zero for this scalar type.
Definition: Teuchos_ScalarTraitsDecl.hpp:132
TEST_EQUALITY
#define TEST_EQUALITY(v1, v2)
Assert the equality of v1 and v2.
Definition: Teuchos_LocalTestingHelpers.hpp:87
Teuchos::TypeNameTraits
Default traits class that just returns typeid(T).name().
Definition: Teuchos_TypeNameTraits.hpp:85
Teuchos::Comm::getRank
virtual int getRank() const =0
Returns the rank of this process.
Teuchos::RCP
Smart reference counting pointer class for automatic garbage collection.
Definition: Teuchos_RCPDecl.hpp:429
Teuchos_UnitTestHarness.hpp
Unit testing support.
Teuchos_DefaultMpiComm.hpp
Implementation of Teuchos wrappers for MPI.
Teuchos::REDUCE_SUM
Sum.
Definition: Teuchos_EReductionType.hpp:72
Teuchos::ScalarTraits::one
static T one()
Returns representation of one for this scalar type.
Definition: Teuchos_ScalarTraitsDecl.hpp:134
TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL
TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(Comm, ReduceSum, PacketType)
Definition: reduce.cpp:167
TEST_EQUALITY_CONST
#define TEST_EQUALITY_CONST(v1, v2)
Assert the equality of v1 and constant v2.
Definition: Teuchos_LocalTestingHelpers.hpp:79
Teuchos_ConfigDefs.hpp
Teuchos header file which uses auto-configuration information to include necessary C++ headers.
testReduceSum
bool testReduceSum(bool &success, std::ostream &out, const int root, const Teuchos::Comm< int > &comm)
Definition: reduce.cpp:53
Teuchos::DefaultComm::getComm
static Teuchos::RCP< const Comm< OrdinalType > > getComm()
Return the default global communicator.
Definition: Teuchos_DefaultComm.hpp:212
TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT
#define TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT(TEST_GROUP, TEST_NAME, TYPE)
Instantiate a templated unit test with one template parameter.
Definition: Teuchos_UnitTestHelpers.hpp:187
Teuchos_CommHelpers.hpp
Teuchos::Comm::getSize
virtual int getSize() const =0
Returns the number of processes that make up this communicator.
Teuchos::Comm
Abstract interface for distributed-memory communication.
Definition: Teuchos_Comm.hpp:85
TEUCHOS_TEST_FOR_EXCEPTION
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Definition: Teuchos_TestForException.hpp:170