Tpetra parallel linear algebra Version of the Day
Loading...
Searching...
No Matches
Tpetra_Details_MpiTypeTraits.cpp
1/*
2// @HEADER
3// ***********************************************************************
4//
5// Tpetra: Templated Linear Algebra Services Package
6// Copyright (2008) Sandia Corporation
7//
8// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9// the U.S. Government retains certain rights in this software.
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17//
18// 2. Redistributions in binary form must reproduce the above copyright
19// notice, this list of conditions and the following disclaimer in the
20// documentation and/or other materials provided with the distribution.
21//
22// 3. Neither the name of the Corporation nor the names of the
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39//
40// ************************************************************************
41// @HEADER
42*/
43
45
46#ifdef HAVE_TPETRACORE_MPI
47
48namespace Teuchos {
49namespace Details {
50namespace Impl {
51
62template<class T>
63MPI_Datatype
64computeKokkosComplexMpiDatatypeImpl (const ::Kokkos::complex<T>& z)
65{
66 static_assert (MpiTypeTraits<T>::isSpecialized, "This function only "
67 "works if MpiTypeTraits<T>::isSpecialized.");
68 static_assert (! MpiTypeTraits<T>::needsFree, "This function requires "
69 "! MpiTypeTraits<T>::needsFree, since otherwise it would "
70 "leak memory.");
71 // We assume here that every instance of T has the same
72 // MPI_Datatype, i.e., has the same binary representation.
73 MPI_Datatype innerDatatype = MpiTypeTraits<T>::getType (z.real ());
74 MPI_Datatype outerDatatype; // return value
75
76 // If Kokkos::complex<T> has the same layout as T[2], then we can
77 // use a contiguous derived MPI_Datatype. This is likely the only
78 // code path that will execute. Contiguous types are likely more
79 // efficient for MPI to execute, and almost certainly more efficient
80 // for MPI to set up.
81 if (sizeof ( ::Kokkos::complex<T>) == 2 * sizeof (T)) {
82 (void) MPI_Type_contiguous (2, innerDatatype, &outerDatatype);
83 }
84 else { // must use the general struct approach
85 // I borrowed and adapted the code below from the MPICH
86 // documentation:
87 //
88 // www.mpich.org/static/docs/v3.1/www3/MPI_Type_struct.html
89 int blockLengths[3];
90 MPI_Aint arrayOfDisplacements[3];
91 MPI_Datatype arrayOfTypes[3];
92
93 // See documentation of MyComplex (above) for explanation.
94 static_assert (sizeof (MyComplex<T>) == sizeof ( ::Kokkos::complex<T>),
95 "Attempt to construct a struct of the same size and layout "
96 "as Kokkos::complex<T> failed.");
97 ::Teuchos::Details::Impl::MyComplex<T> z2;
98
99 // First entry in the struct.
100 blockLengths[0] = 1;
101 // Normally, &z2.re would equal &z2, but I'll be conservative and
102 // actually compute the offset, even though it's probably just 0.
103 //
104 // Need the cast to prevent the compiler complaining about
105 // subtracting addresses of different types.
106 arrayOfDisplacements[0] = reinterpret_cast<uintptr_t> (&z2.re) - reinterpret_cast<uintptr_t> (&z2);
107 arrayOfTypes[0] = innerDatatype;
108
109 // Second entry in the struct.
110 blockLengths[1] = 1;
111 arrayOfDisplacements[1] = reinterpret_cast<uintptr_t> (&z2.im) - reinterpret_cast<uintptr_t> (&z2);
112 arrayOfTypes[1] = innerDatatype;
113
114#if MPI_VERSION < 2
115 // Upper bound of the struct.
116 blockLengths[2] = 1;
117 arrayOfDisplacements[2] = sizeof (MyComplex<T>);
118 arrayOfTypes[2] = MPI_UB; // "upper bound type"; signals end of struct
119#endif // MPI_VERSION < 2
120
121 // Define the MPI_Datatype.
122#if MPI_VERSION < 2
123 (void) MPI_Type_struct (3, blockLengths, arrayOfDisplacements,
124 arrayOfTypes, &outerDatatype);
125#else
126 // Don't include the upper bound with MPI_Type_create_struct.
127 (void) MPI_Type_create_struct (2, blockLengths, arrayOfDisplacements,
128 arrayOfTypes, &outerDatatype);
129#endif // MPI_VERSION < 2
130 }
131
132 MPI_Type_commit (&outerDatatype);
133 return outerDatatype;
134}
135
137MPI_Datatype
138computeKokkosComplexMpiDatatype (const ::Kokkos::complex<double>& z)
139{
140
141 return computeKokkosComplexMpiDatatypeImpl<double> (z);
142}
143
145MPI_Datatype
146computeKokkosComplexMpiDatatype (const ::Kokkos::complex<float>& z)
147{
148 return computeKokkosComplexMpiDatatypeImpl<float> (z);
149}
150
151} // namespace Impl
152
153MPI_Datatype
154MpiTypeTraits< ::Kokkos::complex<double> >::
155getType (const ::Kokkos::complex<double>& z)
156{
157 if (hasMpi3) {
158#if MPI_VERSION >= 3
159 return MPI_C_DOUBLE_COMPLEX; // requires MPI 2.?
160#else
161 return MPI_DATATYPE_NULL; // FIXME (mfh 17 Nov 2016) Better to throw?
162#endif // MPI_VERSION >= 3
163 }
164 else { // ! hasMpi3
165 return Impl::computeKokkosComplexMpiDatatype (z);
166 }
167}
168
169MPI_Datatype
170MpiTypeTraits< ::Kokkos::complex<double> >::
171getType ()
172{
173 if (hasMpi3) {
174#if MPI_VERSION >= 3
175 return MPI_C_DOUBLE_COMPLEX; // requires MPI 2.?
176#else
177 return MPI_DATATYPE_NULL; // FIXME (mfh 17 Nov 2016) Better to throw?
178#endif // MPI_VERSION >= 3
179 }
180 else { // ! hasMpi3
181 // Values are arbitrary. The function just looks at the address
182 // offsets of the class fields, not their contents.
183 ::Kokkos::complex<double> z (3.0, 4.0);
184 return Impl::computeKokkosComplexMpiDatatype (z);
185 }
186}
187
188MPI_Datatype
189MpiTypeTraits< ::Kokkos::complex<float> >::
190getType (const ::Kokkos::complex<float>& z)
191{
192 if (hasMpi3) {
193#if MPI_VERSION >= 3
194 return MPI_C_FLOAT_COMPLEX; // requires MPI 2.?
195#else
196 return MPI_DATATYPE_NULL; // FIXME (mfh 17 Nov 2016) Better to throw?
197#endif // MPI_VERSION >= 3
198 }
199 else { // ! hasMpi3
200 return Impl::computeKokkosComplexMpiDatatype (z);
201 }
202}
203
204MPI_Datatype
205MpiTypeTraits< ::Kokkos::complex<float> >::
206getType ()
207{
208 if (hasMpi3) {
209#if MPI_VERSION >= 3
210 return MPI_C_FLOAT_COMPLEX; // requires MPI 2.?
211#else
212 return MPI_DATATYPE_NULL; // FIXME (mfh 17 Nov 2016) Better to throw?
213#endif // MPI_VERSION >= 3
214 }
215 else { // ! hasMpi3
216 // Values are arbitrary. The function just looks at the address
217 // offsets of the class fields, not their contents.
218 ::Kokkos::complex<float> z (3.0, 4.0);
219 return Impl::computeKokkosComplexMpiDatatype (z);
220 }
221}
222
223} // namespace Details
224} // namespace Teuchos
225
226
227#endif // HAVE_TPETRACORE_MPI
Add specializations of Teuchos::Details::MpiTypeTraits for Kokkos::complex<float> and Kokkos::complex...
Implementation details of Tpetra.