Discontinuous Galerkin Library
#include "dg/algorithm.h"
Loading...
Searching...
No Matches
mpi_gather_kron.h
Go to the documentation of this file.
1#pragma once
2
3#include <cassert>
4#include <thrust/host_vector.h>
5
6#include "exceptions.h"
7#include "config.h"
8#include "mpi_datatype.h"
9#include "tensor_traits.h"
10#include "memory.h"
11#include "mpi_gather.h"
12#include "mpi_cart.h" // for MPI_Cart functions
13
14namespace dg
15{
17namespace detail
18{
19// Gather into internal buffer and provide pointers from Contiguous Gather without self-messages
20// i.e. this class is in charge of handling pointers
21template<template< typename> typename Vector>
22struct MPIContiguousKroneckerGather
23{
24 MPIContiguousKroneckerGather( MPI_Comm comm = MPI_COMM_NULL) : m_mpi_gather(comm){ }
25 MPIContiguousKroneckerGather(
26 const std::map<int, thrust::host_vector<int>>& recvIdx, // 1d block index in units of chunk size
27 unsigned chunk_size,
28 MPI_Comm comm_1d)
29 : m_recvIdx(recvIdx), m_chunk_size(chunk_size)
30 {
31 int ndims;
32 mpi_cartdim_get( comm_1d, &ndims);
33 assert( ndims == 1);
34 int rank;
35 MPI_Comm_rank( comm_1d, &rank);
36 static_assert( dg::is_vector_v<Vector<double>, SharedVectorTag>,
37 "Only Shared vectors allowed");
38 auto recvChunks = detail::MPIContiguousGather::make_chunks(
39 recvIdx, chunk_size);
40 m_mpi_gather = dg::detail::MPIContiguousGather( recvChunks, comm_1d);
41 m_buffer_size = m_mpi_gather.buffer_size(false);
42 }
43 template< template<class> class OtherVector>
44 friend struct MPIContiguousKroneckerGather; // enable copy
45
46 template< template<typename > typename OtherVector>
47 MPIContiguousKroneckerGather( const MPIContiguousKroneckerGather<OtherVector>& src)
48 : m_mpi_gather( src.m_mpi_gather),
49 m_recvIdx(src.m_recvIdx),
50 m_chunk_size(src.m_chunk_size),
51 m_buffer_size(src.m_buffer_size)
52 {
53 }
54
55 MPI_Comm communicator() const{return m_mpi_gather.communicator();}
56 // Number of pointers in receive buffer is number of indices in m_recvIdx
57 unsigned buffer_size() const { return detail::flatten_map( m_recvIdx).size(); }
58 unsigned chunk_size() const { return m_chunk_size; }
59 bool isCommunicating() const{ return m_mpi_gather.isCommunicating(); }
60
61 template<class ContainerType>
62 void global_gather_init( const ContainerType& gatherFrom) const
63 {
65 m_buffer.template set<value_type>( m_buffer_size);
66 auto& buffer = m_buffer.template get<value_type>();
67 m_mpi_gather.global_gather_init( gatherFrom, buffer, false);
68 }
69 template<class ContainerType>
70 void global_gather_wait( const ContainerType& gatherFrom,
71 Vector<const dg::get_value_type<ContainerType>*>& buffer_ptrs) const
72 {
74 auto& buffer = m_buffer.template get<value_type>();
75 m_mpi_gather.global_gather_wait( buffer);
76
77 int rank = 0;
78 MPI_Comm_rank( communicator(), &rank);
79 unsigned start = 0, buffer_start = 0;
80 for( auto& idx : m_recvIdx)
81 for( unsigned u=0; u<idx.second.size(); u++)
82 {
83 if( rank != idx.first)
84 {
85 buffer_ptrs[start] = thrust::raw_pointer_cast(
86 buffer.data()) + buffer_start*m_chunk_size;
87 buffer_start ++;
88 }
89 else
90 buffer_ptrs[start] = thrust::raw_pointer_cast(
91 gatherFrom.data()) + idx.second[u]*m_chunk_size;
92 start++;
93 }
94
95 }
96 private:
97 dg::detail::MPIContiguousGather m_mpi_gather;
98 std::map<int,thrust::host_vector<int>> m_recvIdx;
99 unsigned m_chunk_size = 0;
100 unsigned m_buffer_size = 0;
101 mutable detail::AnyVector<Vector> m_buffer;
102};
103}//namespace detail
105
107
143template<template< typename> typename Vector>
145{
147 MPIKroneckerGather( MPI_Comm comm = MPI_COMM_NULL) : m_mpi_gather(comm){ }
165 MPIKroneckerGather( unsigned left_size,
166 const std::map<int, thrust::host_vector<int>>& recvIdx,
167 unsigned n,
168 unsigned num_cols,
169 unsigned right_size,
170 MPI_Comm comm_1d)
171 {
172 m_contiguous = (left_size==1);
173 // If not contiguous data we need to make it contiguous (gather into store)
174 if( not m_contiguous)
175 {
176 auto sendIdx = mpi_permute( recvIdx, comm_1d);
177 // In that case only gather unique messages into send store
178 detail::Unique<int> uni = detail::find_unique_order_preserving(
179 detail::flatten_map( sendIdx));
180 auto uni_sendIdx = detail::make_map_t<thrust::host_vector<int>>(
181 detail::combine_gather( uni.gather1, uni.gather2),
182 detail::get_size_map( sendIdx)); // now sendIdx goes into unique messages
183 // bootstrap communication pattern back to recvIdx
184 // (so that recvIdx has index into same store)
185 auto uni_recvIdx = dg::mpi_permute ( uni_sendIdx, comm_1d);
186 m_mpi_gather = detail::MPIContiguousKroneckerGather<Vector>(
187 uni_recvIdx, n*left_size*right_size, comm_1d);
188 // everything becomes a z - derivative ...
189 // we gather all unique indices contiguously into send buffer
190 // uni.unique == unique local indices into gatherFrom
191 thrust::host_vector<int> g2( uni.unique.size()*n*left_size*
192 right_size);
193 for( unsigned l=0; l<uni.unique.size(); l++)
194 for( unsigned j=0; j<n; j++)
195 for( unsigned i=0; i<left_size; i++)
196 for( unsigned k=0; k<right_size; k++)
197 g2[((l*n+j)*left_size+i)*right_size + k] =
198 ((i*num_cols + uni.unique[l])*n + j)*right_size + k;
199 m_g2 = g2;
200 }
201 else
202 m_mpi_gather = detail::MPIContiguousKroneckerGather<Vector>(
203 recvIdx, n*left_size*right_size, comm_1d);
204 }
205
207 template< template<class> class OtherVector>
208 friend struct MPIKroneckerGather;
209
211 template< template<typename > typename OtherVector>
213 : m_contiguous( src.m_contiguous),
214 m_g2( src.m_g2),
215 m_mpi_gather( src.m_mpi_gather)
216 {
217 }
218
220 MPI_Comm communicator() const{return m_mpi_gather.communicator();}
223 unsigned buffer_size() const { return m_mpi_gather.buffer_size(); }
225 unsigned chunk_size() const { return m_mpi_gather.chunk_size(); }
227 bool isCommunicating() const{ return m_mpi_gather.isCommunicating(); }
228
242 template<class ContainerType>
243 void global_gather_init( const ContainerType& gatherFrom) const
244 {
246 if( not m_contiguous)
247 {
248 m_store.template set<value_type>( m_g2.size());
249 auto& store = m_store.template get<value_type>();
250 thrust::gather( m_g2.begin(), m_g2.end(), gatherFrom.begin(),
251 store.begin());
252 m_mpi_gather.global_gather_init( store);
253 }
254 else
255 m_mpi_gather.global_gather_init( gatherFrom);
256 }
269 template<class ContainerType>
270 void global_gather_wait( const ContainerType& gatherFrom,
271 Vector<const dg::get_value_type<ContainerType>*>& buffer_ptrs) const
272 {
273 if( not m_contiguous)
274 {
276 auto& store = m_store.template get<value_type>();
277 m_mpi_gather.global_gather_wait( store, buffer_ptrs);
278 }
279 else
280 m_mpi_gather.global_gather_wait( gatherFrom, buffer_ptrs);
281
282 }
283 private:
284 bool m_contiguous=false;
285 Vector<int> m_g2;
286 dg::detail::MPIContiguousKroneckerGather<Vector> m_mpi_gather;
287 mutable detail::AnyVector<Vector> m_store;
288};
289} // namespace dg
Error classes or the dg library.
constexpr bool is_vector_v
Utility typedef.
Definition predicate.h:75
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
Definition tensor_traits.h:45
std::map< int, MessageType > mpi_permute(const std::map< int, MessageType > &messages, MPI_Comm comm)
Exchange messages between processes in a communicator.
Definition mpi_permutation.h:90
const double n
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
Communicator for asynchronous communication of MPISparseBlockMat.
Definition mpi_gather_kron.h:145
void global_gather_init(const ContainerType &gatherFrom) const
. Globally (across processes) asynchronously gather data into a buffer
Definition mpi_gather_kron.h:243
bool isCommunicating() const
True if the gather/scatter operation involves actual MPI communication.
Definition mpi_gather_kron.h:227
MPI_Comm communicator() const
The internal MPI communicator used.
Definition mpi_gather_kron.h:220
void global_gather_wait(const ContainerType &gatherFrom, Vector< const dg::get_value_type< ContainerType > * > &buffer_ptrs) const
Wait for asynchronous communication to finish and gather received data into buffer and return pointer...
Definition mpi_gather_kron.h:270
MPIKroneckerGather(unsigned left_size, const std::map< int, thrust::host_vector< int > > &recvIdx, unsigned n, unsigned num_cols, unsigned right_size, MPI_Comm comm_1d)
Construct from communication pattern.
Definition mpi_gather_kron.h:165
MPIKroneckerGather(const MPIKroneckerGather< OtherVector > &src)
Construct from other execution policy.
Definition mpi_gather_kron.h:212
unsigned chunk_size() const
n*left_size*right_size
Definition mpi_gather_kron.h:225
MPIKroneckerGather(MPI_Comm comm=MPI_COMM_NULL)
no communication
Definition mpi_gather_kron.h:147
unsigned buffer_size() const
Number of pointers in receive buffer equals number of indices in recvIdx.
Definition mpi_gather_kron.h:223
double value_type