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  using Teuchos::reduce;
58  using std::endl;
59  typedef PacketType packet_type;
60 
61  // Teuchos constructs the output stream such that it only prints on
62  // Process 0 anyway.
63  out << "Testing Teuchos::reduce<int, " << TypeNameTraits<packet_type>::name ()
64  << "> with reductType = REDUCE_SUM and root = " << root << endl;
65 
66  const packet_type ZERO = Teuchos::ScalarTraits<packet_type>::zero ();
67  const packet_type ONE = Teuchos::ScalarTraits<packet_type>::one ();
68  const int count = 10;
69  packet_type sendBuf[10];
70  packet_type recvBuf[10];
71  for (int i = 0; i < count; ++i) {
72  sendBuf[i] = ONE;
73  recvBuf[i] = ZERO;
74  }
76  reduce<int, packet_type> (sendBuf, recvBuf, count, reductType, root, comm);
77 
78  // Don't trust that any other Teuchos communicator wrapper functions
79  // work here. Instead, if building with MPI, use raw MPI. If not
80  // building with MPI, first test that comm has only one process,
81  // then assume this in the test.
82 
83 #ifdef HAVE_TEUCHOS_MPI
84  using Teuchos::MpiComm;
85  int err = MPI_SUCCESS;
86 
87  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
89  (mpiComm == NULL, std::logic_error, "Building with MPI, but default "
90  "communicator is not a Teuchos::MpiComm!");
91  MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
92 
93  // Use a barrier to make sure that every process got this far.
94  err = MPI_Barrier (rawMpiComm);
96  (err != MPI_SUCCESS, std::logic_error, "MPI_Barrier failed!");
97 
98  // Recompute using MPI. Use an all-reduce to simplify the test.
99  packet_type sendBuf2[10];
100  packet_type recvBuf2[10];
101  for (int i = 0; i < count; ++i) {
102  sendBuf2[i] = ONE;
103  recvBuf2[i] = ZERO;
104  }
105  // FIXME (14 Jul 2015) Need to get the MPI_Datatype right for PacketType.
106  MPI_Datatype rawMpiType;
107  if (typeid (packet_type) == typeid (short)) {
108  rawMpiType = MPI_SHORT;
109  } else if (typeid (packet_type) == typeid (unsigned short)) {
110  rawMpiType = MPI_UNSIGNED_SHORT;
111  } else if (typeid (packet_type) == typeid (int)) {
112  rawMpiType = MPI_INT;
113  } else if (typeid (packet_type) == typeid (unsigned int)) {
114  rawMpiType = MPI_UNSIGNED;
115  } else if (typeid (packet_type) == typeid (long)) {
116  rawMpiType = MPI_LONG;
117  } else if (typeid (packet_type) == typeid (unsigned long)) {
118  rawMpiType = MPI_UNSIGNED_LONG;
119  } else if (typeid (packet_type) == typeid (long long)) {
120  rawMpiType = MPI_LONG_LONG;
121  } else if (typeid (packet_type) == typeid (unsigned long long)) {
122  rawMpiType = MPI_UNSIGNED_LONG_LONG;
123  } else if (typeid (packet_type) == typeid (float)) {
124  rawMpiType = MPI_FLOAT;
125  } else if (typeid (packet_type) == typeid (double)) {
126  rawMpiType = MPI_DOUBLE;
127  } else {
129  (true, std::logic_error, "Unimplemented conversion from PacketType = "
130  << TypeNameTraits<packet_type>::name () << " to MPI_Datatype.");
131  }
132 
133  err = MPI_Allreduce (sendBuf2, recvBuf2, count, rawMpiType, MPI_SUM, rawMpiComm);
135  (err != MPI_SUCCESS, std::logic_error, "MPI_Allreduce failed!");
136  if (root == comm.getRank ()) {
137  for (int i = 0; i < count; ++i) {
138  TEST_EQUALITY( recvBuf2[i], recvBuf[i] );
139  }
140  }
141 
142  int lclSuccess = success ? 1 : 0;
143  int gblSuccess = lclSuccess;
144  err = MPI_Allreduce (&lclSuccess, &gblSuccess, 1, MPI_INT, MPI_MIN, rawMpiComm);
146  (err != MPI_SUCCESS, std::logic_error, "MPI_Allreduce failed!");
147  success = gblSuccess == 1 ? true : false;
148 
149 #else // HAVE_TEUCHOS_MPI
151  (comm.getSize () != 1, std::logic_error, "Not building with MPI, but "
152  "communicator has size = " << comm.getSize () << " != 1. We don't know "
153  "how to test this case.");
154  for (int i = 0; i < count; ++i) {
155  TEST_EQUALITY( sendBuf[i], recvBuf[i] );
156  TEST_EQUALITY( recvBuf[i], ONE );
157  }
158 #endif // HAVE_TEUCHOS_MPI
159 
160  return success;
161 }
162 
163 
164 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( Comm, ReduceSum, PacketType )
165 {
166  using Teuchos::Comm;
167  using Teuchos::RCP;
168  using Teuchos::reduce;
169  typedef PacketType packet_type;
170 
171  RCP<const Comm<int> > comm = Teuchos::DefaultComm<int>::getComm ();
172  const int numProcs = comm->getSize ();
173 
174  // Make sure that it works for all possible root processes in the
175  // communicator, not just Process 0.
176  for (int root = 0; root < numProcs; ++root) {
177  const bool curSuccess = testReduceSum<packet_type> (success, out, root, *comm);
178  TEST_EQUALITY_CONST( curSuccess, true );
179  success = success && curSuccess;
180  }
181 }
182 
183 //
184 // mfh 14 Jul 2015: We only need to test int for now. See Bug 6375.
185 //
186 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: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.