Stokhos Package Browser (Single Doxygen Collection) Version of the Day
Loading...
Searching...
No Matches
FadMPAssembly/VectorImport.hpp
Go to the documentation of this file.
1/*
2//@HEADER
3// ************************************************************************
4//
5// Kokkos: Manycore Performance-Portable Multidimensional Arrays
6// Copyright (2012) 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 H. Carter Edwards (hcedwar@sandia.gov)
39//
40// ************************************************************************
41//@HEADER
42*/
43
44#ifndef KOKKOS_VECTORIMPORT_HPP
45#define KOKKOS_VECTORIMPORT_HPP
46
47#include <utility>
48#include <limits>
49#include <iostream>
50#include <sstream>
51#include <stdexcept>
52
53#include <Kokkos_Core.hpp>
54
55#include <Teuchos_CommHelpers.hpp>
56
57namespace Kokkos {
58namespace Example {
59
60template< class CommMessageType , class CommIdentType , class VectorType >
61class VectorImport ;
62
63} // namespace Example
64} // namespace Kokkos
65
66#if ! defined( KOKKOS_ENABLE_MPI )
67
68//----------------------------------------------------------------------------
69//----------------------------------------------------------------------------
70
71namespace Kokkos {
72namespace Example {
73
74template< class CommMessageType , class CommIdentType , class VectorType >
75struct VectorImport {
76
77 const Teuchos::RCP<const Teuchos::Comm<int> > comm ;
78 const unsigned count_owned ;
79 const unsigned count_receive ;
80
81 VectorImport( const Teuchos::RCP<const Teuchos::Comm<int> > arg_comm ,
82 const CommMessageType & ,
83 const CommMessageType & ,
84 const CommIdentType & ,
85 const unsigned arg_count_owned ,
86 const unsigned arg_count_receive )
87 : comm( arg_comm )
88 , count_owned( arg_count_owned )
89 , count_receive( arg_count_receive )
90 {}
91
92 inline
93 void operator()( const VectorType & ) const {}
94};
95
96
97} // namespace Example
98} // namespace Kokkos
99
100//----------------------------------------------------------------------------
101//----------------------------------------------------------------------------
102
103#else /* defined( KOKKOS_ENABLE_MPI ) */
104
105#include <Teuchos_DefaultMpiComm.hpp>
106
107namespace Kokkos {
108namespace Example {
109
110template< class CommMessageType , class CommIdentType , class VectorType >
111class VectorImport {
112private:
113
114 // rank == 1 or array_layout == LayoutRight
115 static_assert(
116 ( VectorType::rank == 1 ) ||
117 std::is_same< typename VectorType::array_layout , Kokkos::LayoutRight >::value,
118 "Kokkos::Example::VectorImport Assert Fail: rank != 1 or array_layout != LayoutRight" );
119
120 typedef typename VectorType::HostMirror HostVectorType ;
121 typedef typename CommMessageType::HostMirror HostCommMessageType;
122
123 enum { ReceiveInPlace =
124 std::is_same< typename VectorType::memory_space ,
125 typename HostVectorType::memory_space >::value };
126
127 const CommMessageType recv_msg ;
128 const CommMessageType send_msg ;
129 const CommIdentType send_nodeid ;
130 HostCommMessageType host_recv_msg ;
131 HostCommMessageType host_send_msg ;
132 VectorType send_buffer ;
133 HostVectorType host_send_buffer ;
134 HostVectorType host_recv_buffer ;
135 unsigned chunk ;
136
137public:
138
139 const Teuchos::RCP<const Teuchos::Comm<int> > comm ;
140 const unsigned count_owned ;
141 const unsigned count_receive ;
142
143 struct Pack {
144 typedef typename VectorType::execution_space execution_space ;
145 const CommIdentType index ;
146 const VectorType source ;
147 const VectorType buffer ;
148
149 KOKKOS_INLINE_FUNCTION
150 void operator()( const unsigned i ) const
151 { buffer( i ) = source( index(i) ); }
152
153 Pack( const CommIdentType & arg_index ,
154 const VectorType & arg_source ,
155 const VectorType & arg_buffer )
156 : index( arg_index )
157 , source( arg_source )
158 , buffer( arg_buffer )
159 {
160 Kokkos::parallel_for( index.extent(0) , *this );
161 execution_space().fence();
162 }
163 };
164
165 VectorImport( const Teuchos::RCP<const Teuchos::Comm<int> > & arg_comm ,
166 const CommMessageType & arg_recv_msg ,
167 const CommMessageType & arg_send_msg ,
168 const CommIdentType & arg_send_nodeid ,
169 const unsigned arg_count_owned ,
170 const unsigned arg_count_receive )
171 : recv_msg( arg_recv_msg )
172 , send_msg( arg_send_msg )
173 , send_nodeid( arg_send_nodeid )
174 , host_recv_msg()
175 , host_send_msg()
176 , send_buffer()
177 , host_send_buffer()
178 , host_recv_buffer()
179 , comm( arg_comm )
180 , count_owned( arg_count_owned )
181 , count_receive( arg_count_receive )
182 {
183 host_recv_msg = Kokkos::create_mirror_view( recv_msg );
184 host_send_msg = Kokkos::create_mirror_view( send_msg );
185 Kokkos::deep_copy( host_recv_msg , recv_msg );
186 Kokkos::deep_copy( host_send_msg , send_msg );
187 if ( ! ReceiveInPlace ) {
188 host_recv_buffer = HostVectorType("recv_buffer",count_receive);
189 }
190
191 unsigned send_count = 0 ;
192 for ( unsigned i = 0 ; i < send_msg.extent(0) ; ++i ) { send_count += host_send_msg(i,1); }
193 send_buffer = VectorType("send_buffer",send_count);
194 host_send_buffer = Kokkos::create_mirror_view( send_buffer );
195 }
196
197 inline
198 void operator()( const VectorType & v ) const
199 {
200 typedef typename VectorType::value_type scalar_type ;
201 typedef typename HostVectorType::value_type host_scalar_type ;
202
203 const Teuchos::MpiComm<int> & teuchos_mpi_comm = dynamic_cast< const Teuchos::MpiComm<int> & >( *comm );
204
205 MPI_Comm mpi_comm = * teuchos_mpi_comm.getRawMpiComm();
206
207 const int mpi_tag = 42 ;
208 const unsigned chunk = v.extent(1);
209
210 // Subvector for receives
211 const std::pair<unsigned,unsigned> recv_range( count_owned , count_owned + count_receive );
212 const VectorType recv_vector = Kokkos::subview( v , recv_range );
213
214 std::vector< MPI_Request > recv_request( recv_msg.extent(0) , MPI_REQUEST_NULL );
215
216 // Post receives
217 if (ReceiveInPlace) {
218 scalar_type * ptr = recv_vector.data();
219
220 for ( size_t i = 0 ; i < recv_msg.extent(0) ; ++i ) {
221 const int proc = host_recv_msg(i,0);
222 const int count = host_recv_msg(i,1) * chunk ;
223
224 MPI_Irecv( ptr , count * sizeof(scalar_type) , MPI_BYTE ,
225 proc , mpi_tag , mpi_comm , & recv_request[i] );
226
227 ptr += count ;
228 }
229 }
230 else {
231 host_scalar_type * ptr = host_recv_buffer.data();
232
233 for ( size_t i = 0 ; i < recv_msg.extent(0) ; ++i ) {
234 const int proc = host_recv_msg(i,0);
235 const int count = host_recv_msg(i,1) * chunk ;
236
237 MPI_Irecv( ptr , count * sizeof(host_scalar_type) , MPI_BYTE ,
238 proc , mpi_tag , mpi_comm , & recv_request[i] );
239
240 ptr += count ;
241 }
242
243 }
244
245 MPI_Barrier( mpi_comm );
246
247 { // Pack and send
248 const Pack pack( send_nodeid , v , send_buffer );
249
250 Kokkos::deep_copy( host_send_buffer , send_buffer );
251
252 host_scalar_type * ptr = host_send_buffer.data();
253
254 for ( size_t i = 0 ; i < send_msg.extent(0) ; ++i ) {
255 const int proc = host_send_msg(i,0);
256 const int count = host_send_msg(i,1) * chunk ;
257
258 // MPI_Ssend blocks until
259 // (1) a receive is matched for the message and
260 // (2) the send buffer can be re-used.
261 //
262 // It is suggested that MPI_Ssend will have the best performance:
263 // http://www.mcs.anl.gov/research/projects/mpi/sendmode.html .
264
265 MPI_Ssend( ptr ,
266 count * sizeof(host_scalar_type) , MPI_BYTE ,
267 proc , mpi_tag , mpi_comm );
268
269 ptr += count ;
270 }
271 }
272
273 // Wait for receives and verify:
274
275 for ( size_t i = 0 ; i < recv_msg.extent(0) ; ++i ) {
276 MPI_Status recv_status ;
277 int recv_which = 0 ;
278 int recv_size = 0 ;
279
280 MPI_Waitany( recv_msg.extent(0) , & recv_request[0] , & recv_which , & recv_status );
281
282 const int recv_proc = recv_status.MPI_SOURCE ;
283
284 MPI_Get_count( & recv_status , MPI_BYTE , & recv_size );
285
286 // Verify message properly received:
287
288 const int expected_proc = host_recv_msg(recv_which,0);
289 const int expected_size = host_recv_msg(recv_which,1) * chunk * sizeof(scalar_type);
290
291 if ( ( expected_proc != recv_proc ) ||
292 ( expected_size != recv_size ) ) {
293
294 int local_rank = 0 ;
295
296 MPI_Comm_rank( mpi_comm , & local_rank );
297
298 std::ostringstream msg ;
299 msg << "VectorImport error:"
300 << " P" << local_rank
301 << " received from P" << recv_proc
302 << " size " << recv_size
303 << " expected " << expected_size
304 << " from P" << expected_proc ;
305 throw std::runtime_error( msg.str() );
306 }
307 }
308
309 // Copy received data to device memory.
310
311 if ( ! ReceiveInPlace ) { Kokkos::deep_copy( recv_vector , host_recv_buffer ); }
312 }
313};
314
315/*
316template< class CommMessageType , class CommIdentType ,
317 class S, class L, class D, class M >
318class VectorImport< CommMessageType, CommIdentType,
319 Kokkos::View<S,L,D,M,Kokkos::Impl::ViewMPVectorContiguous> >
320{
321public:
322
323 typedef Kokkos::Impl::ViewMPVectorContiguous Specialize;
324 typedef Kokkos::View<S,L,D,M,Specialize> VectorType;
325
326private:
327
328 typedef typename VectorType::flat_array_type FlatVectorType;
329 typedef VectorImport<CommMessageType, CommIdentType, FlatVectorType> FlatVectorImportType;
330
331 FlatVectorImportType flat_import;
332
333public:
334
335 VectorImport( const Teuchos::RCP<const Teuchos::Comm<int> > & arg_comm ,
336 const CommMessageType & arg_recv_msg ,
337 const CommMessageType & arg_send_msg ,
338 const CommIdentType & arg_send_nodeid ,
339 const unsigned arg_count_owned ,
340 const unsigned arg_count_receive ) :
341 flat_import( arg_comm,
342 arg_recv_msg,
343 arg_send_msg,
344 arg_send_nodeid,
345 arg_count_owned,
346 arg_count_receive ) {}
347
348 inline void operator()( const VectorType & v ) const
349 {
350 FlatVectorType flat_v = v;
351 flat_import(flat_v);
352 }
353
354};
355*/
356
357} // namespace Example
358} // namespace Kokkos
359
360#endif
361
362//----------------------------------------------------------------------------
363
364#endif /* #ifndef KOKKOS_VECTORIMPORT_HPP */
Kokkos::DefaultExecutionSpace execution_space
void operator()(const VectorType &) const
const Teuchos::RCP< const Teuchos::Comm< int > > comm
VectorImport(const Teuchos::RCP< const Teuchos::Comm< int > > arg_comm, const CommMessageType &, const CommMessageType &, const CommIdentType &, const unsigned arg_count_owned, const unsigned arg_count_receive)
void deep_copy(const Stokhos::CrsMatrix< ValueType, DstDevice, Layout > &dst, const Stokhos::CrsMatrix< ValueType, SrcDevice, Layout > &src)
Stokhos::CrsMatrix< ValueType, Device, Layout >::HostMirror create_mirror_view(const Stokhos::CrsMatrix< ValueType, Device, Layout > &A)