1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 //          Kokkos: Node API and Parallel Node Kernels
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 #ifndef KOKKOS_TEUCHOS_COMM_ADAPTERS_HPP
44 #define KOKKOS_TEUCHOS_COMM_ADAPTERS_HPP
45 
46 #include <TeuchosKokkosComm_config.h>
47 #include <Teuchos_CommHelpers.hpp>
48 #include <Kokkos_Core.hpp>
49 #include <KokkosCompat_View.hpp>
50 
51 /// \file Kokkos_TeuchosCommAdapters.hpp
52 /// \brief Adapters for Teuchos::Comm functions for Kokkos:View.
53 ///
54 /// Currently these just pass the Kokkos::View pointer along to the existing
55 /// Teuchos::Comm functions, but in the future could be more adapted
56 /// implementations.
57 ///
58 /// Not all comm functions have been overloaded.
59 
60 namespace Teuchos {
61 
62 //! Variant of send() that takes a tag (and restores the correct order of arguments).
63 template<typename Ordinal, class ViewType>
64 typename std::enable_if<(Kokkos::Impl::is_view<ViewType>::value)>::type
send(const ViewType & sendBuffer,const Ordinal count,const int destRank,const int tag,const Comm<Ordinal> & comm)65 send (const ViewType& sendBuffer,
66       const Ordinal count,
67       const int destRank,
68       const int tag,
69       const Comm<Ordinal>& comm)
70 {
71   send(sendBuffer.data(), count, destRank, tag, comm);
72 }
73 
74 //! Variant of ssend() that takes a tag (and restores the correct order of arguments).
75 template<typename Ordinal, class ViewType>
76 typename std::enable_if<(Kokkos::Impl::is_view<ViewType>::value)>::type
ssend(const ViewType & sendBuffer,const Ordinal count,const int destRank,const int tag,const Comm<Ordinal> & comm)77 ssend (const ViewType& sendBuffer,
78        const Ordinal count,
79        const int destRank,
80        const int tag,
81        const Comm<Ordinal>& comm)
82 {
83   ssend(sendBuffer.data(), count, destRank, tag, comm);
84 }
85 
86 //! Variant of readySend() that accepts a message tag.
87 template<typename Ordinal, class ViewType>
88 typename std::enable_if<(Kokkos::Impl::is_view<ViewType>::value)>::type
readySend(const ViewType & sendBuffer,const Ordinal count,const int destRank,const int tag,const Comm<Ordinal> & comm)89 readySend (const ViewType& sendBuffer,
90            const Ordinal count,
91            const int destRank,
92            const int tag,
93            const Comm<Ordinal>& comm)
94 {
95   readySend(sendBuffer.data(), count, destRank, tag, comm);
96 }
97 
98 //! Variant of isend() that takes a tag (and restores the correct order of arguments).
99 template<typename Ordinal, class ViewType>
100 typename std::enable_if<(Kokkos::Impl::is_view<ViewType>::value),RCP<CommRequest<Ordinal> >>::type
isend(const ViewType & sendBuffer,const int destRank,const int tag,const Comm<Ordinal> & comm)101 isend (const ViewType& sendBuffer,
102        const int destRank,
103        const int tag,
104        const Comm<Ordinal>& comm)
105 {
106   using Kokkos::Compat::persistingView;
107   // See Issue #1454: https://github.com/trilinos/Trilinos/issues/1454
108   typename ViewType::const_type sendBuffer_const = sendBuffer;
109   return isend (persistingView (sendBuffer_const), destRank, tag, comm);
110 }
111 
112 //! Variant of ireceive that takes a tag argument (and restores the correct order of arguments).
113 template<typename Ordinal, class ViewType>
114 typename std::enable_if<(Kokkos::Impl::is_view<ViewType>::value),RCP<CommRequest<Ordinal> >>::type
ireceive(const ViewType & recvBuffer,const int sourceRank,const int tag,const Comm<Ordinal> & comm)115 ireceive (const ViewType& recvBuffer,
116           const int sourceRank,
117           const int tag,
118           const Comm<Ordinal>& comm)
119 {
120   using Kokkos::Compat::persistingView;
121   return ireceive(persistingView(recvBuffer), sourceRank, tag, comm);
122 }
123 
124 
125 template<typename Ordinal, typename SendViewType, typename RecvViewType>
126 typename std::enable_if<(Kokkos::Impl::is_view<SendViewType>::value && Kokkos::Impl::is_view<RecvViewType>::value)>::type
reduceAll(const SendViewType & sendBuf,const RecvViewType & recvBuf,const EReductionType reductionType,const Comm<Ordinal> & comm)127 reduceAll (const SendViewType& sendBuf,
128            const RecvViewType& recvBuf,
129            const EReductionType reductionType,
130            const Comm<Ordinal>& comm)
131 {
132   // We can't use the array of intrinsic scalar type
133   // ((non_)const_array_intrinsic_type) here, because we're doing a
134   // reduction.  That means we need to compute with the actual value
135   // type.
136   typedef typename SendViewType::value_type send_value_type;
137   typedef typename RecvViewType::value_type recv_value_type;
138 
139   const bool typesDiffer =
140     ! std::is_same<send_value_type, recv_value_type>::value;
141   TEUCHOS_TEST_FOR_EXCEPTION(
142     typesDiffer, std::invalid_argument, "Teuchos::reduceAll: Send and receive "
143     "Views contain data of different types.");
144   TEUCHOS_TEST_FOR_EXCEPTION(
145     SendViewType::rank > 1 || RecvViewType::rank > 1, std::invalid_argument,
146     "Teuchos::reduceAll: Both send and receive Views must have rank 1.  "
147     "The send View's rank is " << SendViewType::rank << " and the receive "
148     "View's rank is " << RecvViewType::rank << ".");
149   TEUCHOS_TEST_FOR_EXCEPTION(
150     sendBuf.extent (0) != recvBuf.extent (0), std::invalid_argument,
151     "Send and receive buffer lengths do not match.  sendBuf.extent(0) = "
152     << sendBuf.extent (0) << " != recvBuf.extent(0) = "
153     << recvBuf.extent (0) << ".");
154 
155   // mfh 04 Nov 2014: Don't let Teuchos::SerialComm do a deep copy;
156   // that always happens on the host, since SerialComm doesn't know
157   // about Kokkos.
158   if (comm.getSize () == 1) {
159     Kokkos::deep_copy (recvBuf, sendBuf);
160   }
161   else {
162     const Ordinal count = static_cast<Ordinal> (sendBuf.extent (0));
163     reduceAll (comm, reductionType, count,
164                sendBuf.data (),
165                recvBuf.data ());
166   }
167 }
168 
169 template<typename Ordinal, typename Serializer,
170          class SendViewType,
171          class RecvViewType>
172 typename std::enable_if<(Kokkos::Impl::is_view<SendViewType>::value && Kokkos::Impl::is_view<RecvViewType>::value)>::type
reduceAll(const Comm<Ordinal> & comm,const Serializer & serializer,const EReductionType reductType,const Ordinal count,const SendViewType & sendBuffer,const RecvViewType & recvBuffer)173 reduceAll(const Comm<Ordinal>& comm,
174           const Serializer& serializer,
175           const EReductionType reductType,
176           const Ordinal count,
177           const SendViewType& sendBuffer,
178           const RecvViewType& recvBuffer)
179 {
180   // We can't use the array of intrinsic scalar type
181   // ((non_)const_array_intrinsic_type) here, because we're doing a
182   // reduction.  That means we need to compute with the actual value
183   // type.
184   typedef typename SendViewType::value_type send_value_type;
185   typedef typename RecvViewType::value_type recv_value_type;
186 
187   const bool typesDiffer =
188     ! std::is_same<send_value_type, recv_value_type>::value;
189   TEUCHOS_TEST_FOR_EXCEPTION(
190     typesDiffer, std::invalid_argument, "Teuchos::reduceAll: Send and receive "
191     "Views contain data of different types.");
192   TEUCHOS_TEST_FOR_EXCEPTION(
193     SendViewType::rank > 1 || RecvViewType::rank > 1, std::invalid_argument,
194     "Teuchos::reduceAll: Both send and receive Views must have rank 1.  "
195     "The send View's rank is " << SendViewType::rank << " and the receive "
196     "View's rank is " << RecvViewType::rank << ".");
197 
198   // mfh 04 Nov 2014: Don't let Teuchos::SerialComm do a deep copy;
199   // that always happens on the host, since SerialComm doesn't know
200   // about Kokkos.
201   if (comm.getSize () == 1) {
202     Kokkos::deep_copy (recvBuffer, sendBuffer);
203   }
204   else {
205     reduceAll (comm, serializer, reductType, count,
206                sendBuffer.data (),
207                recvBuffer.data ());
208   }
209 }
210 
211 template<typename Ordinal,
212          class ViewType>
213 typename std::enable_if<(Kokkos::Impl::is_view<ViewType>::value)>::type
broadcast(const Comm<Ordinal> & comm,const int rootRank,const Ordinal count,const ViewType & buffer)214 broadcast(const Comm<Ordinal>& comm,
215                const int rootRank,
216                const Ordinal count,
217                const ViewType& buffer)
218 {
219   broadcast( comm, rootRank, count, buffer.data() );
220 }
221 
222 template<typename Ordinal,
223          class ViewType,
224          typename Serializer>
225 typename std::enable_if<(Kokkos::Impl::is_view<ViewType>::value)>::type
broadcast(const Comm<Ordinal> & comm,const Serializer & serializer,const int rootRank,const Ordinal count,const ViewType & buffer)226 broadcast(const Comm<Ordinal>& comm,
227                const Serializer& serializer,
228                const int rootRank,
229                const Ordinal count,
230                const ViewType& buffer)
231 {
232   broadcast( comm, serializer, rootRank, count, buffer.data() );
233 }
234 
235 } // namespace Teuchos
236 
237 #endif // KOKKOS_TEUCHOS_COMM_ADAPTERS_HPP
238