Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Loading...
Searching...
No Matches
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
45#ifdef HAVE_TEUCHOS_MPI
47#endif // HAVE_TEUCHOS_MPI
49
50
51template<class PacketType>
52bool
53testScatter (bool& success, std::ostream& out,
54 const int root, const Teuchos::Comm<int>& comm)
55{
56 using Teuchos::scatter;
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 Teuchos::OSTab tab0 (out);
64 out << "Testing Teuchos::scatter<int, "
65 << TypeNameTraits<packet_type>::name ()
66 << "> with root = " << root << endl;
67 Teuchos::OSTab tab1 (out);
68
69 int lclSuccess = 1;
70 int gblSuccess = lclSuccess;
71
72#ifdef HAVE_TEUCHOS_MPI
73 using Teuchos::MpiComm;
74 int errCode = MPI_SUCCESS;
75
76 const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
78 (mpiComm == NULL, std::logic_error, "Building with MPI, but default "
79 "communicator is not a Teuchos::MpiComm!");
80 MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
81#endif // HAVE_TEUCHOS_MPI
82
83 const packet_type ZERO = Teuchos::ScalarTraits<packet_type>::zero ();
84 const packet_type ONE = Teuchos::ScalarTraits<packet_type>::one ();
85 const int myRank = comm.getRank ();
86 const int numProcs = comm.getSize ();
87 const int sendCount = 10;
88 const int recvCount = 10;
89
90 out << "Initializing receive buffer (on all processes)" << endl;
91
92 // Set up the receive buffer on each process.
93 Teuchos::Array<packet_type> recvBuf (recvCount);
94 for (int i = 0; i < recvCount; ++i) {
95 recvBuf[i] = ZERO;
96 }
97
98 out << "Filling send buffer (on root process only)" << endl;
99
100 // The send buffer is only needed on the root process. It exists
101 // elsewhere for syntax's sake, but is only allocated with nonzero
102 // size on the root process.
104 if (myRank == root) {
105 sendBuf.resize (sendCount * numProcs);
106 try {
107 // Fill the send buffer. The root process will send (p+1)*1, (p+1)*2,
108 // ..., (p+1)*sendCount to Process p. This helps us test whether the
109 // scatter worked correctly.
110 for (int p = 0; p < numProcs; ++p) {
111 for (int k = 0; k < sendCount; ++k) {
112 const packet_type val = static_cast<packet_type> (p+1) *
113 (ONE + static_cast<packet_type> (k));
114 sendBuf[p*sendCount + k] = val;
115 }
116 }
117 } catch (std::exception& e) {
118 std::cerr << "Root process " << root << " threw an exception: "
119 << e.what () << endl;
120 lclSuccess = 0;
121 }
122 }
123
124#ifdef HAVE_TEUCHOS_MPI
125 // Make sure that the root process didn't throw an exception when
126 // filling the send buffer, by broadcasting from it to all the other
127 // processes.
128 gblSuccess = lclSuccess;
129 errCode = MPI_Bcast (&gblSuccess, 1, MPI_INT, root, rawMpiComm);
131 (errCode != MPI_SUCCESS, std::logic_error, "MPI_Bcast failed!");
133 (gblSuccess != 1, std::logic_error, "Filling the send buffer failed on "
134 "the root (" << root << ") process! This probably indicates a bug in "
135 "the test.");
136#endif // HAVE_TEUCHOS_MPI
137
138 // Invoke the function to test.
139 out << "About to invoke scatter" << endl;
140 scatter<int, packet_type> (sendBuf.getRawPtr (), sendCount,
141 recvBuf.getRawPtr (), recvCount,
142 root, comm);
143 out << "Done with scatter" << endl;
144
145 // Test whether each process got the expected results.
146 for (int k = 0; k < recvCount; ++k) {
147 const packet_type expectedVal = static_cast<packet_type> (myRank+1) *
148 (ONE + static_cast<packet_type> (k));
149 TEST_EQUALITY( recvBuf[k], expectedVal );
150 }
151 lclSuccess = success ? 1 : 0;
152 gblSuccess = lclSuccess;
153
154 // Use an all-reduce to check whether all processes got what they
155 // should have gotten.
156 //
157 // Don't trust that any other Teuchos communicator wrapper functions
158 // work here. Instead, if building with MPI, use raw MPI. If not
159 // building with MPI, first test that comm has only one process,
160 // then assume this in the test.
161
162#ifdef HAVE_TEUCHOS_MPI
163 errCode = MPI_Allreduce (&lclSuccess, &gblSuccess, 1,
164 MPI_INT, MPI_MIN, rawMpiComm);
166 (errCode != MPI_SUCCESS, std::logic_error, "MPI_Allreduce failed!");
167#else // HAVE_TEUCHOS_MPI
169 (comm.getSize () != 1, std::logic_error, "Not building with MPI, but "
170 "communicator has size = " << comm.getSize () << " != 1. We don't know "
171 "how to test this case.");
173 (comm.getRank () != root, std::logic_error, "Not building with MPI, but "
174 "the one process of rank " << comm.getRank () << " is not the root "
175 "process of rank " << root << ". We don't know how to test this case.");
176#endif // HAVE_TEUCHOS_MPI
177
178 return gblSuccess == 1;
179}
180
181
182TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( Comm, Scatter, PacketType )
183{
184 using Teuchos::Comm;
185 using Teuchos::RCP;
186 using std::endl;
187 typedef PacketType packet_type;
188
189 Teuchos::OSTab tab0 (out);
190 out << "Testing Teuchos::scatter" << endl;
191 Teuchos::OSTab tab1 (out);
192
193 RCP<const Comm<int> > comm = Teuchos::DefaultComm<int>::getComm ();
194 const int numProcs = comm->getSize ();
195
196 // Make sure that it works for all possible root processes in the
197 // communicator, not just Process 0.
198 for (int root = 0; root < numProcs; ++root) {
199 out << "Test for root = " << root << endl;
200 const bool curSuccess = testScatter<packet_type> (success, out, root, *comm);
201 TEST_EQUALITY_CONST( curSuccess, true );
202 success = success && curSuccess;
203 }
204
205 comm->barrier (); // make sure that everybody finished
206 out << "Done with test!" << endl;
207}
208
209//
210// mfh 14 Jul 2015: We only need to test int for now. See Bug 6375.
211//
212TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( Comm, Scatter, int )
Teuchos header file which uses auto-configuration information to include necessary C++ headers.
Implementation of Teuchos wrappers for MPI.
#define TEST_EQUALITY_CONST(v1, v2)
Assert the equality of v1 and constant v2.
#define TEST_EQUALITY(v1, v2)
Assert the equality of v1 and v2.
Unit testing support.
#define TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(TEST_GROUP, TEST_NAME, TYPE)
Macro for defining a templated unit test with one template parameter.
#define TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT(TEST_GROUP, TEST_NAME, TYPE)
Instantiate a templated unit test with one template parameter.
Abstract interface for distributed-memory communication.
static Teuchos::RCP< const Comm< OrdinalType > > getComm()
Return the default global communicator.
Smart reference counting pointer class for automatic garbage collection.
Concrete serial communicator subclass.
Default traits class that just returns typeid(T).name().
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
TEUCHOSCOMM_LIB_DLL_EXPORT void scatter(const int sendBuf[], const int sendCount, int recvBuf[], const int recvCount, const int root, const Comm< int > &comm)
bool testScatter(bool &success, std::ostream &out, const int root, const Teuchos::Comm< int > &comm)
Definition scatter.cpp:53
static T one()
Returns representation of one for this scalar type.
static T zero()
Returns representation of zero for this scalar type.