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